Пример #1
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)
Пример #2
0
def expandUDFAtCursor():
    ''' Attempt text expansion on the word at the cursor.

        The expansions available are based firstly on the mimetype of the
        document, for example "text_x-c++src.expand" for "text/x-c++src", and
        secondly on "all.expand".

        TODO Split this function!
    '''
    view = kate.activeView()
    document = view.document()
    try:
        word_range, argument_range = _wordAndArgumentAtCursorRanges(document, view.cursorPosition())
    except ParseError as e:
        kate.ui.popup(i18nc('@title:window', 'Parse error'), e, 'dialog-warning')
        return
    word = document.text(word_range)
    expansions = getExpansionsFor(document.mimeType())
    if word in expansions:
        func = expansions[word][0]
    else:
        kate.ui.popup(
            i18nc('@title:window', 'Error')
          , i18nc('@info:tooltip', 'Expansion "<icode>%1</icode>" not found', word)
          , 'dialog-warning'
          )
        return
    arguments = []
    namedArgs = {}
    if argument_range is not None:
        # strip parentheses and split arguments by comma
        preArgs = [arg.strip() for arg in document.text(argument_range)[1:-1].split(',') if bool(arg.strip())]
        kate.kDebug('Arguments = {}'.format(arguments))
        # form a dictionary from args w/ '=' character, leave others in a list
        for arg in preArgs:
            if '=' in arg:
                key, value = [item.strip() for item in arg.split('=')]
                namedArgs[key] = value
            else:
                arguments.append(arg)
    # Call user expand function w/ parsed arguments and
    # possible w/ named params dict
    try:
        kate.kDebug('Arguments = {}'.format(arguments))
        kate.kDebug('Named arguments = {}'.format(namedArgs))
        if len(namedArgs):
            replacement = func(*arguments, **namedArgs)
        else:
            replacement = func(*arguments)
    except Exception as e:
        # remove the top of the exception, it's our code
        try:
            type, value, tb = sys.exc_info()
            sys.last_type = type
            sys.last_value = value
            sys.last_traceback = tb
            tblist = traceback.extract_tb(tb)
            del tblist[:1]
            l = traceback.format_list(tblist)
            if l:
                l.insert(0, i18nc('@info', 'Traceback (most recent call last):<nl/>'))
            l[len(l):] = traceback.format_exception_only(type, value)
        finally:
            tblist = tb = None
        # convert file names in the traceback to links. Nice.
        def replaceAbsolutePathWithLinkCallback(match):
            text = match.group()
            filePath = match.group(1)
            fileName = os.path.basename(filePath)
            text = text.replace(filePath, i18nc('@info', '<link url="%1">%2</link>', filePath, fileName))
            return text
        s = ''.join(l).strip()
        # FIXME: extract the filename and then use i18nc, instead of manipulate the i18nc text
        s = re.sub(
            i18nc('@info', 'File <filename>"(/[^\n]+)"</filename>, line')
          , replaceAbsolutePathWithLinkCallback
          , s
          )
        kate.kDebug('EXPAND FAILURE: {}'.format(s))
        kate.ui.popup(
            i18nc('@title:window', 'Error')
          , i18nc('@info:tooltip', '<bcode>%1</bcode>', s)
          , 'dialog-error'
          )
        return

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

    assert(isinstance(replacement, str))

    with kate.makeAtomicUndo(document):
        # Remove old text
        if argument_range is not None:
            document.removeText(argument_range)
        document.removeText(word_range)

        kate.kDebug('Expanded text:\n{}'.format(replacement))

        # 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 = view.templateInterface2()
            if ti2 is not None:
                ti2.insertTemplateText(word_range.start(), replacement, {}, None)
                return
            # Fallback to default (legacy) way...

        # Just insert text :)
        document.insertText(word_range.start(), replacement)