Beispiel #1
0
    def start(self):
        '''Start the netbean server and vim client.'''
        dbg('...')
        self.server = NetbeanServer()
        self.server.startServer()
        self.server.addEventHandler(self.eventReceived)

        self.vimLauncher = VimLauncher(vimExec=self.vimExec,
                                       netbeanPort=self.server.netbeanPort,
                                       netbeanPwd=self.server.netbeanPwd)
        self.vimLauncher.startVim()

        self.server.waitForConnection()
        self.server.waitStartupDone()
        dbg('done')
Beispiel #2
0
    def start( self ):
        '''Start the netbean server and vim client.'''
        dbg( '...' )    
        self.server = NetbeanServer()
        self.server.startServer()
        self.server.addEventHandler( self.eventReceived )
    
        self.vimLauncher = VimLauncher( vimExec=self.vimExec, netbeanPort=self.server.netbeanPort, netbeanPwd=self.server.netbeanPwd )
        self.vimLauncher.startVim()

        self.server.waitForConnection()
        self.server.waitStartupDone()
        dbg( 'done' )    
Beispiel #3
0
    def start(self, sock_id=None):
        """Start the netbean server and vim client."""
        dbg("...")
        self.server = NetbeanServer()
        self.server.startServer()
        self.server.addEventHandler(self.eventReceived)

        self.vimLauncher = VimLauncher(
            vimExec=self.vimExec,
            netbeanPort=self.server.netbeanPort,
            netbeanPwd=self.server.netbeanPwd,
            sock_id=sock_id,
        )
        self.vimLauncher.startVim()

        self.server.waitForConnection()
        self.server.waitStartupDone()
        dbg("done")
Beispiel #4
0
class VimWrapper:
    '''The frontend for wrapping vim. It will launch vim and initiate the netbean communication.
    
    It provides easy-to-use members to interact with vim, be notified about vim events, ...
    '''
    def __init__(self, **kwargs):
        '''Init the vim wrapper.

        Keyword arguments: 
        - vimExec: path the vim executable file
        '''
        self.server = None
        self.vimLauncher = None
        self.vimExec = kwargs['vimExec']
        self.bufInfo = BufferMgr()
        self.ignoreNextOpenFile = 0

    def start(self):
        '''Start the netbean server and vim client.'''
        dbg('...')
        self.server = NetbeanServer()
        self.server.startServer()
        self.server.addEventHandler(self.eventReceived)

        self.vimLauncher = VimLauncher(vimExec=self.vimExec,
                                       netbeanPort=self.server.netbeanPort,
                                       netbeanPwd=self.server.netbeanPwd)
        self.vimLauncher.startVim()

        self.server.waitForConnection()
        self.server.waitStartupDone()
        dbg('done')

    def close(self):
        '''Close vim and the netbean server.'''
        if self.server and self.server.isConnected():
            self.server.sendDisconnect()
            self.server.closeServer()
        self.bufInfo.clear()

    def processVimEvents(self, nbEvents=-1):
        self.server.processVimEvents(nbEvents)

    #######################################################################
    #                               Vim Access Functions
    #######################################################################

    # For all the functions here, the following applies:
    # - line numbering starts at 1.
    # - column starts at 0 and is byte based. A tab for example counts for one column increment a
    # single character with double bytes will count for two columns.
    # - offset starts at 0 and is byte based. A double-byte char will bring offset to two.

    ##########  Buffer info, properties

    def _getCursor(self):
        '''Return the current (bufId, cursorLine, cursorCol, cursorFileOffset ).'''
        s = self.server.call(0, 'getCursor', 'NUM NUM NUM NUM')
        return s

    def getBufId(self):
        return self._getCursor()[0]

    def getCursorLine(self):
        return self._getCursor()[1]

    def getCursorCol(self):
        return self._getCursor()[2]

    def getCursorLineCol(self):
        return self._getCursor()[1:3]

    def getCursorOffset(self):
        return self._getCursor()[3]

    def getLength(self, bufId):
        '''Length of the content of the current buffer.'''
        return self.server.call(bufId, 'getLength', 'NUM')[0]

    def setModified(self, bufId, modified):
        '''Mark the buffer as modified.'''
        return self.server.sendCmd(bufId, 'setModified', bool(modified))

    def isBufferModified(self, bufId):
        '''Return True if the buffer bufId is modified.'''
        ret = self.server.call(bufId, 'getModified', 'NUM')[0]
        return ret == 1

    def numberBufferModified(self):
        '''Return the number of currently modified buffer. When this number is 0
        it is safe to tell vim to exit.'''
        return self.server.call(0, 'getModified', 'NUM')

    def setCurrentBuffer(self, bufId):
        '''Set bufId as the current buffer.'''
        self.server.sendCmd(bufId, 'setVisible', True)

    def setCurrentBufferByPath(self, path):
        '''Set path as the current buffer.'''
        bufId = self.bufInfo.bufIdOfPath(path)
        self.server.sendCmd(bufId, 'setVisible', True)

    def setCurrentBufferOffset(self, bufId, offset):
        '''Make bufId the current buffer and position the cursor at offset.'''
        self.server.sendCmd(bufId, 'setDot', offset)

    def setCurrentBufferLineCol(self, bufId, line, col):
        '''Make bufId the current buffer and position the cursor at (line,col)'''
        self.server.sendCmd(bufId, 'setDot', (line, col))

    def setBufferReadonly(self, bufId):
        '''Set the bufId as readOnly.'''
        self.server.sendCmd(bufId, 'setReadOnly')

    ######### Text manipulation

    def text(self, bufId):
        '''Return the content of the buffer bufId.'''
        return self.server.call(bufId, 'getText', 'STR')[0]

    def insertText(self, bufId, offset, text):
        '''Make bufId the current buffer and insert text at the offset.

        Warning, this will not change the isBufferModified status. The status
        must be changed explicitely.

        Return: None on success, message on failure.'''
        return self.server.call(bufId, 'insert', 'OPTMSG', offset, text)[0]

    def removeText(self, bufId, offset, length):
        '''Delete text starting from offset, up to length. Make bufId the current buffer.

        Warning, this will not change the isBufferModified status. The status
        must be changed explicitely.

        Return None upon success, or an error message upon failure.
        '''
        return self.server.call(bufId, 'remove', 'OPTMSG', offset, length)[0]

    ########## Buffer manipulation

    def openFile(self, path):
        '''Open the specified file.

        Return the bufId of the new buffer.
        '''
        bufId = self.bufInfo.createBufId()
        self.ignoreNextOpenFile += 1
        self.server.sendCmd(bufId, 'editFile', path)
        self.processVimEvents()
        self.server.sendCmd(bufId, 'setFullName', path)
        self.server.sendCmd(bufId, 'initDone')
        self.bufInfo.addBuffer(bufId, path)
        return bufId

    def createBuffer(self, path):
        '''Create a new buffer in Vim with the bufId specified. 

        Return the bufId of the new buffer.
        '''
        bufId = self.bufInfo.createBufId()

        if 1:
            self.server.sendCmd(bufId, 'create')
            self.server.sendCmd(bufId, 'setTitle', path)
            self.server.sendCmd(bufId, 'setFullName', path)
            self.server.sendCmd(bufId, 'initDone')
        else:
            # optional alternative implemtation
            self.server.sendCmd(bufId, 'editFile', path)
            self.server.sendCmd(bufId, 'setFullpath', path)
            self.server.sendCmd(bufId, 'initDone')

        self.bufInfo.addBuffer(bufId, path)
        # fetch the fileOpened event
        self.processVimEvents()

        return bufId

    def closeBuffer(self, bufId):
        '''Close the current buffer, assigns the next available buffer as current buffer.

        If this is the last buffer, we are without current buffer.

        No return value.
        '''
        curBufId = self.getBufId()
        nextBufId = self.bufInfo.nextBuffer(bufId)
        self.bufInfo.rmBufferByBufId(bufId)
        self.server.sendCmd(bufId, 'close')
        if curBufId == bufId:
            self.setCurrentBuffer(nextBufId)

    def assignBufId(self, bufId, path):
        '''Assign the bufId to the path, for recently opened buffers.'''
        self.server.sendCmd(bufId, 'putBufferNumber', path)

    def saveBuffer(self, bufId):
        '''Save the buffer and display message saved.'''
        self.server.sendCmd(bufId, 'save')
        self.server.sendCmd(bufId, 'saveDone')  # display 'buffer saved' in vim

    def saveAndExit(self):
        '''Save all the modified buffers and tell vim to exit.

        Return:
        -  0: success vim closes the connection.
        -  n > 0: user has canceled the operation, n buffer still contain modifications.
        '''
        return self.server.call(0, 'saveAndExit', 'OPTNUM')

    def addEventHandler(self, hlr):
        '''Add an event handler to receive buffer created/deleted events.'''
        self.bufInfo.addEventHandler(hlr)

    ########### Keys

    def setSpecialKeys(self, keys):
        '''Set netbeans hotkeys.'''
        self.server.sendCmd(0, 'specialKeys', keys)

    def sendKeys(self, keys):
        '''Send the key string keys to vim.'''
        self.vimLauncher.sendKeys(keys)

    def sendKeysNormalMode(self, keys):
        '''Send the key string keys to vim, but ensure that Vim is normal mode previously.'''
        self.vimLauncher.sendKeysNormalMode(keys)

    ########### Other

    def raiseVim(self):
        '''Raise the vim window to ght foreground.'''
        self.server.sendCmd(0, 'raise')

    ########### Events

    def eventReceived(self, bufId, name, args):
        '''Called when a vim event is received.'''
        dbg('%d %s \'%s\'' % (bufId, name, args))

        f = self.eventMap.get(name, VimWrapper.eventIgnore)
        f(self, bufId, name, args)

    def eventIgnore(self, bufId, name, args):
        '''Ignore the event!'''
        pass

    def eventFileOpened(self, bufId, name, args):
        if bufId != 0:
            # file is already associated
            return

        if bufId == 0 and self.ignoreNextOpenFile > 0:
            dbg('Ignoring event because of self.ignoreNextOpenFile = %d',
                self.ignoreNextOpenFile)
            self.ignoreNextOpenFile -= 1
            return

        # need to associate the file
        path, opened, modified = parseNetbeanArgs(args, 'STR BOOL BOOL')
        dbg('path="%s"', path)
        bufId = self.bufInfo.createBufId()
        self.assignBufId(bufId, path)
        self.bufInfo.addBuffer(bufId, path)

    def eventFileClosed(self, bufId, name, args):
        dbg('%d %s \'%s\'' % (bufId, name, args))
        self.bufInfo.rmBufferByBufId(bufId)

    def eventKeyAtPos(self, bufId, name, args):
        '''Triggered when a netbeans hotkey is pressed along with <Pause>'''
        dbg('%d %s \'%s\'' % (bufId, name, args))
        key, offset, (line, col) = parseNetbeanArgs(args, 'STR NUM POS')
        self.bufInfo.notifyEvent('Hotkey', (bufId, key, offset, (line, col)))

    eventMap = {
        'fileOpened': eventFileOpened,
        'killed': eventFileClosed,
        'newDotAndMark': eventIgnore,
        'keyCommand': eventIgnore,
        'keyAtPos': eventKeyAtPos,
    }
Beispiel #5
0
class VimWrapper:
    """The frontend for wrapping vim. It will launch vim and initiate the netbean communication.
    
    It provides easy-to-use members to interact with vim, be notified about vim events, ...
    """

    def __init__(self, **kwargs):
        """Init the vim wrapper.

        Keyword arguments: 
        - vimExec: path the vim executable file
        """
        self.server = None
        self.vimLauncher = None
        self.vimExec = kwargs["vimExec"]
        self.bufInfo = BufferMgr()
        self.ignoreNextOpenFile = 0

    def start(self, sock_id=None):
        """Start the netbean server and vim client."""
        dbg("...")
        self.server = NetbeanServer()
        self.server.startServer()
        self.server.addEventHandler(self.eventReceived)

        self.vimLauncher = VimLauncher(
            vimExec=self.vimExec,
            netbeanPort=self.server.netbeanPort,
            netbeanPwd=self.server.netbeanPwd,
            sock_id=sock_id,
        )
        self.vimLauncher.startVim()

        self.server.waitForConnection()
        self.server.waitStartupDone()
        dbg("done")

    def close(self):
        """Close vim and the netbean server."""
        if self.server and self.server.isConnected():
            self.server.sendDisconnect()
            self.server.closeServer()
        self.bufInfo.clear()

    def processVimEvents(self, nbEvents=-1):
        self.server.processVimEvents(nbEvents)

    #######################################################################
    #                               Vim Access Functions
    #######################################################################

    # For all the functions here, the following applies:
    # - line numbering starts at 1.
    # - column starts at 0 and is byte based. A tab for example counts for one column increment a
    # single character with double bytes will count for two columns.
    # - offset starts at 0 and is byte based. A double-byte char will bring offset to two.

    ##########  Buffer info, properties

    def _getCursor(self):
        """Return the current (bufId, cursorLine, cursorCol, cursorFileOffset )."""
        s = self.server.call(0, "getCursor", "NUM NUM NUM NUM")
        return s

    def getBufId(self):
        return self._getCursor()[0]

    def getCursorLine(self):
        return self._getCursor()[1]

    def getCursorCol(self):
        return self._getCursor()[2]

    def getCursorLineCol(self):
        return self._getCursor()[1:3]

    def getCursorOffset(self):
        return self._getCursor()[3]

    def getLength(self, bufId):
        """Length of the content of the current buffer."""
        return self.server.call(bufId, "getLength", "NUM")[0]

    def setModified(self, bufId, modified):
        """Mark the buffer as modified."""
        return self.server.sendCmd(bufId, "setModified", bool(modified))

    def isBufferModified(self, bufId):
        """Return True if the buffer bufId is modified."""
        ret = self.server.call(bufId, "getModified", "NUM")[0]
        return ret == 1

    def numberBufferModified(self):
        """Return the number of currently modified buffer. When this number is 0
        it is safe to tell vim to exit."""
        return self.server.call(0, "getModified", "NUM")

    def setCurrentBuffer(self, bufId):
        """Set bufId as the current buffer."""
        self.server.sendCmd(bufId, "setVisible", True)

    def setCurrentBufferByPath(self, path):
        """Set path as the current buffer."""
        bufId = self.bufInfo.bufIdOfPath(path)
        self.server.sendCmd(bufId, "setVisible", True)

    def setCurrentBufferOffset(self, bufId, offset):
        """Make bufId the current buffer and position the cursor at offset."""
        self.server.sendCmd(bufId, "setDot", offset)

    def setCurrentBufferLineCol(self, bufId, line, col):
        """Make bufId the current buffer and position the cursor at (line,col)"""
        self.server.sendCmd(bufId, "setDot", (line, col))

    def setBufferReadonly(self, bufId):
        """Set the bufId as readOnly."""
        self.server.sendCmd(bufId, "setReadOnly")

    ######### Text manipulation

    def text(self, bufId):
        """Return the content of the buffer bufId."""
        return self.server.call(bufId, "getText", "STR")[0]

    def insertText(self, bufId, offset, text):
        """Make bufId the current buffer and insert text at the offset.

        Warning, this will not change the isBufferModified status. The status
        must be changed explicitely.

        Return: None on success, message on failure."""
        return self.server.call(bufId, "insert", "OPTMSG", offset, text)[0]

    def removeText(self, bufId, offset, length):
        """Delete text starting from offset, up to length. Make bufId the current buffer.

        Warning, this will not change the isBufferModified status. The status
        must be changed explicitely.

        Return None upon success, or an error message upon failure.
        """
        return self.server.call(bufId, "remove", "OPTMSG", offset, length)[0]

    ########## Buffer manipulation

    def openFile(self, path):
        """Open the specified file.

        Return the bufId of the new buffer.
        """
        bufId = self.bufInfo.createBufId()
        self.ignoreNextOpenFile += 1
        self.server.sendCmd(bufId, "editFile", path)
        self.processVimEvents()
        self.server.sendCmd(bufId, "setFullName", path)
        self.server.sendCmd(bufId, "initDone")
        self.bufInfo.addBuffer(bufId, path)
        return bufId

    def createBuffer(self, path):
        """Create a new buffer in Vim with the bufId specified. 

        Return the bufId of the new buffer.
        """
        bufId = self.bufInfo.createBufId()

        if 1:
            self.server.sendCmd(bufId, "create")
            self.server.sendCmd(bufId, "setTitle", path)
            self.server.sendCmd(bufId, "setFullName", path)
            self.server.sendCmd(bufId, "initDone")
        else:
            # optional alternative implemtation
            self.server.sendCmd(bufId, "editFile", path)
            self.server.sendCmd(bufId, "setFullpath", path)
            self.server.sendCmd(bufId, "initDone")

        self.bufInfo.addBuffer(bufId, path)
        # fetch the fileOpened event
        self.processVimEvents()

        return bufId

    def closeBuffer(self, bufId):
        """Close the current buffer, assigns the next available buffer as current buffer.

        If this is the last buffer, we are without current buffer.

        No return value.
        """
        curBufId = self.getBufId()
        nextBufId = self.bufInfo.nextBuffer(bufId)
        self.bufInfo.rmBufferByBufId(bufId)
        self.server.sendCmd(bufId, "close")
        if curBufId == bufId:
            self.setCurrentBuffer(nextBufId)

    def assignBufId(self, bufId, path):
        """Assign the bufId to the path, for recently opened buffers."""
        self.server.sendCmd(bufId, "putBufferNumber", path)

    def saveBuffer(self, bufId):
        """Save the buffer and display message saved."""
        self.server.sendCmd(bufId, "save")
        self.server.sendCmd(bufId, "saveDone")  # display 'buffer saved' in vim

    def saveAndExit(self):
        """Save all the modified buffers and tell vim to exit.

        Return:
        -  0: success vim closes the connection.
        -  n > 0: user has canceled the operation, n buffer still contain modifications.
        """
        return self.server.call(0, "saveAndExit", "OPTNUM")

    def addEventHandler(self, hlr):
        """Add an event handler to receive buffer created/deleted events."""
        self.bufInfo.addEventHandler(hlr)

    ########### Keys

    def setSpecialKeys(self, keys):
        """Set netbeans hotkeys."""
        self.server.sendCmd(0, "specialKeys", keys)

    def sendKeys(self, keys):
        """Send the key string keys to vim."""
        self.vimLauncher.sendKeys(keys)

    def sendKeysNormalMode(self, keys):
        """Send the key string keys to vim, but ensure that Vim is normal mode previously."""
        self.vimLauncher.sendKeysNormalMode(keys)

    ########### Other

    def raiseVim(self):
        """Raise the vim window to ght foreground."""
        self.server.sendCmd(0, "raise")

    ########### Events

    def eventReceived(self, bufId, name, args):
        """Called when a vim event is received."""
        dbg("%d %s '%s'" % (bufId, name, args))

        f = self.eventMap.get(name, VimWrapper.eventIgnore)
        f(self, bufId, name, args)

    def eventIgnore(self, bufId, name, args):
        """Ignore the event!"""
        pass

    def eventFileOpened(self, bufId, name, args):
        if bufId != 0:
            # file is already associated
            return

        if bufId == 0 and self.ignoreNextOpenFile > 0:
            dbg("Ignoring event because of self.ignoreNextOpenFile = %d", self.ignoreNextOpenFile)
            self.ignoreNextOpenFile -= 1
            return

        # need to associate the file
        path, opened, modified = parseNetbeanArgs(args, "STR BOOL BOOL")
        dbg('path="%s"', path)
        bufId = self.bufInfo.createBufId()
        self.assignBufId(bufId, path)
        self.bufInfo.addBuffer(bufId, path)

    def eventFileClosed(self, bufId, name, args):
        dbg("%d %s '%s'" % (bufId, name, args))
        self.bufInfo.rmBufferByBufId(bufId)

    def eventKeyAtPos(self, bufId, name, args):
        """Triggered when a netbeans hotkey is pressed along with <Pause>"""
        dbg("%d %s '%s'" % (bufId, name, args))
        key, offset, (line, col) = parseNetbeanArgs(args, "STR NUM POS")
        self.bufInfo.notifyEvent("Hotkey", (bufId, key, offset, (line, col)))

    eventMap = {
        "fileOpened": eventFileOpened,
        "killed": eventFileClosed,
        "newDotAndMark": eventIgnore,
        "keyCommand": eventIgnore,
        "keyAtPos": eventKeyAtPos,
    }