Ejemplo n.º 1
0
def UpdateSignatureHelp(state, signature_info):  # noqa
    if not ShouldUseSignatureHelp():
        return state

    signatures = signature_info.get('signatures') or []

    if not signatures:
        if state.popup_win_id:
            # TODO/FIXME: Should we use popup_hide() instead ?
            vim.eval(f"popup_close( { state.popup_win_id } )")
        return SignatureHelpState(None, SignatureHelpState.INACTIVE)

    if state.state != SignatureHelpState.ACTIVE:
        state.anchor = vimsupport.CurrentLineAndColumn()

    state.state = SignatureHelpState.ACTIVE

    # Generate the buffer as a list of lines
    buf_lines = _MakeSignatureHelpBuffer(signature_info)
    screen_pos = vimsupport.ScreenPositionForLineColumnInWindow(
        vim.current.window,
        state.anchor[0] + 1,  # anchor 0-based
        state.anchor[1] + 1)  # anchor 0-based

    # Simulate 'flip' at the screen boundaries by using screenpos and hiding the
    # signature help menu if it overlaps the completion popup (pum).
    #
    # FIXME: revert to cursor-relative positioning and the 'flip' option when that
    # is implemented (if that is indeed better).

    # By default display above the anchor
    line = int(screen_pos['row']) - 1  # -1 to display above the cur line
    pos = "botleft"

    cursor_line = vimsupport.CurrentLineAndColumn()[0] + 1
    if int(screen_pos['row']) <= len(buf_lines):
        # No room at the top, display below
        line = int(screen_pos['row']) + 1
        pos = "topleft"

    # Don't allow the popup to overlap the cursor
    if (pos == 'topleft' and line < cursor_line
            and line + len(buf_lines) >= cursor_line):
        line = 0

    # Don't allow the popup to overlap the pum
    if line > 0 and GetIntValue('pumvisible()'):
        pum_line = GetIntValue('pum_getpos().row') + 1
        if pos == 'botleft' and pum_line <= line:
            line = 0
        elif (pos == 'topleft' and pum_line >= line and pum_line <
              (line + len(buf_lines))):
            line = 0

    if line <= 0:
        # Nowhere to put it so hide it
        if state.popup_win_id:
            # TODO/FIXME: Should we use popup_hide() instead ?
            vim.eval(f"popup_close( { state.popup_win_id } )")
        return SignatureHelpState(None, SignatureHelpState.INACTIVE)

    if int(screen_pos['curscol']) <= 1:
        col = 1
    else:
        # -1 for padding,
        # -1 for the trigger character inserted (the anchor is set _after_ the
        # character is inserted, so we remove it).
        # FIXME: multi-byte characters would be wrong. Need to set anchor before
        # inserting the char ?
        col = int(screen_pos['curscol']) - 2

    if col <= 0:
        col = 1

    options = {
        "line": line,
        "col": col,
        "pos": pos,
        "wrap": 0,
        # NOTE: We *dont'* use "cursorline" here - that actually uses PMenuSel,
        # which is just too invasive for us (it's more selected item than actual
        # cursorline. So instead, we manually set 'cursorline' in the popup window
        # and enable sytax based on the current file syntax)
        "flip": 1,
        "padding": [0, 1, 0,
                    1],  # Pad 1 char in X axis to match completion menu
    }

    if not state.popup_win_id:
        state.popup_win_id = GetIntValue(
            f'popup_create( { json.dumps( buf_lines ) }, '
            f'{ json.dumps( options ) } )')
    else:
        vim.eval(f'popup_settext( { state.popup_win_id }, '
                 f'{ json.dumps( buf_lines ) } )')

    # Should do nothing if already visible
    vim.eval(
        f'popup_move( { state.popup_win_id }, { json.dumps( options ) } )')
    vim.eval(f'popup_show( { state.popup_win_id } )')

    syntax = utils.ToUnicode(vim.current.buffer.options['syntax'])
    active_signature = int(signature_info.get('activeSignature', 0))
    vim.eval(f"win_execute( { state.popup_win_id }, "
             f"'set syntax={ syntax } cursorline | "
             f"call cursor( [ { active_signature + 1 }, 1 ] )' )")

    return state
Ejemplo n.º 2
0
def UpdateSignatureHelp(state, signature_info):  # noqa
    if not ShouldUseSignatureHelp():
        return state

    signatures = signature_info.get('signatures') or []

    if not signatures:
        if state.popup_win_id:
            # TODO/FIXME: Should we use popup_hide() instead ?
            vim.eval("popup_close( {} )".format(state.popup_win_id))
        return SignatureHelpState(None, SignatureHelpState.INACTIVE)

    if state.state != SignatureHelpState.ACTIVE:
        state.anchor = vimsupport.CurrentLineAndColumn()

    state.state = SignatureHelpState.ACTIVE

    # Generate the buffer as a list of lines
    buf_lines = _MakeSignatureHelpBuffer(signature_info)
    screen_pos = vimsupport.ScreenPositionForLineColumnInWindow(
        vim.current.window,
        state.anchor[0] + 1,  # anchor 0-based
        state.anchor[1] + 1)  # anchor 0-based

    # Simulate 'flip' at the screen boundaries by using screenpos and hiding the
    # signature help menu if it overlaps the completion popup (pum).
    #
    # FIXME: revert to cursor-relative positioning and the 'flip' option when that
    # is implemented (if that is indeed better).

    # By default display above the anchor
    line = int(screen_pos['row']) - 1  # -1 to display above the cur line
    pos = "botleft"

    cursor_line = vimsupport.CurrentLineAndColumn()[0] + 1
    if int(screen_pos['row']) <= len(buf_lines):
        # No room at the top, display below
        line = int(screen_pos['row']) + 1
        pos = "topleft"

    # Don't allow the popup to overlap the cursor
    if (pos == 'topleft' and line < cursor_line
            and line + len(buf_lines) >= cursor_line):
        line = 0

    # Don't allow the popup to overlap the pum
    if line > 0 and GetIntValue('pumvisible()'):
        pum_line = GetIntValue(vim.eval('pum_getpos().row')) + 1
        if pos == 'botleft' and pum_line <= line:
            line = 0
        elif (pos == 'topleft' and pum_line >= line and pum_line <
              (line + len(buf_lines))):
            line = 0

    if line <= 0:
        # Nowhere to put it so hide it
        if state.popup_win_id:
            # TODO/FIXME: Should we use popup_hide() instead ?
            vim.eval("popup_close( {} )".format(state.popup_win_id))
        return SignatureHelpState(None, SignatureHelpState.INACTIVE)

    if int(screen_pos['curscol']) <= 1:
        col = 1
    else:
        # -1 for padding,
        # -1 for the trigger character inserted (the anchor is set _after_ the
        # character is inserted, so we remove it).
        # FIXME: multi-byte characters would be wrong. Need to set anchor before
        # inserting the char ?
        col = int(screen_pos['curscol']) - 2

    if col <= 0:
        col = 1

    options = {
        "line": line,
        "col": col,
        "pos": pos,
        "wrap": 0,
        "flip": 1,
        "padding": [0, 1, 0,
                    1],  # Pad 1 char in X axis to match completion menu
    }

    if not state.popup_win_id:
        state.popup_win_id = GetIntValue(
            vim.eval("popup_create( {}, {} )".format(json.dumps(buf_lines),
                                                     json.dumps(options))))
    else:
        vim.eval('popup_settext( {}, {} )'.format(state.popup_win_id,
                                                  json.dumps(buf_lines)))

    # Should do nothing if already visible
    vim.eval('popup_move( {}, {} )'.format(state.popup_win_id,
                                           json.dumps(options)))
    vim.eval('popup_show( {} )'.format(state.popup_win_id))

    return state