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

Ability to add line continuations in multi-line contexts #172

Open
Tracked by #204
Xophmeister opened this issue Jan 13, 2023 · 6 comments
Open
Tracked by #204

Ability to add line continuations in multi-line contexts #172

Xophmeister opened this issue Jan 13, 2023 · 6 comments
Labels
P3 minor: not priorized type: feature request

Comments

@Xophmeister
Copy link
Member

Xophmeister commented Jan 13, 2023

Is your feature request related to a problem? Please describe.
In some languages (e.g., Python, Bash), multi-line contexts require a line continuation character; usually an escaped newline.

I don't believe -- but I'm not certain! -- that it's possible to distinguish between a single-line and multi-line context, in the query language. That is, in the sense of performing different actions in different contexts. Therefore, line continuations can't be inserted as though they were delimiters, because they'd be inserted in all contexts.

Describe the solution you'd like
As this would apply to the source as a whole, perhaps a new directive:

(#multiline! STRING)

The default would be (#multiline! "\n"). However, this could be overridden to something like (#multiline! " \\\n") -- or whatever the language's escape character is -- when needed.

Any newlines that are added by Topiary in a multi-line context will use this STRING, rather than a simple \n.

Describe alternatives you've considered
One could assume the programmer knew what they were doing and thus look for manually added line continuation nodes. Then queries could be written that target these characters: if they exist, we're in a multi-line context; otherwise, single-line.

My gut feeling is that this may incorrectly target non-line continuation nodes. However, even if that's not the case, it would double the number of queries required (i.e., an explicit multi-line and single-line version, for each).

@Xophmeister
Copy link
Member Author

Xophmeister commented Jan 16, 2023

A rule that explicitly targets the line-continuation and appends a hardline was suggested, so multi-line Bash commands preserve their formatting. i.e.,:

(command
  "\\" @append_hardline
)

Unfortunately, the Bash grammar rejects this query outright with an Invalid node type error 😞

@Niols
Copy link
Member

Niols commented Jan 16, 2023

I'm actually quite curious to see how that will unfold. I don't know about bash, but in POSIX Shell, the line continuation is not handled in the parser but in the lexer. If the tree-sitter grammar follows the official one, I suppose it would not appear there. (Again, bash is very much not POSIX Shell so it might be doing its own thing there.)

@Xophmeister
Copy link
Member Author

On further thought, having this apply to the whole source will be too general; even if it's limited to just softlines. For example, I've specified the following queries to format Bash compound statements:

(compound_statement
  .
  "{" @append_spaced_softline @append_indent_start
)

(compound_statement
  "}" @prepend_spaced_softline @prepend_indent_end
  .
)

With the proposal in the OP issue, that would format a multi-line compound statement like so:

{ \
  whatever \
}

That's neither what we want, nor -- in this case -- is it valid, as this code is equivalent to { whatever } which is syntactically incorrect.

Perhaps a construct more like this, where specific nodes are tagged as requiring line continuations would be better:

; Set the continuation string for softlines globally...
(#line-continuation! " \\")

; ...but only apply it to tagged nodes
[
  (some)
  (node)
  (types)
] @require_line_continuation

Or perhaps delimited softlines (#175) would serve both cases, where the line continuation is the delimiter.

@Xophmeister
Copy link
Member Author

See #205 for a possible solution.

@nbacquey
Copy link
Member

nbacquey commented Apr 6, 2023

Does #354 solve this issue, with (@append_delimiter) and (#multi_line_only!)?

@Xophmeister
Copy link
Member Author

Does #354 solve this issue, with (@append_delimiter) and (#multi_line_only!)?

In principle, yes 🎉 It's a little bit fiddly, for line continuations, because you have to @append_delimiter at every expected line-break (apart from the last one). It can be done, though. For example, these rules added to the Bash rules:

(command
  (_) @append_delimiter @append_spaced_softline
  .
  (_)

  (#delimiter! " \\")
  (#multi_line_only!)
)

(command
  .
  (_) @append_indent_start
) @append_indent_end

...correctly produce this output:

command \
  --option1 \
  --option2
command --option1 --option2

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
P3 minor: not priorized type: feature request
Projects
None yet
Development

No branches or pull requests

4 participants