Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Question] Python scopes are detected in the first line (header) for top-level scopes but not nested scopes. #799

Open
anthony-S93 opened this issue Dec 16, 2023 · 1 comment · May be fixed by #805

Comments

@anthony-S93
Copy link

This isn't an issue per se; I'm asking out of curiosity more than anything else.

The behavior can be demonstrated using the following sample code (refer to the attached video):

def top_level_function(): # For top-level blocks, the scope is highlighted when the cursor is at the header.

    print("foo")


class TopLevelClass:  # For top-level blocks, the scope is highlighted when the cursor is at the header.

    def __init__(self) -> None: # Which isn't the case for nested blocks.

        # For nested blocks, the scope is only highlighted when the cursor is one line past the header
        self.foo = "bar"

Note that both class_definition and function_definition are listed in scope.include.python

indent_blank_line_python-2023-12-16_15.47.05.mp4

Which seems a bit strange to me because upon inspecting the highlight groups using :InspectTree, I didn't see any difference in the way the two function_definitions are parsed other than the fact that one is nested in a block while the other is at the top level.

(function_definition) ; [3:1 - 5:16]      <<<< This is the top-level function
 name: (identifier) ; [3:5 - 22]
 parameters: (parameters) ; [3:23 - 24]
 (comment) ; [3:27 - 108]
 body: (block) ; [5:5 - 16]
  (expression_statement) ; [5:5 - 16]
   (call) ; [5:5 - 16]
    function: (identifier) ; [5:5 - 9]
    arguments: (argument_list) ; [5:10 - 16]
     (string) ; [5:11 - 15]
      (string_start) ; [5:11 - 11]
      (string_content) ; [5:12 - 14]
      (string_end) ; [5:15 - 15]
(class_definition) ; [8:1 - 13:24]
 name: (identifier) ; [8:7 - 19]
 (comment) ; [8:23 - 104]
 body: (block) ; [10:5 - 13:24]
  (function_definition) ; [10:5 - 13:24]     <<<< This is the nested function
   name: (identifier) ; [10:9 - 16]
   parameters: (parameters) ; [10:17 - 22]
    (identifier) ; [10:18 - 21]
   return_type: (type) ; [10:27 - 30]
    (none) ; [10:27 - 30]
   (comment) ; [10:33 - 73]
   (comment) ; [12:9 - 102]
   body: (block) ; [13:9 - 24]
    (expression_statement) ; [13:9 - 24]
     (assignment) ; [13:9 - 24]
      left: (attribute) ; [13:9 - 16]
       object: (identifier) ; [13:9 - 12]
       attribute: (identifier) ; [13:14 - 16]
      right: (string) ; [13:20 - 24]
       (string_start) ; [13:20 - 20]
       (string_content) ; [13:21 - 23]
       (string_end) ; [13:24 - 24]

As you can see, in both function_definitions, the start and end positions listed by the parser are accurate. Given their similarities, I was wondering why the plugin treats both cases differently. According to the parser, the nested function begins at position [10:5]; but since the indent line is shown starting from one line below the declaration, the highlighting of the indent line will not take place until the cursor has gone past the first newline in the scope. This behavior is sensible albeit inconsistent with the case where the declaration is at the top-level of the source file. For top_level_function(), the highlighting takes place as soon as the cursor enters the line containing the declaration.

@lukas-reineke
Copy link
Owner

This is a side effect of a trick I'm using when getting the scope. I convert the cursor position to a range from the beginning of the line, to the cursor.

M.get_cursor_range = function(win)
local pos = vim.api.nvim_win_get_cursor(win)
local row, col = pos[1] - 1, pos[2]
return { row, 0, row, col }
end

I do this to avoid weird single line scopes. In most languages this works, but in Python indentation matters, so it's not quite right.

This would be pretty tricky to fix without breaking other cases worse. So I think I will not look into this.

But PRs are always welcome.

@Danielkonge Danielkonge linked a pull request Dec 21, 2023 that will close this issue
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants