imba
imba copied to clipboard
Use `=` instead of `:` for style properties
This proposal has been in the back of my mind for a while and I'd like to float it here so that we can discuss it thoroughly. We can't change this after we hit 2.0 final, so we need to discuss before that. The basic proposal is to use key=value
instead of key:value
for style properties.
It is hard to get a feel for it without trying it with correct highlighting+tooling but I'm confident it will look and feel just as good once used to it. More importantly, there are many arguments in favor of making this change.


Why
-
:
is already a bit ambiguous due to::before
,::backdrop
and other pseudo-elements. - We now use the
@
for style modifiers like@hover
and@focus
, and for event handlers@click=...
, and for decorators@lazy def ...
, and for upcoming accessorsprop item @ref.local ...
. The only reason for using@
for style states was that we usekey:value
for properties. - We can use
@
for the things it is actually used for in css today, like@font-face
,@layer
,@supports
etc. So the syntax will move away from css in terms of using=
instead of:
for properties, but closer since:hover
and@font-face
will be the same. - The
:some-state
will now universally be related to styles, it is not a concept elsewhere in imba. This means that we could down the road allow setting style pseudo-states on elements like<div :selected=condition @click=...> ...
- Since colon-prefixed identifiers is not a thing in imba 2, they could be deeply linked with styles. So setting
:selected = yes
could set a pseudo-state that is accessible from styles and code. - There is some inherent difference between
header@hover
andheader@dark
, in that@hover
is a pseudo state of the element, but@dark
is a general pseudo-state of the app itself. This separation would be cleaner withheader:hover
andheader@dark
. - The
=
sign is not used for anything in styles, yet its meaning is universally understood in most languages.
Why not
- For those who have used imba2 for a long time it might take some time to change the muscle memory
- Copying regular css styles into imba will be more cumbersome without help from tooling
- May feel even more different than css, scaring away potential new users
- Can be a bit of pain to migrate.
Migrating
It is easy to write a script that can take the current syntax and apply the changes automatically. It will still be an awkward transition for sure. The easiest first step would be to allow both for a while, since adding support for =
will not break any existing code. Everything will work the same until we start to allow :hover/:focus
++ for pseudo classes. So we could make sure the tooling, highlighting etc works nicely first.
I am very open to feedback and input here - I'm not set on this change but I would like to consider it while we still can.
First thoughts after reading:
- This is the perfect time for a migration
- The other advantage is becoming more cohesive with the rest of Imba.
key=val
means the same thing also in styles. -
bg@md:hover=green4
seems better thanbg@md@hover:green4
as:
takes less space - In terms of feeling, the
=
sign is further than:
in the keyboard but doesn't require holding theshift
key. But in the other hand, we're used to typingprop
,space
,=
thenspace
when assigning to variablesa = val
. So that definitely requires muscle memory adjustment.
It unlocks some nice features and we can overcome most challenges with tooling. So memory adjustment
seems like the only major issue IMO.
Tooling
For copying things from the internet, I suggest we support that as a first class feature in VSCode Imba. We might need a rewrite anyway to account for typescript's very breaking change for tooling but that's another topic.
I suggest we add a paste and convert
@cmd+shift+V
and convert current file
command that detects the source type (js, css, yml, json or old imba) and converts it to imba code on the fly.
Questions
- Could we support multi line values like
grid-template*
with the new=
syntax?
@haikyuu, multi-line values could be supported with or without "=" because the symbol before the list could be anything; it's the newline and indentations that Imba has to look out for. That is how other languages like Python, Ruby, Nim, and others work as well.
On a separate note, I agree that the =
operator can make the style syntax less ambiguous; however, it would make the style syntax more like a preprocessor (SASS) than CSS, which could increase Imba's learning curve.
On Nov 4, 2022, at 4:56 AM, Sindre Aarsaether @.***> wrote:
I am very open to feedback and input here - I'm not set on this change but I would like to consider it while we still can.
I think the the proposal makes a lot of sense and I’m not at all wedded to legacy CSS notation. Internal logical consistency is far more valuable, although this makes me wonder if we should revisit object literal notation as well, so instead of having:
const object = { a: 'foo', b: 42, c: {} }
const person = name: 'Bob Smith' age: 32 gender: ‘male’
let todos = [ title:'one' completed:yes
title:'two' completed:no ]
Would it possibly make sense to use:
const object = { a = 'foo', b = 42, c = {} }
const person = name = 'Bob Smith' age = 32 gender = ‘male'
let todos = [ title = 'one' completed = yes
title = 'two' completed = no ]
Then we could use the same syntax to globally work with style and event modifiers and handlers in bound data to produce dynamically filtered views and behaviors on object member values that might be used in.a large number of presentation contexts without having to represent them as tags:
const person = title = “Los tres programadores atrevidos" @hover = memoize googleTranslateToEnglish # invoke googleTranslateToEnglish whenever title is used in a hovered context .alt = memoize googleTranslateToJapanese # googleTranslateToJapanese whenever title is use in an alt hovered context year = 1980 publisher = Penguine @click.left.ctrl = imba.router.go “published-by-penguine” titleYear = “{title} — {year}” # dynamically update the title component when used in an @hover or @hover.alt context
It might also be nice we had a function invocation modifier syntax so we could say:
invokeSlowNetworkAPI.eagerly.asynchronously.withMemoization(onData)
While on the subject of syntax departures, have we ever considered YAML’s pipe ‘|' notation for defining indentation delimited multi-line strings?
Finally, I think we should reserve some syntax now to add Hygenic Macros at some point in the future!
Warmest Regards,
Peter Wasilko
(edited for grammar)
@peter-wasilko, I agree with you on the "internal logic consistency," but I think it would make Imba look more like CoffeeScript or YAML than JS/TS/JSON, which could make Imba lose traction like Ruby and CoffeeScript.
My thoughts on this conversation so far are that in order for Imba v2 to gain more traction than v1, the syntax will need to be balanced out. I like most of the features Imba v2 has right now, such as do
blocks, array comprehensions with for...in
loops, the terser HTML syntax, the more terse yet flexible function calls, and the (potential) CSS =
operator, but I think a few features would be pushing Imba towards Ruby and CoffeeScript, which, as I mentioned before, could make Imba v2 lose traction.
I am all hands up for any improvement.
@somebee, I am wondering if we need an aggregate issue for syntactical improvements, so the core team could coordinate the improvements with developers working on syntax highlighters/plugins, and those improvements are documented. If so, I would recommend aggregating this one with #758 and possibly #752.
I don't mind switching to =
.
:some-state will now universally be related to styles
If this syntax change is what opens up this behavior without needing to use another convoluted character, then I think it's worth it.
However, I think that's the only concrete reason I'd be for this. I personally don't think being at parity with vanilla CSS is a concern, and I'm not sure the ambiguity between the semantics of things like @hover
and @dark
matter enough. After all, things work as-is, right? And I haven't felt particularly confused by any of it.
As far as the why nots, I think all of those can be pretty easily addressed. Copying styles into Imba is already a bit cumbersome, we should make tooling for that anyway.
Using space and comma as the delimiters might be worth exploring.
css bg blue, c red, p 5px 10px, bd 1px solid blue, m 4 4
I feel that It's much faster and more comfortable to type than both =
and :
, which is relevant because CSS is probably what we type the most when writing UIs. It seems easy to parse since each property is delimited with a comma meaning the first space-separated string will always be the property name, and it adds additional clarity to when properties that accept multiple arguments end.
=
seems like the strongest contendor for visual grepping though. It's hard to know how comma+space would compare with syntax highlighting.
Using space and comma as the delimiters might be worth exploring.
css bg blue, c red, p 5px 10px, bd 1px solid blue, m 4 4
I feel that It's much faster and more comfortable to type than both = and :, which is relevant because CSS is probably what we type the most when writing UIs. It seems easy to parse since each property is delimited with a comma meaning the first space-separated string will always be the property name, and it adds additional clarity to when properties that accept multiple arguments end.
@familyfriendlymikey, I see where you are coming from, but how would CSS selectors work with the space and comma syntax? We also need to take issues like #381 into account, which is why I was suggesting an aggregate issue for syntactical enhancements.
Hi All,
I really wish we had Hygenic Macros or some sort of Sweet.js inspired pre-processor so we could experiment with Syntax Rules and test alternate notations without modifying the core language.
The Racket Community has really leveraged that sort of tech to the point that DSL creation is a normal coding mode for many of its users.
Warmest Regards,
Peter J. Wasilko
On Nov 7, 2022, at 10:30 AM, Ivan Rodriguez @.***> wrote:
@familyfriendlymikey https://github.com/familyfriendlymikey, I see where you are coming from, but how would CSS selectors work with the space and comma syntax? We also need to take issues like #381 https://github.com/imba/imba/issues/381 into account, which is why I was suggesting an aggregate issue for syntactical enhancements.
@peter-wasilko, I like the idea of hygienic macros, and the closest language I know of that has that macro implementation and Is not a lisp is Julia, which has many features that are similar to Imba's (without the HTML and CSS). However, the macro system would probably need a compiler overhaul.
@peter-wasilko's comment on macros has my gears turning right now. Since around May/June of this year, I have been working on my own virtual machine, ExtVM (examples can be found here, and here is one for macro usage), until recently (I've been busy lately). While I was writing ExtVM, I have been developing a new algorithm for traversing and validating the abstract syntax tree (AST) of a program written in the object code. I do not want to pollute this issue with the details unless @somebee and the core team want more info about the algorithm.
TL;DR: Skip to the second paragraph unless you are fine with statistics.
I was able to do some research on the big three CSS preprocessors (SASS, Less, and Stylus), and regarding GitHub star count, Less takes the lead with 16k+ stars, followed by SASS and Stylus with 14k+ and 11k+ stars respectively. I could not use NPM trends because node-sass
got the axe. With those numbers in mind, I can say that I think the "it's just CSS" paradigm is still hanging around for a while, and Less is closer to CSS than than SASS and Stylus; that is like the "it's just javascript" paradigm is lingering, which is why there is a current discussion in angular/angular#43485 (I suggested dropping the pipe syntax, which led to the discovery of a canonical design issue), and the paradigm is why Vue 3 dropped its support for filters in templates.
Excuse me for the tangent. If I could rank where Imba is and where Imba could be regarding its CSS syntax, I would say that Imba is more like SASS (in the middle of the three) with either :
or =
, and the space and comma syntax would look more like Stylus (the last of the three). That is why I was suggesting balancing out Imba's syntax.
I am trying to dissect the compiler, but I cannot find any .jison
files for the parser. I found src/compiler/grammar.imba1
in the imba
package, which said that the grammar was generated by a .jison
file
I am trying to dissect the compiler, but I cannot find any
.jison
files for the parser. I foundsrc/compiler/grammar.imba1
in theimba
package, which said that the grammar was generated by a.jison
file
The grammar file is the one you have in the link grammar.imba1
and jison is the tool that generates the parser.
The Imba parser is generated by Jison from this grammar file
I would take the change now, rather than later. I'm all about the benefits. I understand the interest in making it easy for newcomers, but how much more friction is this really going to add? I don't think this will make or break a decision to like or try Imba. I already made a snippet converter to convert vanilla css snippets to Imba. So it would only take a small update to it. I'm sure some of the other brilliant users can make better converters, and vscode extensions for that purpose.
@ericvida, you are correct. The :
->=
is easy to implement, but the problem would be with parsing the space and comma-delimited syntax.
@somebee, @IRod22
How about we use strictly colon (no-space) :
for style states, and strictly use colon+space :
for property values?
global css c:hover: red
Would that be too confusing?
@ericvida, that would look confusing. especially if element selectors were being used (which I think is required for global css
declarations BTW). @somebee, @haikyuu, this might need coordination/aggregation with other issues I mentioned before; the reason being is that all of those issues, (possibly) issue #770, and this issue deal the Imba compiler/syntax.
Everyone, I was looking at the MDN docs for @font-face
declarations, and there are a few things that stuck out to me about the src
descriptor:
@font-face {
font-family: "Trickster";
src: local("Trickster"),
url("trickster-COLRv1.otf") format("opentype") tech(color-COLRv1), url("trickster-outline.otf")
format("opentype"), url("trickster-outline.woff") format("woff");
}
Notice how the syntax involves comma-separated and space-separated lists. That definitely will need further discussion or a separate issue.
Hey guys, I'm new to Imba, but that may be a good thing in this discussion because I'm not used to the syntax yet. I've never coded a project in Imba, so I don't expect certain things to be in certain positions of the code.
I've also been designing a new language (I have been for the past 5 years), and have been collecting feedback from friends and strangers over this time. So here are my two cents:
- We pick up visual clues without even noticing. Seeing a bunch of
key: value
automatically registers as an object definition or CSS - Btw, object definitions and CSS rules use the same mental model, at least for me. In both, you are stating what the values of the properties are as opposed to storing them in variables. Of course, the values will later be stored in memory but I see a difference between the statements "this is it" and "assign this value there". That's why (I think) colons are also used in type definitions and JSON.
- I also think it's better not to reuse tokens when possible. The rules for different meanings of tokens depending on the context are invisible for newcomers and are to get just by reading the code. (this is in reference to a suggestion that the colon
a:b
meant something while ina: b
it would mean something else) - I really like the
@
for states because I see it and I thinkat that state
- Familiarity shouldn't be undervalued. It makes adoption a lot easier. I learned Imba in just a few hours exactly because I didn't have to remap too many things. I think that would be true for people who know CSS, Sass, Pug and Ruby
- About the colon in
::before
, for me, colon meansaccess a special state
on a selector. So in:
+:before
, the first:
tries to access a state on avoid
selector (void:
), which creates a pseudo-element, and then gets a void state, returning the default state. That element is the placed in the DOM using a pseudo-class (:before
). So the long version of::before
would bevoid:void:before
or(new Element()):default:before
That's it guys. I may be way off-base since I've only known Imba for a day, but hope those thoughts contribute in some way
Congrats on an awesome language!