Пример #1
0
def _ask_for_CMakeLists_location_and_try_open(start_dir_to_show, cur_doc_dir):
    selected_dir = KUrlRequesterDialog.getUrl(
        start_dir_to_show
      , kate.mainInterfaceWindow().window()
      , i18nc('@title:window', '<filename>CMakeLists.txt</filename> location')
      )
    kate.kDebug('CMakeHelper: selected_dir={}'.format(selected_dir))

    if selected_dir.isEmpty():
        return                                              # User pressed 'Cancel'

    selected_dir = selected_dir.toLocalFile()               # Get selected path
    # Is it relative?
    if not os.path.isabs(selected_dir):
        # Yep, join w/ a path of the current doc
        selected_dir = os.path.abspath(os.path.join(cur_doc_dir, selected_dir))

    # Check if there CMakeLists.txt present
    cmakelists = os.path.join(selected_dir, _CMAKE_LISTS)
    if _is_there_CMakeLists(selected_dir):
        # Open it!
        _openDocumentNoCheck(QUrl.fromLocalFile(cmakelists))
    else:
        kate.ui.popup(
            i18nc('@title:window', 'Error')
          , i18nc('@info:tooltip', 'No such file <filename>%1</filename>', cmakelists)
          , 'dialog-error'
          )
Пример #2
0
def _collect_colors(document):
    '''Scan a given document and collect unique colors

        Returns a list of QColor objects.
    '''
    result = []
    # Iterate over document's lines trying to find #colors
    for l in range(0, document.lines()):
        line = document.line(l)                             # Get the current line
        start = 0                                           # Set initial position to 0 (line start)
        while start < len(line):                            # Repeat 'till the line end
            start = line.find('#', start)                   # Try to find a '#' character (start of #color)
            if start == -1:                                 # Did we found smth?
                break                                       # No! Nothing to do...
            # Try to get a word right after the '#' char
            end = start + 1
            for c in line[end:]:
                if not (c in string.hexdigits or c in string.ascii_letters):
                    break
                end += 1
            color_range = KTextEditor.Range(l, start, l, end)
            color_str = document.text(color_range)
            color = QColor(color_str)
            if color.isValid() and color not in result:
                result.append(color)
                kate.kDebug('ColorUtils: scan for #colors found {}'.format(color_str))
            start = end
    return result
Пример #3
0
def tryOpen():
    view = kate.activeView()
    assert('View expected to be valid' and view is not None)
    assert('This action supposed to select some text before' and view.selection())

    doc = view.document()
    doc_url = doc.url()
    new_url = KUrl(_try_make_url_from_text(view.selectionText()))

    kate.kDebug('Current document URI: {}'.format(repr(doc_url)))

    # 0) Make sure it is valid
    if not new_url.isValid():
        kate.ui.popup(
            i18nc('@title:window', 'Error')
          , i18nc('@info:tooltip', "Selected text doesn't looks like a valid URI")
          , 'dialog-error'
          )
        return

    # 1) Is it have some schema? and current document is not 'Untitled'...
    if new_url.isRelative() and not doc_url.isEmpty():
        # Replace filename from the doc_url w/ the current selection
        new_url = doc_url.upUrl()
        new_url.addPath(view.selectionText())

    kate.kDebug('Trying URI: {}'.format(repr(new_url)))
    # Ok, try to open it finally
    _try_open_show_error(new_url)
Пример #4
0
    def track_input(self, char, cursor):
        assert('parameter expected to be a string' and isinstance(char, str))

        #kate.kDebug('@KeySequenceTracker: input="{}"'.format(char))
        #kate.kDebug('@KeySequenceTracker: curr-pos=({},{})'.format(cursor.line(),cursor.column()))
        #if self.next_expected_pos is not None:
            #kate.kDebug('@KeySequenceTracker: next-pos=({},{})'.format(self.next_expected_pos.line(),self.next_expected_pos.column()))

        if len(char) != 1:
            self.reset()                                    # Looks like copy-n-pasted text... drop it!
        elif char == KeySequenceTracker.TRIGGER_CHAR:
            if self.next_expected_pos is not None:          # Is tracking already enabled?
                self._dispatch()                            # Yep, then this is a final char... Handle it!
                self.reset()                                # Ready for next key sequence
            else:
                kate.kDebug('@KeySequenceTracker: ---[start tracking key sequence]---')
                self.next_expected_pos = KTextEditor.Cursor(cursor.line(), cursor.column() + 1)
            self.moved = False
        elif self.next_expected_pos is not None:            # Do we record?
            # ATTENTION Ugly PyKDE do not export some vital functions!
            # Like relation operators for types (Cursor and Range for example)...
            is_equal_cursors = self.next_expected_pos.line() == cursor.line() \
              and self.next_expected_pos.column() == cursor.column()
            if is_equal_cursors:
                self.sequence += char                       # Yeah! Just collect a one more char
                self.next_expected_pos = KTextEditor.Cursor(cursor.line(), cursor.column() + 1)
            else:
                kate.kDebug('@KeySequenceTracker: ---[next-pos != cursor]---')
                self.reset()
Пример #5
0
def _is_there_CMakeLists(path):
    '''Try to find `CMakeLists.txt` in a given path'''
    kate.kDebug('CMakeHelper: checking `{}` for CMakeLists.txt'.format(path))
    assert(isinstance(path, str))
    if os.access(os.path.join(path, _CMAKE_LISTS), os.R_OK):
        return True
    return False
Пример #6
0
    def _dispatch(self):
        kate.kDebug('@KeySequenceTracker: collected key sequence "{}"'.format(self.sequence))
        view = kate.activeView()
        cursor = view.cursorPosition()
        word_range = KTextEditor.Range(
            cursor.line()
          , cursor.column() - len(self.sequence) - 2
          , cursor.line()
          , cursor.column()
          )
        document = view.document()
        assert('Sanity check' and view is not None)
        mimeType = document.mimeType()
        expansions = getExpansionsFor(mimeType)

        if not hasattr(dynamic, 'registered_handlers') or mimeType not in dynamic.registered_handlers:
            return

        assert('Sanity check' and isinstance(dynamic.registered_handlers[mimeType], list))
        for func in dynamic.registered_handlers[mimeType]:
            assert('Sanity check' and inspect.isfunction(func) and hasattr(func, 'match_regex'))
            match = func.match_regex.search(self.sequence)
            if match is not None:
                result = func(self.sequence, match)
                self._inject_expand_result(document, result, word_range, func)
                return
Пример #7
0
def _get_1st_arg_if_add_subdirectory_cmd(document, line):
    # TODO WTF? '\badd_subdirectory' doesn't match! Just wanted to
    # make sure that 'add_subdirectory' is not a part of some other word...
    match = _ADD_SUB_RE.search(document.line(line))
    if match:
        kate.kDebug('CMakeHelper: line[{}] "{}" match: {}'.format(line, document.line(line), match.groups()))
        return [subdir for subdir in match.group(1).split() if subdir != _SUBDIR_OPT][0]
    return None
Пример #8
0
 def addDir(self):
     path = KFileDialog.getExistingDirectory(
         KUrl('')
       , self
       , i18nc('@title:window', 'Select a Directory with CMake Modules')
       )
     kate.kDebug('CMakeCC: got path={}'.format(path))
     self.moduleDirs.addItem(str(path))
Пример #9
0
 def track_cursor(self, cursor):
     kate.kDebug('@KeySequenceTracker: moved to ({},{})'.format(cursor.line(),cursor.column()))
     if self.next_expected_pos is not None \
       and ( \
             self.next_expected_pos.line() != cursor.line() \
           or (self.next_expected_pos.column() + 1) != cursor.column() \
       ):
         kate.kDebug('@KeySequenceTracker: moved from ({},{})'.format(self.next_expected_pos.line(),self.next_expected_pos.column()))
         self.reset()
Пример #10
0
def createSignalAutocompleteCMake(view=None, *args, **kwargs):
    try:
        view = view or kate.activeView()
        if view:
            kate.kDebug('CMake Helper Plugin: Registering completer')
            cci = view.codeCompletionInterface()
            cci.registerCompletionModel(_cmake_completion_model)
    except:
        kate.kDebug('CMake Helper Plugin: Unable to get an active view')
Пример #11
0
def getTextBlockAroundCursor(doc, pos, upPred, downPred):
    start = _getTextBlockAroundCursor(doc, pos.line(), doc.lines(), TOWARDS_START, upPred)
    end = _getTextBlockAroundCursor(doc, pos.line(), doc.lines(), TOWARDS_END, downPred)
    if start != end:
        start += 1

    kate.kDebug(
        "getTextBlockAroundCursor[pos={},{}]: ({},{}), ({},{})".format(pos.line(), pos.column(), start, 0, end, 0)
    )
    return KTextEditor.Range(start, 0, end, 0)
Пример #12
0
 def _decorator(func):
     if not hasattr(dynamic, 'registered_handlers'):
         setattr(dynamic, 'registered_handlers', dict())
     mimeType = kate.activeDocument().mimeType()
     if mimeType not in dynamic.registered_handlers:
         dynamic.registered_handlers[mimeType] = list()
     dynamic.registered_handlers[mimeType].append(func)
     setattr(func, 'match_regex', regex)
     kate.kDebug('Set KS expander for {} to {}'.format(mimeType, func.__name__))
     return func
Пример #13
0
def destroy():
    '''Plugins that use a toolview need to delete it for reloading to work.'''
    kate.kDebug('Unloading...')
    global _cmake_completion_model
    if _cmake_completion_model:
        _cmake_completion_model = None

    global _cmake_tool_view
    if _cmake_tool_view:
        _cmake_tool_view = None
Пример #14
0
def _mergeExpansions(left, right):
    assert(isinstance(left, dict) and isinstance(right, dict))
    result = left
    for exp_key, exp_tuple in right.items():
        if exp_key not in result:
            result[exp_key] = exp_tuple
        else:
            result[exp_key] = result[exp_key]
            kate.kDebug('WARNING: Ignore duplicate expansion `{}` from {}'.format(exp_key, exp_tuple[1]))
            kate.kDebug('WARNING: First defined here {}'.format(result[exp_key][1]))
    return result
Пример #15
0
def openDocument(url):
    local_file = url.toLocalFile()
    kate.kDebug('CMakeCC: going to open the document: {}'.format(local_file))
    if os.access(local_file, os.R_OK):
        _openDocumentNoCheck(url)
    else:
        kate.ui.popup(
            i18nc('@title:window', 'Error')
          , i18nc('@info:tooltip', 'Unable to open the document: <filename>%1</filename>', local_file)
          , 'dialog-error'
          )
Пример #16
0
def jinja_environment_configurator(func):
    '''
        ATTENTION Be aware that functions marked w/ jinja_environment_configurator
        decorator should have two leading underscores in their name!
        Otherwise, they will be available as ordinal expand functions, which is
        definitely UB. This made to keep `expand` code simple...
    '''
    if not hasattr(jinja_environment_configurator, 'registered_configurators'):
        setattr(jinja_environment_configurator, 'registered_configurators', dict())
    mimeType = kate.activeDocument().mimeType()
    jinja_environment_configurator.registered_configurators[mimeType] = func
    kate.kDebug('Set jinja2 environment configurator for {} to {}'.format(mimeType, func.__name__))
    return func
Пример #17
0
 def _loadCompleters(self):
     # Load available command completers
     for directory in kate.applicationDirectories('cmake_utils/command_completers'):
         kate.kDebug('CMakeCC: directory={}'.format(directory))
         sys.path.append(directory)
         for completer in glob.glob(os.path.join(directory, '*_cc.py')):
             kate.kDebug('CMakeCC: completer={}'.format(completer))
             cc_name = os.path.basename(completer).split('.')[0]
             module = importlib.import_module(cc_name, "cmake_utils.command_completers")
             if hasattr(module, self._cc_registrar_fn_name):
                 r = getattr(module, self._cc_registrar_fn_name)
                 if isinstance(r, types.FunctionType):
                     r(self.__command_completers)
Пример #18
0
def _getJinjaEnvironment(baseDir):
    kate.kDebug('Make a templates loader for a base dir: {}'.format(baseDir))
    env = jinja2.Environment(loader=jinja2.FileSystemLoader(baseDir))

    env.filters['editable'] = _makeEditableField
    env.tests['boolean'] = _is_bool
    env.tests['integer'] = _is_int

    if hasattr(jinja_environment_configurator, 'registered_configurators'):
        mimeType = kate.activeDocument().mimeType()
        configurator = jinja_environment_configurator.registered_configurators[mimeType]
        kate.kDebug('Setup jinja2 environment for {} [{}]'.format(mimeType, configurator.__name__))
        env = configurator(env)

    return env
Пример #19
0
def _loadExpansionsFromFile(path):
    kate.kDebug('Loading expansions from {}'.format(path))
    name = os.path.basename(path).split('.')[0]
    module = imp.load_source(name, path)
    expansions = {}
    # expansions are everything that don't begin with '__' and are callable
    for name in dir(module):
        o = getattr(module, name)
        # ignore builtins. Note that it is callable.__name__ that is used
        # to set the expansion key so you are free to reset it to something
        # starting with two underscores (or more importantly, a Python
        # keyword)
        # NOTE Detect ONLY a real function!
        if not name.startswith('__') and inspect.isfunction(o):
            expansions[o.__name__] = (o, path)
            kate.kDebug('Adding expansion `{}`'.format(o.__name__))
    return expansions
Пример #20
0
def toggleDocTypeSeisitiveActions():
    view = kate.activeView()
    if view is None:
        return
    doc_type = view.document().highlightingMode()
    kate.kDebug('toggleDocTypeSeisitiveActions: doc_type={}'.format(doc_type))
    clnt = kate.getXmlGuiClient()

    if doc_type in ['C++', 'C++/Qt4', 'C']:
        clnt.stateChanged('if0_actions')
    else:
        clnt.stateChanged('if0_actions', KXMLGUIClient.StateReverse)

    if common.isKnownCommentStyle(doc_type):
        clnt.stateChanged('comment_actions')
    else:
        clnt.stateChanged('comment_actions', KXMLGUIClient.StateReverse)
Пример #21
0
def toggleSelectionSensitiveActions(view):
    clnt = kate.getXmlGuiClient()
    filename = _try_make_url_from_text(view.selectionText())
    kate.kDebug('Original new filename: {}'.format(repr(filename)))

    if view.selection() and len(filename) < _SANE_URI_LENGTH:
        clnt.stateChanged('has_selection')
        # Change action text...
        if _URI_LENGTH_SHOW_THRESHOLD < len(filename):
            lead_pos = int(2 * _URI_LENGTH_SHOW_THRESHOLD / 3)
            tail_pos = -int(_URI_LENGTH_SHOW_THRESHOLD / 3)
            filename = filename[:lead_pos] + '...' + filename[tail_pos:]
        assert('Sanity check' and hasattr(tryOpen, 'action'))
        kate.kDebug('New filename: {}'.format(filename))
        tryOpen.action.setText(
            i18nc('@ation:inmenu', 'Open <filename>%1</filename>', filename)
          )
    else:
        clnt.stateChanged('has_selection', KXMLGUIClient.StateReverse)
        tryOpen.action.setText(i18nc('@ation:inmenu', 'Open selected document'))
Пример #22
0
    def _inject_expand_result(self, document, result, word_range, func):
        '''TODO Catch exceptions from provided function'''

        # Check what type of expand function it was
        if hasattr(func, 'template'):
            result = render_jinja_template(func.template, result)

        kate.kDebug('result={}'.format(repr(result)))
        assert(isinstance(result, str))

        #
        with kate.makeAtomicUndo(document):
            document.removeText(word_range)

            kate.kDebug('Expanded text:\n{}'.format(result))
            # Check if expand function requested a TemplateInterface2 to render
            # result content...
            if hasattr(func, 'use_template_iface') and func.use_template_iface:
                # Use TemplateInterface2 to insert a code snippet
                kate.kDebug('TI2 requested!')
                ti2 = document.activeView().templateInterface2()
                if ti2 is not None:
                    ti2.insertTemplateText(word_range.start(), result, {}, None)
                    return
                # Fallback to default (legacy) way...

            # Just insert text :)
            document.insertText(word_range.start(), result)
Пример #23
0
def init():
    # Set default value if not configured yet
    kate.kDebug('Loading...')
    if settings.CMAKE_BINARY not in kate.sessionConfiguration:
        kate.sessionConfiguration[settings.CMAKE_BINARY] = settings.CMAKE_BINARY_DEFAULT
    if settings.PARENT_DIRS_LOOKUP_CNT not in kate.sessionConfiguration:
        kate.sessionConfiguration[settings.PARENT_DIRS_LOOKUP_CNT] = 0
    if settings.AUX_MODULE_DIRS not in kate.sessionConfiguration:
        kate.sessionConfiguration[settings.AUX_MODULE_DIRS] = []
    if settings.PROJECT_DIR not in kate.sessionConfiguration:
        kate.sessionConfiguration[settings.PROJECT_DIR] = ''
    if settings.TOOLVIEW_ADVANCED_MODE not in kate.sessionConfiguration:
        kate.sessionConfiguration[settings.TOOLVIEW_ADVANCED_MODE] = False
    if settings.TOOLVIEW_BEAUTIFY not in kate.sessionConfiguration:
        kate.sessionConfiguration[settings.TOOLVIEW_BEAUTIFY] = True

    # Create completion model
    global _cmake_completion_model
    if _cmake_completion_model is None:
        kate.kDebug('CMake Helper Plugin: Create a completer')
        _cmake_completion_model = CMakeCompletionModel(kate.application)
        _cmake_completion_model.modelReset.connect(_reset)

    # Make an instance of a cmake tool view
    global _cmake_tool_view
    if _cmake_tool_view is None:
        kate.kDebug('CMake Helper Plugin: Create a tool view')
        _cmake_tool_view = CMakeToolView()
Пример #24
0
    def updateColors(self, view=None):
        '''Scan a document for #colors

            Returns a list of tuples: QColor and range in a document
            TODO Some refactoring needed to reduce code duplication
            (@sa _get_color_range_under_cursor())
        '''
        self.colors = []                                    # Clear previous colors
        if view:
            document = view.document()
        else:
            try:
                document = kate.activeDocument()
            except kate.NoActiveView:
                return                                      # Do nothing if we can't get a current document
        # Iterate over document's lines trying to find #colors
        for l in range(0, document.lines()):
            line = document.line(l)                         # Get the current line
            start = 0                                       # Set initial position to 0 (line start)
            while start < len(line):                        # Repeat 'till the line end
                start = line.find('#', start)               # Try to find a '#' character (start of #color)
                if start == -1:                             # Did we found smth?
                    break                                   # No! Nothing to do...
                # Try to get a word right after the '#' char
                end = start + 1
                for c in line[end:]:
                    if not (c in string.hexdigits):
                        break
                    end += 1
                color_range = KTextEditor.Range(l, start, l, end)
                color_str = document.text(color_range)
                color = QColor(color_str)
                if color.isValid():
                    self.colors.append(ColorRangePair(color, color_range))
                    kate.kDebug('ColorUtilsToolView: scan for #colors found {}'.format(color_str))
                start = end
Пример #25
0
def render_jinja_template(template, data):
    assert(isinstance(data, dict))
    assert(isinstance(template, str))

    # Add some predefined variables
    # - `nl` == new line character
    if 'nl' not in data:
        data['nl'] = '\n'
    # - `tab` == one TAB character
    if 'tab' not in data:
        data['tab'] = '\t'
    # - `space` == one space character
    if 'space' not in data:
        data['space'] = ' '

    result = None
    # Ok, going to render some jinja2 template...
    filename = kate.findApplicationResource('{}/{}'.format(_JINJA_TEMPLATES_BASE_DIR, template))
    if not filename:
        kate.ui.popup(
            i18nc('@title:window', 'Error')
            , i18nc('@info:tooltip', 'Template file not found <filename>%1</filename>', template)
            , 'dialog-error'
            )
        return result

    kate.kDebug('found abs template: {}'.format(filename))

    # Get a corresponding environment for jinja!
    base_dir_pos = filename.find(_JINJA_TEMPLATES_BASE_DIR)
    assert(base_dir_pos != -1)
    basedir = filename[:base_dir_pos + len(_JINJA_TEMPLATES_BASE_DIR)]
    filename = filename[base_dir_pos + len(_JINJA_TEMPLATES_BASE_DIR) + 1:]
    env = _getJinjaEnvironment(basedir)
    kate.kDebug('basedir={}, template_rel={}'.format(basedir, filename))
    try:
        tpl = env.get_template(filename)
        kate.kDebug('data dict={}'.format(data))
        result = tpl.render(data)
    except jinja2.TemplateError as e:
        kate.ui.popup(
            i18nc('@title:window', 'Error')
            , i18nc(
                '@info:tooltip'
                , 'Template file error [<filename>%1</filename>]: <status>%2</status>'
                , template
                , e.message
                )
            , 'dialog-error'
            )
    return result
Пример #26
0
 def _try_syntactic_completer(self, syntax, document, cursor, word, comp_list):
     kate.kDebug('CMakeCC: generic completer: syntax='+str(syntax))
     kate.kDebug('CMakeCC: generic completer: comp_list='+str(comp_list))
     result = []
     if isinstance(syntax, list):
         for sid, s in enumerate(syntax):
             (items, stop) = s.complete(document, cursor, word, comp_list, sid)
             if stop:
                 return items
             result += items
     else:
         (items, stop) = syntax.complete(document, cursor, word, comp_list)
         result = items
     kate.kDebug('CMakeCC: generic completer result={}'.format(result))
     # TODO sort | uniq
     return result
Пример #27
0
    def apply(self):
        kate.sessionConfiguration[settings.CMAKE_BINARY] = self.cmakeBinary.text()
        kate.sessionConfiguration[settings.PARENT_DIRS_LOOKUP_CNT] = self.parentDirsLookupCnt.value()
        try:
            cmake_help_parser.validate_cmake_executable(kate.sessionConfiguration[settings.CMAKE_BINARY])
        except ValueError as error:
            kate.ui.popup(
                i18nc('@title:window', 'Error')
              , i18nc('@info:tooltip', 'CMake executable test run failed:<nl/><message>%1</message>', error)
              , 'dialog-error'
              )
        # TODO Store the following for a current session!
        kate.sessionConfiguration[settings.PROJECT_DIR] = self.projectBuildDir.text()
        kate.sessionConfiguration[settings.AUX_MODULE_DIRS] = []
        for i in range(0, self.moduleDirs.count()):
            kate.sessionConfiguration[settings.AUX_MODULE_DIRS].append(self.moduleDirs.item(i).text())

        # Show some spam
        kate.kDebug('CMakeCC: config save: CMAKE_BINARY={}'.format(kate.sessionConfiguration[settings.CMAKE_BINARY]))
        kate.kDebug('CMakeCC: config save: AUX_MODULE_DIRS={}'.format(kate.sessionConfiguration[settings.AUX_MODULE_DIRS]))
        kate.kDebug('CMakeCC: config save: PROJECT_DIR={}'.format(kate.sessionConfiguration[settings.PROJECT_DIR]))
        kate.sessionConfiguration.save()
Пример #28
0
def getRangeTopology(breakChars):
    '''Get range opened w/ `openCh' and closed w/ `closeCh'

        @return tuple w/ current range, list of nested ranges
                and list of positions of break characters

        @note Assume cursor positioned whithin that range already.
    '''
    document = kate.activeDocument()
    view = kate.activeView()
    pos = view.cursorPosition()

    stack = list()
    nestedRanges = list()
    breakPositions = list()
    firstIteration = True
    found = False
    # Iterate from the current line towards a document start
    for cl in range(pos.line(), -1, -1):
        lineStr = str(document.line(cl))
        if not firstIteration:                              # skip first iteration
            pos.setColumn(len(lineStr))                     # set current column to the end of current line
        else:
            firstIteration = False                          # do nothing on first iteration
        # Iterate from the current column to a line start
        for cc in range(pos.column() - 1, -1, -1):
            #kate.kDebug("c: current position" + str(cl) + "," + str(cc) + ",ch='" + lineStr[cc] + "'")
            # Check open/close brackets
            if lineStr[cc] == ')':                          # found closing char: append its position to the stack
                stack.append((cl, cc, False))
                #kate.kDebug("o( Add position: " + str(stack[-1]))
                continue
            if lineStr[cc] == '(':                          # found open char...
                if len(stack):                              # if stack isn't empty (i.e. there are some closing chars met)
                    #kate.kDebug("o( Pop position: " + str(stack[-1]))
                    nrl, nrc, isT = stack.pop()             # remove last position from the stack
                    if not isT:
                        nestedRanges.append(                # and append a nested range
                            KTextEditor.Range(cl, cc, nrl, nrc)
                          )
                    else:
                        raise LookupError(
                            i18nc(
                                '@info'
                              , 'Misbalanced brackets: at <numid>%1</numid>,<numid>%2</numid> and <numid>%3</numid>,<numid>%4</numid>'
                              , cl + 1, cc + 1, nrl + 1, nrc + 1
                              )
                          )
                else:                                       # otherwise,
                    openPos = (cl, cc + 1, False)           # remember range start (exclude an open char)
                    #kate.kDebug("o( Found position: " + str(openPos))
                    found = True
                    break
                continue
            # Check for template angel brackets
            if lineStr[cc] == '>':
                if looksLikeTemplateAngelBracket(lineStr, cc):
                    stack.append((cl, cc, True))
                    #kate.kDebug("o< Add position: " + str(stack[-1]))
                #else:
                    #kate.kDebug("o< Doesn't looks like template: " + str(cl) + "," + str(cc))
                continue
            if lineStr[cc] == '<':
                if not looksLikeTemplateAngelBracket(lineStr, cc):
                    #kate.kDebug("o< Doesn't looks like template: " + str(cl) + "," + str(cc + 1))
                    pass
                elif len(stack):                            # if stack isn't empty (i.e. there are some closing chars met)
                    #kate.kDebug("o< Pop position: " + str(stack[-1]))
                    nrl, nrc, isT = stack.pop()             # remove last position from the stack
                    if isT:
                        nestedRanges.append(                # and append a nested range
                            KTextEditor.Range(cl, cc, nrl, nrc)
                        )
                    else:
                        raise LookupError(
                            i18nc(
                                '@info'
                              , 'Misbalanced brackets: at <numid>%1</numid>,<numid>%2</numid> and <numid>%3</numid>,<numid>%4</numid>'
                              , cl + 1, cc + 1, nrl + 1, nrc + 1
                              )
                          )
                else:
                    openPos = (cl, cc + 1, True)            # remember range start (exclude an open char)
                    #kate.kDebug("o< Found position: " + str(openPos))
                    found = True
                    break
                continue
            if lineStr[cc] in breakChars and len(stack) == 0:
                breakPositions.append(KTextEditor.Cursor(cl, cc))
        # Did we found smth on the current line?
        if found:
            break                                           # Yep! Break the outer loop

    if not found:
        return (KTextEditor.Range(), list(), list())        # Return empty ranges if nothing found

    assert(len(stack) == 0)                                 # stack expected to be empty!

    breakPositions.reverse()                                # reverse breakers list required cuz we found 'em in a reverse order :)

    # Iterate from the current position towards the end of a document
    pos = view.cursorPosition()                             # get current cursor position again
    firstIteration = True
    found = False
    for cl in range(pos.line(), document.lines()):
        lineStr = str(document.line(cl))
        if not firstIteration:                              # skip first iteration
            pos.setColumn(0)                                # set current column to the start of current line
        else:
            firstIteration = False                          # do nothing on first iteration
        for cc in range(pos.column(), len(lineStr)):
            #kate.kDebug("c: current position" + str(cl) + "," + str(cc) + ",ch='" + lineStr[cc] + "'")
            # Check open/close brackets
            if lineStr[cc] == '(':
                stack.append((cl, cc, False))
                #kate.kDebug("c) Add position: " + str(stack[-1]))
                continue
            if lineStr[cc] == ')':
                if len(stack):
                    #kate.kDebug("c) Pop position: " + str(stack[-1]))
                    nrl, nrc, isT = stack.pop()             # remove a last position from the stack
                    if not isT:
                        nestedRanges.append(                # and append a nested range
                            KTextEditor.Range(nrl, nrc, cl, cc)
                        )
                    else:
                        raise LookupError(
                            i18nc(
                                '@info'
                              , 'Misbalanced brackets: at <numid>%1</numid>,<numid>%2</numid> and <numid>%3</numid>,<numid>%4</numid>'
                              , nrl + 1, nrc + 1, cl + 1, cc + 1
                              )
                          )
                else:
                    closePos = (cl, cc, False)              # remember the range end
                    #kate.kDebug("c) Found position: " + str(closePos))
                    found = True
                    break
                continue
            # Check for template angel brackets
            if lineStr[cc] == '<':
                if looksLikeTemplateAngelBracket(lineStr, cc):
                    stack.append((cl, cc, True))
                    #kate.kDebug("c> Add position: " + str(stack[-1]))
                #else:
                    #kate.kDebug("c> Doesn't looks like template: " + str(cl) + "," + str(cc))
                continue
            if lineStr[cc] == '>':
                if not looksLikeTemplateAngelBracket(lineStr, cc):
                    #kate.kDebug("c> Doesn't looks like template: " + str(cl) + "," + str(cc))
                    pass
                elif len(stack):                            # if stack isn't empty (i.e. there are some closing chars met)
                    #kate.kDebug("c> Pop position: " + str(stack[-1]))
                    nrl, nrc, isT = stack.pop()             # remove last position from the stack
                    if isT:
                        nestedRanges.append(                # and append a nested range
                            KTextEditor.Range(cl, cc, nrl, nrc)
                        )
                    else:
                        raise LookupError(
                            i18nc(
                                '@info'
                              , 'Misbalanced brackets: at <numid>%1</numid>,<numid>%2</numid> and <numid>%3</numid>,<numid>%4</numid>'
                              , nrl + 1, nrc + 1, cl + 1, cc + 1
                              )
                          )
                else:
                    closePos = (cl, cc, True)               # remember the range end
                    kate.kDebug("c> Found position: " + str(closePos))
                    found = True
                    break
                continue
            if lineStr[cc] in breakChars and len(stack) == 0:
                breakPositions.append(KTextEditor.Cursor(cl, cc))
        # Did we found smth on the current line?
        if found:
            break                                           # Yep! Break the outer loop

    if not found:
        return (KTextEditor.Range(), list(), list())        # Return empty ranges if nothing found

    assert(len(stack) == 0)                                 # stack expected to be empty!

    if openPos[2] != closePos[2]:
        raise LookupError(
            i18nc(
                '@info'
              , 'Misbalanced brackets: at <numid>%1</numid>,<numid>%2</numid> and <numid>%3</numid>,<numid>%4</numid>'
              , openPos[0] + 1, openPos[1] + 1, closePos[0] + 1, closePos[1] + 1
              )
          )

    return (KTextEditor.Range(openPos[0], openPos[1], closePos[0], closePos[1]), nestedRanges, breakPositions)
Пример #29
0
def on_text_changed(doc, rng1, text, rng2):
    kate.kDebug('Text changed: rng1={}, rng2={}, text={}'.format(repr(text)))
Пример #30
0
def on_text_removed(doc, rng, text):
    kate.kDebug('Remove text: {}'.format(repr(text)))