Open FHTheron opened 6 years ago
I like the rationale. I also used to do something similar when I had to use eclipse for some Java code.
What I'm wondering is whether we could define a set of commonly used jump types, i.e. jumping around and jumping out, and add sub-scopes for the actual keyword in question, plus the syntax.
I'm thinking of the following template for this:
keyword.control.flow.jump.<jump-type>.<keyword>.<syntax-suffix>
,
with the jump types
return
, exception
,loop
, and goto
.Are there any more types of jumps that I didn't think of here?
Note that I didn't follow the "out" and "around" terminlogy, because from a color scheme PoV the above distinction makes more sense. (Otherwise break
would get the same color as return
since they're both jumping "out" of something.)
For example, jumping out of a loop in C with break
would be scoped as keyword.control.flow.jump.loop.break.c
.
I'm unsure about assert
, however. It's a conditional jump, similarly to an if
statement that could jump to the corresponding else
if the condition turns out to be false.
The same analogy would apply to conditional jumps in assembler, e.g. jnz
vs jmp
.
And finally, highlighting functions as keywords may be semantically right in some languages, but this is going to be controversal. I see the argument for both sides but don't feel strong enough for either, in which case I'd just stick with the status quo.
While we're at it, maybe add some sub-types for keyword.control.flow
as well, such as conditional
and loop
? Are there more flow statements/keywords that don't fit any of these two and jump
?
The C# syntax is fairly expressive already:
goto
keyword.control.flow.goto
break;
keyword.control.flow.break
else if
keyword.control.conditional.elseif
yield return
keyword.control.flow.return
(arguably, return
and yield break
have more similar jump out semantics than return
and yield return
in terms of control flow leaving the method)
so I like the idea of this proposal being standardized across languages for syntax highlighting purposes. Definitely assert
shoudn't get a keyword
scope in the languages where it is a method, but would still be useful to give it some specific (relevant) scope.
So, I was a bit off with the keyword.control.flow
, since according to both TextMate and ST conventions (which were inherited) keyword.control
is already reserved for mostly flow control, but while keyword.control.loop
also makes sense for a while
keyword, grouping flow control keywords within loops in yet another subscope of that seems inappropriate from a color scheme perspective (again).
That would leave us with a list like the following:
keyword
control
conditional
if
else
elseif
exception
try
catch
import
from
loop (do we even want to standardize sub-scopes of this?)
do-while
for
repeat-until
while
flow
exception (maybe flatten since this is the only exception-related flow keyword construct)
throw
goto
loop (maybe flatten this, too)
break
continue
return
yield
Note that these all represent the general name of the construct, for example if a while loop is initiated with repeat
it should still be a sub-scope of keyword.control.loop.while
, or keyword.control.flow.exception.throw
for raise
. repeat-until
(I'm actually not sure why import
should be a sub-scope of keyword.control
. Seems to make more sense as keyword.import
or keyword.other.import
even.)
@wbond Can this be labeled RFC?
@FichteFoll @keith-hall : How to sort switch
and case
like statements into the tree?
I saw different solutions like
keyword.control
keyword.control.switch
, keyword.control.switch.case
keyword.control.case
, keyword.control.case.in
, keyword.control.case.end
, ...I think all of them are keyword.control.conditional
as well as they just group a chain of if-else constructs in a more efficient way.
That's a yes from me regarding keyword.control.conditional
.
I think the widely used practice currently is to do keyword.control.<keyword-name>
, with the exception of conditional weaved in for if
and family. The problem is that we never really agreed upon a naming scheme here, but I still believe my last suggestion to be pretty close once the parenthesized comments are addressed.
While reviweing #1850 I noticed I never thought about languages that use keywords to terminate control structures (like done
or end
or endwhile
). What about keyword.control.<group>.end
?
While reviewing #1850 I noticed I never thought about languages that use keywords to terminate control structures (like
done
orend
orendwhile
). What aboutkeyword.control.<group>.end
?
Does this mean you'd also want to scope the opener as ...<group>.begin
?
This would mean to scope all kinds of loops (i.e. while
, for
, repeat
, ...) with keyword.control.loop.begin
if the keywords are used to open a loop statement. Keywords like until
, end
, endfor
, endwhile
would be scoped keyword.control.loop.end
then? This arises the question how to scope a while
keyword, if the language allows to put it to the beginning and the end? Use two scopes for it depending on position?
Meta Example
do
bar;
while(foo);
while (foo)
bar
endwhile
Or do you prefer scopes like
keyword.control.loop.while.begin
and keyword.control.loop.while.end
?Not sure if it makes sense or whether it is just too much? How to handle syntaxes which use the same end
keyword for different kinds of loops then? Scope the same word with different scopes? Not sure about that.
Scopes like begin
and end
make sense only if they are used as general scopes which are located in the same level for all statements, which feels sometimes odd. Example:
keyword.control.loop.begin.while
and keyword.control.loop.end.while
keyword.control.loop.begin.for
and keyword.control.loop.end.for
How to handle repeat ... until
loops here?
Finally I find keyword.control.loop.while
vs. keyword.control.loop.end
enough if end is a commonly used terminator keyword for one or more types of loops.
Otherwise keyword.control.loop.<group>
is enough.
Finally I find
keyword.control.loop.while
vs.keyword.control.loop.end
enough if end is a commonly used terminator keyword for one or more types of loops.
That's what I was going with initially, but also for conditionals. Example:
while (foo)
bar
endwhile
if (foo)
bar
endif
while: keyword.control.loop.while
endwhile: keyword.control.loop.end
if: keyword.control.conditional.if
endif: keyword.control.conditional.end
Keywords like
until
,end
,endfor
,endwhile
would be scopedkeyword.control.loop.end
then?
Yes.
How to handle syntaxes which use the same
end
keyword for different kinds of loops then? Scope the same word with different scopes? Not sure about that.
I don't see a problem with that.
Python also has two different scopes for from
, as
and in
depending on how they are used, and I wouldn't want those to have the same.
Lua uses end
for everything, including function definitions.
Scopes like
begin
andend
make sense only if they are used as general scopes which are located in the same level for all statements, which feels sometimes odd.
That's a warranted concern for the case where we want to have both begin
and end
.
Another is languages that don't have keywords to close the control structures.
How to handle
repeat ... until
loops here?
keyword.control.loop.begin.repeat-until
and keyword.control.loop.end.repeat-until
(or alternatively with begin and end at the end)
I believe that leaves us at the following options:
keyword.control.<loop/conditional>.end
regardless of how it was opened; opening keywords as beforekeyword.control.loop.<begin/end>.repeat-until
keyword.control.loop.repeat-until.<begin/end>
Each of these has advantages and disadvantages in general or special cases.
I favor option 1.
Here's an update of my most recent proposal regarding the exact scope names.
import
out of control
. Imports don't/shouldn't affect flow controlflow
(jump) subgroups (exception
and loop
) as they barely provide a benefit andswitch
/select
/case
keyword.control.*.end
keyword
context
block
resource
import
control
conditional
case
else
elseif
if
select
switch
exception
catch
defer
finally
try
loop
do-while
for
repeat-until
while
flow
assert
break
continue
exit
goto
return
throw
yield
*
end
import
from
<keyword-name> (with/using/include/use)
More questions: what about then
in if statements? Similarly, what aboutdo
in for ... do; ... end
?
Edit: added finally
Edit: added defer
and assert
Edit: added panic
Edit: added with
under .import
(indirectly) and
Edit: added 2nd level scope .control.resource
context
Edit: renamed panic
to exit
I favor option 1.
Me too.
Here's an update of my most recent proposal regarding the exact scope names.
Like it.
Maybe add keyword.control.exception.finally
?
I like the dedicated keyword.import
as it really does not belong to control structures. Is it meant for general purpose preprocessor
stuff which is executed by the compiler at compile time or the interpreter at module import time as well? Ask because of #1860 and because of C/C++ using keyword.control.import
for such keywords atm.
More questions: what about
then
in if statements? Similarly, what aboutdo
infor ... do; ... end
?
I tend to scope them the same way as the opening keyword of a loop to ensure them to get the same color. The D PR and Bash use a general keyword.other
or keyword.control
atm.
So, I could see adding keyword.import
, but I'm not sure about removing keyword.control.import
for now, since I don't think many color scheme color keyword
by itself, but I could be completely wrong about that.
For now we may have to use keyword.control.import keyword.import
to allow backwards compatibility.
Ideally the colon on these three lines should have the same scope and whatever changes are made to conditional keyword
scopes should probably apply to the punctuation.section.block
character as well.
conditional
keyword
scopes should probably apply to thepunctuation.section.block
character as well.
This depends on your color scheme. if
, elif
, else
are of keyword.control.conditional
, which would not apply to the punctuation. A punctuation is not a keyword.
You are otherwise right with punctuations and metas to be scoped a bit inconsistent.
Just in case, the word "apply" might have been a bad choice.
I only meant that all those colons should have the same punctuation.section.conditional.block
since they are part of conditional lines, not that they should be scoped as keywords. The "apply" referred to keeping it in sync so that if keyword.control.flow.conditional.python
were to change to keyword.control.flow.conditional.if.python
for example, it will be nice if the colon changed to punctuation.section.conditional.if.block
to match.
Go uses the defer
keyword instead of finally
to declare statements to be excuted when the current scope (in code) is left. Bash's trap
is similar to this. It's not really a "jumping" keyword like return
since it declares what is being jumped over rather than where from, so I'd think of it as being related to finally
and thus get a subscope in exception
, i.e. keyword.control.exception.defer
. Opinions?
I'd vote to add the following scope to the list of defaults
keyword: assert
scope: keyword.control.exception.assert
idea/reason: An assertion is something like a short try
block, which raises an exception if the boolean result of the expression is false
.
I like that and added it to my latest proposal, as well as defer
.
Actually, wouldn't that go more in the direction of throwing an exception conditionally and thus belong to keyword.control.flow.assert
?
None of the flow
keywords is followed by an expression to evaluate. They are instead followed by arguments which are returned only. For instance throw Exception
just creates an object and breaks the linear flow.
But I don't have a strong meaning about it. Basically, flow
is very correct as well.
Assert is special in that it combined conditional branching with flow control that jumps out of the current context. Considering that previous arguments seemed to be more in favor of targeting this special flow control of "exiting/moving the context exactly here", I'd say the jumping part (out of the function to the next try-catch or maybe even the entire program) is more important than the soft implication of a try block saying "something in here might throw".
Maybe someone else could give a third pair of eyes to this?
Now, for a related thing, the ?
operator in rust should probably also get a keyword.control.flow
scope, but I'm not sure which. It results in an Err
type being returned from the current function, which is rust's equivalent of an exception, more or less, but you could also argue it's an assertion because it basically checks for an Err in an rvalue and unwrap that if it isn't. It's different from other languages where the operator just causes the remainder of the line to evaluate to null
and would thus be classified as an operator.
And finally, there is the panic macro/function in rust/go, which is like the ultimate control flow word but not really a keyword? Do we prioritize semantic or syntactic accuracy here and if the former, should we introduce keyword.control.flow[.exception].panic
?
I'd say the jumping part (out of the function to the next try-catch or maybe even the entire program) is more important
This is my view as well. I'd be more interested in the jump than the cause.
This is my view as well. I'd be more interested in the jump than the cause.
Convinced.
... there is the panic macro/function in rust/go,
It looks very much like the die
or dump
in Perl. I assigned keyword.control.flow.[die|dump].perl
to them, even though they are called function in the docs. I found it more useful to make them stand out from "normal" builtin functions as they act pretty much like throw
.
With assert
in mind, we propably should panic
a keyword.control.flow.panic
. An extra sub scope feels a bit overwhelming at the moment.
How about the following keywords?
Python, JavaScript use await
for coroutines, which might be scoped as keyword.control.flow.await
, because it basically causes the caller to block until the asynchronous action has finished. Therefore it influences the control flow.
The keyword with
is used in Python, JavaScript, Pascal.
Python: keyword.control.flow.with
JavaScript: keyword.control.with
According to MDN with Description it somehow extends the scope of a context but does not directly control the flow. It therefore doesn't feel related with keywords like break
, continue
, ... which are scoped as keyword.control.flow
as well.
How about keyword.control.[namespace|scope|storage].with
?
keyword.control.flow.await
definitely makes sense. with
not as much, because it defines an anchor point rather than a jump-away.
It's related to try
and finally
in that it ensures that cleanup happens after a block is left due to reaching the end or a different flow mechanism, but unlike finally
it doesn't directly describe where to jump to or what to do when that happens. Still, this is structurally the closest match I can find and we wouldn't need another third-level scope. So I suggest keyword.control.exception.with
, or alternatively keyword.control.with
.
However, there is another type of with statement, e.g. in Visual Basic, that is not flow-related at all and should probably receive a keyword.declaration.with
scope?
It's related to
try
andfinally
in that it ensures that cleanup happens after a block is left
Have this in mind, too. But keyword.control.exception.with
feels a bit off topic as it is not directly related with try ... catch
control structures.
Why?
A with Class as obj
in Python is mainly meant to handle cleanup, but in JavaScript, Pascal and Visual Basic it also manipulates the content of the block's namespace.
In Visual Basic and Pascal with
is used to simplify expressions by defining an object as global namespace of the code block.
In JavaScript with
is used to extend the global namespace to manipulate the way how unqualified identifiers are searched. It's like a local using namespace ...
expression.
Means, all with
statements (except Python so far) are quite equal.
Not sure about whether to use keyword.control.with
or keyword.declaration.with
, but we should choose one, which makes sense for all syntaxes.
C# has a using
keyword, which performs a similar function to with
in other languages, would it make sense to unify that too even though the keyword isn't with
? generally we go for semantic scopes rather than keeping scopes in sync with language nomenclature, so I'm voting for yes here.
I'm tempted to also say that it may be worth scoping with
differently when it affects cleanup than when it affects the global namespace because they are separate uses and meanings after all.
I'm tempted to also say that it may be worth scoping with differently when it affects cleanup than when it affects the global namespace because they are separate uses and meanings after all.
Definitely, imo. These two usages are nothing alike.
I guess we can categorize with
(and using
) into 2.5 categories:
with … as …:
using
or with
keywords), as used in JavaScript, Visual Basic, C#, Pascal, C++, ….
using
).With
in VB, using
in C#?)Ideas:
keyword.control.resource.with/using
or keyword.control.exception.with
keyword.import.namespace.with/using
keyword.other.with
?keyword.declaration
serves a different purpose and shouldn't be used for with
, but I find it hard to come up with a concrete scope name for 2.2.
@keith-hall: C# has a
using
keyword, which performs a similar function towith
in other languages, would it make sense to unify that too even though the keyword isn'twith
? generally we go for semantic scopes rather than keeping scopes in sync with language nomenclature, so I'm voting for yes here.
Seconded. Porting a using (var … = …) {…}
in C# to IronPython uses with … as … :
syntax. These are currently scoped keyword.control.using
.
The other two using
s I have used in C# are analogous to import
in Python, both scoped as keyword.control.namespace
:
using System.IO;
= import io
using Bar = Namespace.Bar;
= from Namespace import Bar
(as Bar
)@FichteFoll:
keyword.control.resource.with/using
orkeyword.control.exception.with
- Not related to control flow.
keyword.import.namespace.with/using
keyword.other.with
?
try
block. It's mostly used to ensure disposal of resources (yes, even if there's an exception).keyword.import.namespace.with/using
makes sense. There might be a case for the 2.ii, but I haven't encountered it.The 2nd level scope keyword.import
is not yet used anywhere. All kinds of imports use keyword.control.import
instead. Not sure whether to start using the former one at this point.
The meaning of the keyword in different syntaxes is:
Syntax | usecase |
---|---|
C++ | add a namespace to the head of the scope chain for (unqualified) identifier lookup |
C# | add a namespace to the head of the scope chain for (unqualified) identifier lookup |
JS | add a namespace to the head of the scope chain for (unqualified) identifier lookup |
Pascal | add an object to the head of the scope chain for (unqualified) identifier lookup / shorter access to object attributes/methods |
Python | context control, no namespace/scope manipulation |
VBScript | add an object to the head of the scope chain for (unqualified) identifier lookup / shorter access to object attributes/methods |
*) The rule applies to the using
keyword in C++/C#.
The best matching existing scope which describes the majority of use cases of extending the namespace for identifier lookup (except Python) is:
keyword.control.import.[using|with]
I'm with you on keyword.control.import.[using|with]
, except I'd like to get rid of control
at some point and am undecided on using
or with
. Neither of these seem to win over the others, because they both describe their effects to a similar level. By the way, Rust uses use
.
Any recommendations for Python's with
case? So far, the only applicable suggestion so far seems to be my own of keyword.control.exception.with
, emphasizing how it relates to try-finally.
I agree with keyword.import
being a proper scope for it, but a lot of syntaxes need to be changed to keep things together. To avoid fragmentation, I'd suggest to finish changes according to this RFC and update string interpolation first. I think the Bash could need some tweaks to string interpolation. Groovy seems to need even more work about all of that. I am on tweaking Batch File atm.
The using
and with
are just the names of the keywords as if
in keyword.control.conditional.if
. There is no special semantic meaning.
Python's with
seems to be something special as it just acts like a block with a special variable being passed to. Don't have a better idea than keyword.control.exception
so far. From the point of colouring, it would even be the best solution.
I agree with
keyword.import
being a proper scope for it, but a lot of syntaxes need to be changed to keep things together. [But let's finish the current changes before taking this on.]
Agreed.
The
using
andwith
are just the names of the keywords asif
inkeyword.control.conditional.if
. There is no special semantic meaning.
Agreed.
Python's
with
seems to be something special as it just acts like a block with a special variable being passed to. Don't have a better idea thankeyword.control.exception
so far. From the point of colouring, it would even be the best solution.
I still like keyword.control.resource.with
for this (and the corresponding keyword.control.resource.using
for languages that use that word instead). The usage does not imply anything about exceptions, only about safe disposal of an object.
There is no special semantic meaning.
The reason for my question was that we'd want to use one scope for the same semantic meaning, even if the keywords in different languages differ. But I guess within the keyword.import
scope, we already know that the keyword is importing something and adding something for grouping with and using seems superfluous compared to some languages doing the same with import
or #include
.
I still like keyword.control.resource.with for this (and the corresponding keyword.control.resource.using for languages that use that word instead).
Do you have any examples for other languages using resource-based keywords like Python's with
? I guess we can add a keyword.control.resource
scope as it is different enough from the other scopes on that level (and then use the literal keyword for the next level).
I updated my proposal above.
Do you have any examples for other languages using resource-based keywords like Python's
with
? I guess we can add akeyword.control.resource
scope as it is different enough from the other scopes on that level (and then use the literal keyword for the next level).
Yes, C# is one. I made reference to it above, but I didn't write out a sample, so it may not have been super-clear. This is excerpted from the StreamReader
examples:
Char[] buffer;
using (var sr = new StreamReader("TestFile1.txt")) {
buffer = new Char[(int)sr.BaseStream.Length];
await sr.ReadAsync(buffer, 0, (int)sr.BaseStream.Length);
}
Console.WriteLine(new String(buffer));
It's basically the same as this "Python:" 😉
with StreamReader(filename) as sr:
# do buffered stuff
Even if you have a return
inside the braces, C# will make sure to call Dispose()
on the StreamReader
, which becomes kind of nice when you nest them in this very contrived example:
using (var httpResponse = webRequest.Response.GetResponseStream())
using (var zipArchive = new ZipArchive(httpResponse))
using (var json = new JsonTextReader(zipArchive))
{
return new JsonSerializer().Deserialize<MyType>(json);
}
Apparently GitHub doesn't know you can stack them without extra braces, but ST3 does. (Thanks @gwenzek!)
All right, thanks. Now, one final question for confirmation: Java uses try
for both try-catch and try-resource. The latter is indicated by an opening paren following the try
, which is enough to differentiate between them in a syntax definition. Now, should try receive a different scope based on which version is being used? keyword.control.exception
vs keyword.control.resource
(Imo yes, because these are different enough use cases. Also, most color schemes likely only target keyword.control
as a whole currently, so we wouldn't be breaking anything in that regard.)
I think something like keyword.control.resource
is appropriate for the use cases of VBS and Pascal as well.
Would keyword.control.context
be a possible maybe more general alternative then?
The common idea behind all with/using/try/...
concepts is to control the context of the executed code block by eighter ensuring resource disposal, extending the scope of variable lookup, ... .
This way, the keyword.control.import
or later on keyword.import
are dedicated to import like statements (alias preprocessor
) only. I still find the idea of coloring preprocessor/import statements differnetly, than normal runtime code.
Thoughts?
Would
keyword.control.context
be a possible maybe more general alternative then?The common idea behind all
with/using/try/...
concepts is to control the context of the executed code block by eighter ensuring resource disposal, extending the scope of variable lookup, ... .
This is acceptable. =)
The common idea behind all
with/using/try/...
concepts is to control the context of the executed code block by eighter ensuring resource disposal, extending the scope of variable lookup, ... .
Yes, that makes sense. However, since they don't really affect control flow, I'd like to suggest keyword.context.resource
and keyword.context.import
in the event we can afford moving them out of keyword.control
since, as you mentioned, they don't affect control flow but rather the context.
I assume we would still have catch
and finally
in a keyword.control.exception
then?
As it turns out more languages (e.g. Ruby) use keywords to control the namespace or the variable lookup, I'd suggest a more general wording for a scope.
In https://github.com/sublimehq/Packages/pull/2156#discussion_r341080243 the keyword.control.context
was made, which seems to be an appropriate scope for context manipulating keywords in general. It also seems to be a good solution for the discussed keywords above with
, using
, ..., which all manipulate the variable lookup of a certain block of code by either importing namespaces or injecting new variables to the context.
An alternative might be keyword.control.block
if we want to create an analogy to the existing punctuation.section.block
scope.
I agree with context
beeing a good choice for these kinds of keywords, ideally with another subscope that describes their effect on the context, but I would like to hear @wbond's opinion on adding keyword.context
(and keyword.import
) because they do not affect control flow and thus shouldn't be in keyword.control
. We already added keyword.declaration
, although we have an additional fallback scope if color schemes don't define a color for keyword
.
A compromise might be keyword.other.context
?
With regards to https://github.com/sublimehq/Packages/pull/2156#discussion_r341741331
Placing the exception
under keyword[.control].context
arises the question why not to place conditional
or loop
under it, too? They also create new contexts with local variables etc. which are cleaned up if the local block is left. I think a try .. catch
block is nothing else then a - simple to write but more complex in function - flow control statement. It just helps to avoid dozens of if ... if else ... if else
statements for error checking/handling.
Next to the existing scopes two major questions came up recently:
with
or using
in languages like Python, Pascal or VBScript , which denote the beginning of a block of code with an extended scope for identifier lookup?begin
or do
in Ruby (or begin
in Erlang)?The current situation is:
keyword.control.flow
as those are reserved for keywords like return
etc. to exit a block of code (or context), which enables a color scheme to color them differently from the conditional
or loop
keywords.{ ... }
code block in C/C++.keyword.control.resource
was the result as we only discussed keywords of 1.exception
).Conclusion:
The only thing we need is a replacement scope for keyword.control.resource
which can be generally applied to the discussed keywords. Maybe the ones I previously suggested - with the arguments for or against each of them.
I don't find that looking too bad when completing your scope scheme @FichteFoll.
keyword
control
block/context
begin
do
with
using
conditional
...
exception
...
loop
...
flow
...
A color scheme can address keyword.control
for general purpose keyword colors and than add specialization for maybe keyword.control.flow
only to only scope return
etc. diffently. ... or add a color for each of them.
With regards to the keyword.import
I want to suggest to better use a 2nd level scope name, which denotes to all kinds of preprocessor directives including #define
, #if
or whatever. While import
could be understood as such, it's somehow irritating because of its current use to denote #include
or import
.
I know there are differences between compiled languages like C/C++ and interpreted ones, but in both cases all imports or defines are made before normal runtime code is executed uppon initialization of a module. A 2nd level scope should just address both.
We should keep the import & preprocessor discussion at #1860.
Generic block keywords like do
or begin
definitely sound like good candidates for keyword.context.block
.
For the resource context keywords, keyword.context.resource
seems to work pretty well, too.
Conditional statements or keywords primarily affect control flow and the fact they may also involve different scoping is secondary and not even true for all languages (e.g. Python), so they should not go into .context
.
Re-reading the last few posts here, I'm not actually sure where the proposal to move try
and catch
to keyword.context.resource
came from. I mention it in https://github.com/sublimehq/Packages/pull/2156#discussion_r341741331, but I don't understand why. Probably as a reaction to your comment at https://github.com/sublimehq/Packages/pull/2156#discussion_r341080243 without thinking it through.
They affect control flow more than context, just like with conditionals, so they shouldn't be moved away from keword.control
.
I'll update the proposal above with the recent discussion points.
What do you think of keyword.context.import
for the with/using keywords that affect namespace resolution for the current context only?
We should keep the import & preprocessor discussion at #1860.
Yes, just forgot about this to be pending.
... where the proposal to move try and catch to keyword.context.resource came from.
From Java, I guess. It supports something like try (var = new Class) { ... } catch { ... }
which is similar to pythons with
statement. But I would keep it a normal keyword.control.exception
, too.
Otherwise keyword.context.block
and keyword.context.resource
sounds not too bad, if we really need to distinguish them. I tend to not think so, but maybe I've not learned enough syntaxes so far to judge that. :-)
if we really need to distinguish them.
I agree there is something weird about .context.block
. "context" already implies some sort of block structure and .context.resource
most likely does, too. Scopes and life-times may be an argument, but in Python scopes inherently leak their locals, for example.
Would this mean we should braces in C-like languages as keyword.context
as well? Operators don't receive punctuation scopes either.
Still, maybe keyword.context
is already enough? (Or stick to keyword.control.context
after all?)
In https://github.com/sublimehq/Packages/pull/2156#issuecomment-557211975, @wbond mentioned keyword.control.flow.termination
for grouping the keywords that terminate excution, like exit
, panic
, die
etc. I like that. (Edit: however, that cannot be applied to functions performing the same operation)
He also voiced his support for keyword.control.block
and keyword.control.context
over keyword.context
. Would you mind explaining these choices, @wbond?
To me, these types of keywords are explicitly not control-flow-related.
Intro
First let me define what I mean with "jump" keywords. Things like
if
andelse
are of course also flow control keywords and they do result in the CPU executing branches, but I'm more specifically considering the jump in terms of visual code flow. For example, a subtlegoto
that radically changes the execution flow isn't always as visible as the effect it has.Current scopes
In
C
these currently get the scopekeyword.control.c
, but this scope is also used (correctly) forif
,while
, and other actual flow control keywords.In
Python
the scope iskeyword.control.flow.python
and includes loop keywords as well asreturn
andraise
.New scopes
I suggest that some of these flow control keywords get scoped as two new flow control types - one type jumps within the current frame/call stack the other jumps out of the current call stack.
C
goto
break
continue
return
exit()
assert()
C++
C
C
throw
Python
break
continue
pass
.return
(already scoped withkeyword.control.flow.return.python
)raise
(already scoped withkeyword.control.flow.raise.python
)assert
yield
?And many more languages with similar keywords/statements.
Alternative
The same colouring can be achieved if all languages define unique scopes for all flow control keywords. This will avoid having to define what each keyword's jump type is.
Python
has this for 2 keywords,Shell-Unix-Generic
seems to havekeyword.control.*.shell
for all keywords. A colour scheme can then add each of these to colour them as desired. It does mean that the colour scheme now defines what jump type a jump keyword is, which may or may not matter.Example screenshots
Current:![current](https://user-images.githubusercontent.com/16208294/31589922-4f4ca894-b209-11e7-8054-5ad6ed4559eb.png)
Proposed, using new scopes with illustrative colours:![proposed](https://user-images.githubusercontent.com/16208294/31589925-523de856-b209-11e7-8aa4-fed2b2b950a6.png)