nvim-treesitter-context icon indicating copy to clipboard operation
nvim-treesitter-context copied to clipboard

the 'else' is not show in context bar

Open weixuanhu opened this issue 1 year ago • 12 comments

Description

A test code as below it is a simple if ... else , when navigating the else part the context shows only the if without else. This is misleading.

image
int main() {
    if ( 1 == 1 ) {
        2 = 2;
        2 = 2;
        2 = 2;
        2 = 2;
        2 = 2;
        2 = 2;
        2 = 2;
        2 = 2;
        2 = 2;
        2 = 2;
        2 = 2;
        2 = 2;
        2 = 2;
        2 = 2;
        2 = 2;
        2 = 2;
        2 = 2;
        2 = 2;
    } else {
        3 = 3;
        3 = 3;
        3 = 3;
        3 = 3;
        3 = 3;
        3 = 3;
        3 = 3;
        3 = 3;
        3 = 3;
        3 = 3;
        3 = 3;
        3 = 3;
        3 = 3;
        3 = 3;
        3 = 3;
        3 = 3;
        3 = 3;
        3 = 3;
        3 = 3;
        3 = 3;
        3 = 3;
        3 = 3;
        3 = 3;
        3 = 3;
        3 = 3;
    }
    return 0;
}

neovim version version 0.9.1, Build type: Release nvim-treesitter-context is download on 2023.10.20

packer.nvim lua config: use 'nvim-treesitter/nvim-treesitter-context'

nvim-treesitter-context.lua :

require 'treesitter-context'.setup {
    enable = true,          -- Enable this plugin (Can be enabled/disabled later via commands)
    max_lines = 0,          -- How many lines the window should span. Values <= 0 mean no limit.
    min_window_height = 0,  -- Minimum editor window height to enable context. Values <= 0 mean no limit.
    line_numbers = true,
    multiline_threshold = 20, -- Maximum number of lines to show for a single context
    trim_scope = 'outer',   -- Which context lines to discard if `max_lines` is exceeded. Choices: 'inner', 'outer'
    mode = 'cursor',        -- Line used to calculate context. Choices: 'cursor', 'topline'
    -- Separator between context and content. Should be a single character string, like '-'.
    -- When separator is set, the context will only show up when there are at least 2 lines above cursorline.
    separator = nil,
    zindex = 20,   -- The Z-index of the context window
    on_attach = nil, -- (fun(buf: integer): boolean) return false to disable attaching
}

Neovim version

0.9.1

Expected behavior

in if ... else context, show the else context.

Actual behavior

in if ... else context, no else context is shown

Minimal config

packer.nvim lua config: `use 'nvim-treesitter/nvim-treesitter-context'`

nvim-treesitter-context.lua :

require 'treesitter-context'.setup { enable = true, -- Enable this plugin (Can be enabled/disabled later via commands) max_lines = 0, -- How many lines the window should span. Values <= 0 mean no limit. min_window_height = 0, -- Minimum editor window height to enable context. Values <= 0 mean no limit. line_numbers = true, multiline_threshold = 20, -- Maximum number of lines to show for a single context trim_scope = 'outer', -- Which context lines to discard if max_lines is exceeded. Choices: 'inner', 'outer' mode = 'cursor', -- Line used to calculate context. Choices: 'cursor', 'topline' -- Separator between context and content. Should be a single character string, like '-'. -- When separator is set, the context will only show up when there are at least 2 lines above cursorline. separator = nil, zindex = 20, -- The Z-index of the context window on_attach = nil, -- (fun(buf: integer): boolean) return false to disable attaching }


-- ADD INIT.LUA SETTINGS THAT IS _NECESSARY_ FOR REPRODUCING THE ISSUE

Steps to reproduce

install nvim-treesitter-context, then use neovim to review below code, go to the last else line.

int main() {
    if ( 1 == 1 ) {
        2 = 2;
        2 = 2;
        2 = 2;
        2 = 2;
        2 = 2;
        2 = 2;
        2 = 2;
        2 = 2;
        2 = 2;
        2 = 2;
        2 = 2;
        2 = 2;
        2 = 2;
        2 = 2;
        2 = 2;
        2 = 2;
        2 = 2;
        2 = 2;
    } else {
        3 = 3;
        3 = 3;
        3 = 3;
        3 = 3;
        3 = 3;
        3 = 3;
        3 = 3;
        3 = 3;
        3 = 3;
        3 = 3;
        3 = 3;
        3 = 3;
        3 = 3;
        3 = 3;
        3 = 3;
        3 = 3;
        3 = 3;
        3 = 3;
        3 = 3;
        3 = 3;
        3 = 3;
        3 = 3;
        3 = 3;
        3 = 3;
        3 = 3;
    }
    return 0;
}

weixuanhu avatar Nov 06 '23 02:11 weixuanhu

This looks like C, does it?

Generally this plugin just uses the hierarchical tree structure that the treesitter parser for the language provides. For example with python or rust, this works fine.

You can inspect what the parser provides using the :InspectTree (in a recent neovim version).

So my hunch would be that this should actually be an issue / request to the treesitter C parser.

syphar avatar Nov 06 '23 05:11 syphar

thanks syphar

No it is a cc file. I copy it as a c file, the else part is not shown either.

:InspectTree shows below info. I notice that alternative: (else_clause) ; [23:7 - 49:5] corresponds to the else branch, so will treesitter-context handle the alternative: (else_clause) ?

(preproc_include) ; [1:1 - 2:0]
 path: (string_literal) ; [1:10 - 18]
  (string_content) ; [1:11 - 17]
(function_definition) ; [3:1 - 51:1]
 type: (primitive_type) ; [3:1 - 3]
 declarator: (function_declarator) ; [3:5 - 10]
  declarator: (identifier) ; [3:5 - 8]
  parameters: (parameter_list) ; [3:9 - 10]
 body: (compound_statement) ; [3:12 - 51:1]
  (if_statement) ; [4:5 - 49:5]
   condition: (condition_clause) ; [4:8 - 17]
    value: (binary_expression) ; [4:10 - 15]
     left: (number_literal) ; [4:10 - 10]
     right: (number_literal) ; [4:15 - 15]
   consequence: (compound_statement) ; [4:19 - 23:5]
    (expression_statement) ; [5:9 - 14]
     (assignment_expression) ; [5:9 - 13]
      left: (user_defined_literal) ; [5:9 - 9]
       (number_literal) ; [5:9 - 9]
       (literal_suffix) ; [5:10 - 9]
      right: (number_literal) ; [5:13 - 13]
    (expression_statement) ; [6:9 - 14]
     (assignment_expression) ; [6:9 - 13]
      left: (user_defined_literal) ; [6:9 - 9]
       (number_literal) ; [6:9 - 9]
       (literal_suffix) ; [6:10 - 9]
      right: (number_literal) ; [6:13 - 13]
    (expression_statement) ; [7:9 - 14]
     (assignment_expression) ; [7:9 - 13]
      left: (user_defined_literal) ; [7:9 - 9]
       (number_literal) ; [7:9 - 9]
       (literal_suffix) ; [7:10 - 9]
      right: (number_literal) ; [7:13 - 13]
    (expression_statement) ; [8:9 - 14]
     (assignment_expression) ; [8:9 - 13]
      left: (user_defined_literal) ; [8:9 - 9]
       (number_literal) ; [8:9 - 9]
       (literal_suffix) ; [8:10 - 9]
      right: (number_literal) ; [8:13 - 13]
    (expression_statement) ; [9:9 - 14]
     (assignment_expression) ; [9:9 - 13]
      left: (user_defined_literal) ; [9:9 - 9]
       (number_literal) ; [9:9 - 9]
       (literal_suffix) ; [9:10 - 9]
      right: (number_literal) ; [9:13 - 13]
    (expression_statement) ; [10:9 - 14]
     (assignment_expression) ; [10:9 - 13]
      left: (user_defined_literal) ; [10:9 - 9]
       (number_literal) ; [10:9 - 9]
       (literal_suffix) ; [10:10 - 9]
      right: (number_literal) ; [10:13 - 13]
    (expression_statement) ; [11:9 - 14]
     (assignment_expression) ; [11:9 - 13]
      left: (user_defined_literal) ; [11:9 - 9]
       (number_literal) ; [11:9 - 9]
       (literal_suffix) ; [11:10 - 9]
      right: (number_literal) ; [11:13 - 13]
    (expression_statement) ; [12:9 - 14]
     (assignment_expression) ; [12:9 - 13]
      left: (user_defined_literal) ; [12:9 - 9]
       (number_literal) ; [12:9 - 9]
       (literal_suffix) ; [12:10 - 9]
      right: (number_literal) ; [12:13 - 13]
    (expression_statement) ; [13:9 - 14]
     (assignment_expression) ; [13:9 - 13]
      left: (user_defined_literal) ; [13:9 - 9]
       (number_literal) ; [13:9 - 9]
       (literal_suffix) ; [13:10 - 9]
      right: (number_literal) ; [13:13 - 13]
    (expression_statement) ; [14:9 - 14]
     (assignment_expression) ; [14:9 - 13]
      left: (user_defined_literal) ; [14:9 - 9]
       (number_literal) ; [14:9 - 9]
       (literal_suffix) ; [14:10 - 9]
      right: (number_literal) ; [14:13 - 13]
    (expression_statement) ; [15:9 - 14]
     (assignment_expression) ; [15:9 - 13]
      left: (user_defined_literal) ; [15:9 - 9]
       (number_literal) ; [15:9 - 9]
       (literal_suffix) ; [15:10 - 9]
      right: (number_literal) ; [15:13 - 13]
    (expression_statement) ; [16:9 - 14]
     (assignment_expression) ; [16:9 - 13]
      left: (user_defined_literal) ; [16:9 - 9]
       (number_literal) ; [16:9 - 9]
       (literal_suffix) ; [16:10 - 9]
      right: (number_literal) ; [16:13 - 13]
    (expression_statement) ; [17:9 - 14]
     (assignment_expression) ; [17:9 - 13]
      left: (user_defined_literal) ; [17:9 - 9]
       (number_literal) ; [17:9 - 9]
       (literal_suffix) ; [17:10 - 9]
      right: (number_literal) ; [17:13 - 13]
    (expression_statement) ; [18:9 - 14]
     (assignment_expression) ; [18:9 - 13]
      left: (user_defined_literal) ; [18:9 - 9]
       (number_literal) ; [18:9 - 9]
       (literal_suffix) ; [18:10 - 9]
      right: (number_literal) ; [18:13 - 13]
    (expression_statement) ; [19:9 - 14]
     (assignment_expression) ; [19:9 - 13]
      left: (user_defined_literal) ; [19:9 - 9]
       (number_literal) ; [19:9 - 9]
       (literal_suffix) ; [19:10 - 9]
      right: (number_literal) ; [19:13 - 13]
    (expression_statement) ; [20:9 - 14]
     (assignment_expression) ; [20:9 - 13]
      left: (user_defined_literal) ; [20:9 - 9]
       (number_literal) ; [20:9 - 9]
       (literal_suffix) ; [20:10 - 9]
      right: (number_literal) ; [20:13 - 13]
    (expression_statement) ; [21:9 - 14]
     (assignment_expression) ; [21:9 - 13]
      left: (user_defined_literal) ; [21:9 - 9]
       (number_literal) ; [21:9 - 9]
       (literal_suffix) ; [21:10 - 9]
      right: (number_literal) ; [21:13 - 13]
    (expression_statement) ; [22:9 - 14]
     (assignment_expression) ; [22:9 - 13]
      left: (user_defined_literal) ; [22:9 - 9]
       (number_literal) ; [22:9 - 9]
       (literal_suffix) ; [22:10 - 9]
      right: (number_literal) ; [22:13 - 13]
   alternative: (else_clause) ; [23:7 - 49:5]
    (compound_statement) ; [23:12 - 49:5]
     (expression_statement) ; [24:9 - 14]
      (assignment_expression) ; [24:9 - 13]
       left: (user_defined_literal) ; [24:9 - 9]
        (number_literal) ; [24:9 - 9]
        (literal_suffix) ; [24:10 - 9]
       right: (number_literal) ; [24:13 - 13]
     (expression_statement) ; [25:9 - 14]
      (assignment_expression) ; [25:9 - 13]
       left: (user_defined_literal) ; [25:9 - 9]
        (number_literal) ; [25:9 - 9]
        (literal_suffix) ; [25:10 - 9]
       right: (number_literal) ; [25:13 - 13]
     (expression_statement) ; [26:9 - 14]
      (assignment_expression) ; [26:9 - 13]
       left: (user_defined_literal) ; [26:9 - 9]
        (number_literal) ; [26:9 - 9]
        (literal_suffix) ; [26:10 - 9]
       right: (number_literal) ; [26:13 - 13]
     (expression_statement) ; [27:9 - 14]
      (assignment_expression) ; [27:9 - 13]
       left: (user_defined_literal) ; [27:9 - 9]
        (number_literal) ; [27:9 - 9]
        (literal_suffix) ; [27:10 - 9]
       right: (number_literal) ; [27:13 - 13]
     (expression_statement) ; [28:9 - 14]
      (assignment_expression) ; [28:9 - 13]
       left: (user_defined_literal) ; [28:9 - 9]
        (number_literal) ; [28:9 - 9]
        (literal_suffix) ; [28:10 - 9]
       right: (number_literal) ; [28:13 - 13]
     (expression_statement) ; [29:9 - 14]
      (assignment_expression) ; [29:9 - 13]
       left: (user_defined_literal) ; [29:9 - 9]
        (number_literal) ; [29:9 - 9]
        (literal_suffix) ; [29:10 - 9]
       right: (number_literal) ; [29:13 - 13]
     (expression_statement) ; [30:9 - 14]
      (assignment_expression) ; [30:9 - 13]
       left: (user_defined_literal) ; [30:9 - 9]
        (number_literal) ; [30:9 - 9]
        (literal_suffix) ; [30:10 - 9]
       right: (number_literal) ; [30:13 - 13]
     (expression_statement) ; [31:9 - 14]
      (assignment_expression) ; [31:9 - 13]
       left: (user_defined_literal) ; [31:9 - 9]
        (number_literal) ; [31:9 - 9]
        (literal_suffix) ; [31:10 - 9]
       right: (number_literal) ; [31:13 - 13]
     (expression_statement) ; [32:9 - 14]
      (assignment_expression) ; [32:9 - 13]
       left: (user_defined_literal) ; [32:9 - 9]
        (number_literal) ; [32:9 - 9]
        (literal_suffix) ; [32:10 - 9]
       right: (number_literal) ; [32:13 - 13]
     (expression_statement) ; [33:9 - 14]
      (assignment_expression) ; [33:9 - 13]
       left: (user_defined_literal) ; [33:9 - 9]
        (number_literal) ; [33:9 - 9]
        (literal_suffix) ; [33:10 - 9]
       right: (number_literal) ; [33:13 - 13]
     (expression_statement) ; [34:9 - 14]
      (assignment_expression) ; [34:9 - 13]
       left: (user_defined_literal) ; [34:9 - 9]
        (number_literal) ; [34:9 - 9]
        (literal_suffix) ; [34:10 - 9]
       right: (number_literal) ; [34:13 - 13]
     (expression_statement) ; [35:9 - 14]
      (assignment_expression) ; [35:9 - 13]
       left: (user_defined_literal) ; [35:9 - 9]
        (number_literal) ; [35:9 - 9]
        (literal_suffix) ; [35:10 - 9]
       right: (number_literal) ; [35:13 - 13]
     (expression_statement) ; [36:9 - 14]
      (assignment_expression) ; [36:9 - 13]
       left: (user_defined_literal) ; [36:9 - 9]
        (number_literal) ; [36:9 - 9]
        (literal_suffix) ; [36:10 - 9]
       right: (number_literal) ; [36:13 - 13]
     (expression_statement) ; [37:9 - 14]
      (assignment_expression) ; [37:9 - 13]
       left: (user_defined_literal) ; [37:9 - 9]
        (number_literal) ; [37:9 - 9]
        (literal_suffix) ; [37:10 - 9]
       right: (number_literal) ; [37:13 - 13]
     (expression_statement) ; [38:9 - 14]
      (assignment_expression) ; [38:9 - 13]
       left: (user_defined_literal) ; [38:9 - 9]
        (number_literal) ; [38:9 - 9]
        (literal_suffix) ; [38:10 - 9]
       right: (number_literal) ; [38:13 - 13]
     (expression_statement) ; [39:9 - 14]
      (assignment_expression) ; [39:9 - 13]
       left: (user_defined_literal) ; [39:9 - 9]
        (number_literal) ; [39:9 - 9]
        (literal_suffix) ; [39:10 - 9]
       right: (number_literal) ; [39:13 - 13]
     (expression_statement) ; [40:9 - 14]
      (assignment_expression) ; [40:9 - 13]
       left: (user_defined_literal) ; [40:9 - 9]
        (number_literal) ; [40:9 - 9]
        (literal_suffix) ; [40:10 - 9]
       right: (number_literal) ; [40:13 - 13]
     (expression_statement) ; [41:9 - 14]
      (assignment_expression) ; [41:9 - 13]
       left: (user_defined_literal) ; [41:9 - 9]
        (number_literal) ; [41:9 - 9]
        (literal_suffix) ; [41:10 - 9]
       right: (number_literal) ; [41:13 - 13]
     (expression_statement) ; [42:9 - 14]
      (assignment_expression) ; [42:9 - 13]
       left: (user_defined_literal) ; [42:9 - 9]
        (number_literal) ; [42:9 - 9]
        (literal_suffix) ; [42:10 - 9]
       right: (number_literal) ; [42:13 - 13]
     (expression_statement) ; [43:9 - 14]
      (assignment_expression) ; [43:9 - 13]
       left: (user_defined_literal) ; [43:9 - 9]
        (number_literal) ; [43:9 - 9]
        (literal_suffix) ; [43:10 - 9]
       right: (number_literal) ; [43:13 - 13]
     (expression_statement) ; [44:9 - 14]
      (assignment_expression) ; [44:9 - 13]
       left: (user_defined_literal) ; [44:9 - 9]
        (number_literal) ; [44:9 - 9]
        (literal_suffix) ; [44:10 - 9]
       right: (number_literal) ; [44:13 - 13]
     (expression_statement) ; [45:9 - 14]
      (assignment_expression) ; [45:9 - 13]
       left: (user_defined_literal) ; [45:9 - 9]
        (number_literal) ; [45:9 - 9]
        (literal_suffix) ; [45:10 - 9]
       right: (number_literal) ; [45:13 - 13]
     (expression_statement) ; [46:9 - 14]
      (assignment_expression) ; [46:9 - 13]
       left: (user_defined_literal) ; [46:9 - 9]
        (number_literal) ; [46:9 - 9]
        (literal_suffix) ; [46:10 - 9]
       right: (number_literal) ; [46:13 - 13]
     (expression_statement) ; [47:9 - 14]
      (assignment_expression) ; [47:9 - 13]
       left: (user_defined_literal) ; [47:9 - 9]
        (number_literal) ; [47:9 - 9]
        (literal_suffix) ; [47:10 - 9]
       right: (number_literal) ; [47:13 - 13]
     (expression_statement) ; [48:9 - 14]
      (assignment_expression) ; [48:9 - 13]
       left: (user_defined_literal) ; [48:9 - 9]
        (number_literal) ; [48:9 - 9]
        (literal_suffix) ; [48:10 - 9]
       right: (number_literal) ; [48:13 - 13]
  (return_statement) ; [50:5 - 13]
   (number_literal) ; [50:12 - 12]


weixuanhu avatar Nov 07 '23 03:11 weixuanhu

The queries for C (and thus C++ since it inherits the C queries and adds a few more) don't seem to contain anything catching else if or else, but this seems to be the case for most (all?) languages.

(I wrote a wrong solution before, see update.)

UPDATE: The above doesn't work as I expected. I have made a fork and tested a bit now. I think that replacing the if_statement query with

(if_statement
  consequence: (_) @context.end
) @context

(else_clause
  (_) @context.end
) @context

behaves more like what I would expect. This caputures else if and if as I would expect:

Screenshot 2023-11-08 at 16 18 17 Screenshot 2023-11-08 at 16 18 45 Screenshot 2023-11-08 at 16 19 09

Danielkonge avatar Nov 08 '23 00:11 Danielkonge

thanks Danielkonge. The behavior in your screenshot is just as what I expected.

weixuanhu avatar Nov 09 '23 04:11 weixuanhu

Note: If you want to always include { if you ever put it on the next line instead of the end of the current line, then you need slightly more complicated queries.

(if_statement
  consequence: (_ "{" (_) @context.end)
) @context

(else_clause
  (_ "{" (_) @context.end)
) @context

or

(if_statement
  consequence: (_ "{" @context.final)
) @context

(else_clause
  (_ "{" @context.final)
) @context

seems to work fine for that.

Previous queries: Screenshot 2023-11-10 at 01 26 04

New queries: Screenshot 2023-11-10 at 01 24 20

With the formatting of my previous comment, these queries behave the same.

Danielkonge avatar Nov 10 '23 00:11 Danielkonge

Hi Danielkonge, I am wondering if you will pull your new context.scm code to pull request ? Frankly speaking I am not that familiar with the syntax of scm file ...

weixuanhu avatar Nov 14 '23 02:11 weixuanhu

Hi Danielkonge, I am wondering if you will pull your new context.scm code to pull request ? Frankly speaking I am not that familiar with the syntax of scm file ...

I can make a pull request that includes the else statements like in my pictures, but we should probably have some general consensus for what to include. Should the { always be included here?

Danielkonge avatar Nov 14 '23 13:11 Danielkonge

Hi Danielkonge, I personally perfer the "Previous queries" in your comment, i.e., NOT to always include {. Maybe we can even have an option to turn it on/off to "always in include the { ?

image

weixuanhu avatar Nov 15 '23 00:11 weixuanhu

Hi Danielkonge, I personally perfer the "Previous queries" in your comment, i.e., NOT to always include {. Maybe we can even have an option to turn it on/off to "always in include the { ?

image

To have an option like that is probably not worth it to try to implement and maintain just for c. Instead it would probably make more sense to allow use of custom queries, though I am not sure if that is already possible to do?

Also, I have made a pull request now.

Danielkonge avatar Nov 16 '23 20:11 Danielkonge

Instead it would probably make more sense to allow use of custom queries, though I am not sure if that is already possible to do?

That is already possible.

lewis6991 avatar Nov 16 '23 22:11 lewis6991

Instead it would probably make more sense to allow use of custom queries, though I am not sure if that is already possible to do?

That is already possible.

This has to be defined for every language? Can it be generalized? I think the else is a very important piece of context.

Susensio avatar Feb 16 '24 08:02 Susensio

You'd have to dig into the code and investigate.

lewis6991 avatar Feb 16 '24 09:02 lewis6991