Replies: 17 comments 108 replies
-
Proposed S-expression syntaxNOTE that the (def-widget something [arg]
(box {:class arg
:halign "start"}
(text "Click this button:")
(button {:onclick "notify-send 'test' 'message'"}
(text "some_script"))))
(def-var some_var "foo")
(def-script-var some_script {:interval "1s"}
"date | sed 's/:/X/g' | rev")
(def-window foo
{:anchor "center"
:width "100px"
:height "10%"}
(something {:arg some_var}))
|
Beta Was this translation helpful? Give feedback.
-
Another, kotlin-inspired optionwidget something(arg) {
box(class = arg, halign = "start") {
text { "Click this button:" }
button(onclick = "notify-send 'test' 'message'") {
text { some_script }
}
}
}
var some_var { "foo" }
scriptvar some_script(interval="1s") {
"date | sed 's/:/X/g' | rev"
}
window foo(
anchor="center",
width="100px",
height="10%",
) {
something(arg = some_var)
} This isnt all that bad in the widget definition, but as soon as it gets to the other parts, it get's weird. Eww is not a programming language, and mapping the syntax of one to eww doesn't really work. I strongly prefer sexpressions over this for now, although I can see how others may prefer something like this. |
Beta Was this translation helpful? Give feedback.
-
services.eww = {
config = {
definitions = {
something = [
("box" { class = "{{arg}}"; halign = "start"; } [
"click this button:" (button { onclick = "notify-send 'test' 'message'"; } [
"{{some_script}}"
])
])
];
};
variables = {
variables = {
some_var = "foo";
};
script_vars = {
some_script = {
delay = "1s";
command = "date | sed 's/:/X/g' | rev";
};
};
};
windows = {
foo = {
geometry = {
anchor = center; # dunno if this would have to be in ""
width = "100px";
height = "10%";
};
widget = [
("something" { arg = "{{some_var}}"; } [])
];
}
}
};
}; Quick nix solution I hacked together, based on what was discussed in #nixos on the nix discord server yesterday. And they even got a semi working transpiler to work, so I could have transpiled this to xml right now. |
Beta Was this translation helpful? Give feedback.
-
I prefer the first syntax more that I look at it. This is my take on its formatting and weird mixture of different styling and conventions. I have also made some other changes. Not sure if anyone'll like it though. I don't know if this is possible too. (include-file "path_to_file")
(def-widget name [args]
(box [class="some-class", halign="start"]
(text "Click Here")
(button [onclick="notify-send 'test' 'message'"]
(text "some_scipt")
)
)
)
(def-var some_var "foo")
(def-script-var some_script [interval="1s"]
"date | sed 's/:/X/g' | rev"
)
(def-window somewindow [anchor="center", width="100px", height="10%"]
(something [arg=some_variable])
) Notes / What's Different / Other things
|
Beta Was this translation helpful? Give feedback.
-
JSON shares a lot of the upsides S-expressions possess, but without looking too weird. Directly converting the XML to JSON is also supported, but looks kind of messy. There's also the fact that a lot of people don't like to use JSON because of its association with JavaScript or simply because they don't like the way it looks. As you said for S-expressions,
{
"eww": {
"definitions": {
"def": {
"box": {
"button": {
"onclick": "notify-send 'test' 'message'",
"text": "{{some_script}}"
},
"class": "{{arg}}",
"halign": "start",
"text": "click this button:"
},
"name": "something"
}
},
"variables": {
"var": {
"name": "some_var",
"text": "foo"
},
"script-var": {
"name": "some_script",
"interval": "1s",
"text": "date | sed 's/:/X/g' | rev"
}
},
"windows": {
"window": {
"geometry": {
"anchor": "center",
"width": "100px",
"height": "10%"
},
"widget": {
"something": {
"arg": "{{some_var}}"
}
},
"name": "foo"
}
}
}
} |
Beta Was this translation helpful? Give feedback.
-
I have very little experience with UI-related stuff, HTML, CSS, js still give me nightmares. Though when fiddling around with frontend I came across elm. Which felt way better to do UI stuff compared to HTML/CSS/js. I am not sure but something like that could be super helpful here too from a user's perspective. From a development standpoint, I really don't know (if it is even possible). import EWW.ScriptUtils exposing executeScript, executeCronScript
import EWW.UI.Components (row, div)
import EWW.UI.Attributes (centerX, centerY, width, height)
soemthing script =
div []
[ text ("click this button")
, button [onClick (NotifySend "text message")] (executeScript script)
]
some_var =
"foo"
script_var =
executeCronScript (seconds 1) "date | sed 's/:/X/g' | rev"
main = window []
[ row [ centerX, centerY, width (px 100), height (pct 10) ]
[ div [ alignRight ] [ something some_var ] ]
]
|
Beta Was this translation helpful? Give feedback.
-
I'm not surprised that alternatives to XML are being considered, but I'd like to start a discussion challenging this. When I first saw this project, I was excited about it because I have never made a GTK applet, but I have many years of HTML under my belt with experience in many different templating syntaxes (Jinja, Handlebars, React, etc.). Figuring out CSS styling for GTK apps was a simple peruse through EWW's excellent docs away and I was cooking on EWW very quickly. For me, XML represents heirarchy of apps excellently and I find it very friendly for this context.
Obviously something needs to change, but it's not like templates with string escaping isn't a solved problem. https://www.arewewebyet.org/topics/templating/ I would vie for upgrading the XML parser to be more fully featured by adopting a fully featured templating language. A fully featured templating language implementation will have solved the string interpolation issue and have componentization and variables built in. I think this is a flexible and backwards compatible way forward. Below is a proposal of a structure that we could have if we adopted a templating language like Jinja2 using Tera: # ./eww.html
# Same high level structure as before, but with the power of templating.
# Setting a variable.
# Supports rust expressions, custom functions, etc.
{% set some_var = "foo" %}
# Setting a script variable using a custom makeScript function
# https://tera.netlify.app/docs/#functions
# Renders to "whatever you need" under the hood.
{% set_global some_script = makeScript(script="date | sed 's/:/X/g' | rev", interval="1s") %}
# Anything can be moved into separate files and imported.
{% import "components.html" as components %}
<eww>
<windows>
<window name="foo">
<geometry anchor="center" width="100px" height="10%"/>
<widget>
{{ components::something(arg=some_var) }}
</widget>
</window>
</windows>
</eww>
# ./components.html
# Macro definition for variable component
# https://tera.netlify.app/docs/#macros
{% macro something(arg, type="text") %}
<box class="{{ arg }}" halign="start">
click this button:
<button onclick="notify-send 'test' 'message'">
{{ some_script }}
</button>
</box>
{% endmacro something %} For more complicated examples, That's my pitch for a more fully featured XML, but please let me know if I'm in the minority. I'd love to hear more rationale from @elkowar and the community about their troubles with XML so we can have more established and community driven reasoning for migrating away. Edit: Indentation fix, use |
Beta Was this translation helpful? Give feedback.
-
This is some lua-ey syntax ig since ive been working with that recently eww {
definitions = {
widget {
name = "something",
-- additional widget attrs
box {
class="{{arg}}",
halign="start",
inner = "click this button:", -- this feels ugly to me but whatever
button {
onclick="notify-send 'test' 'message'",
inner = "{{some_script}}",
}
}
}
},
variables = {
some_var = "foo",
script-var {
name="some_script",
interval="1s",
command = "date | sed 's/:/X/g' | rev"
}
},
widows = {
window {
name="foo",
geometry = {
anchor="center",
width="100px",
height="10%"
},
widget = { -- this can be done in a neater way ofc
widget = 'something',
arg="{{some_var}}"
}
}
}
}
|
Beta Was this translation helpful? Give feedback.
-
Another option that I just remembered: https://github.com/judnich/TupleMarkup |
Beta Was this translation helpful? Give feedback.
-
Have you considered using html and css together with something like https://github.com/bodil/typed-html ? 😊 |
Beta Was this translation helpful? Give feedback.
-
My 2c: I don't mind XML at all. Dont know if there's discussion of this, but I would love to first see things like:
With those in I'm my literally just gonna rebuild my entire UI with Eww cause I love it. Screenshot of my setup at present: |
Beta Was this translation helpful? Give feedback.
-
Proposal: just remove some noice from XML:
|
Beta Was this translation helpful? Give feedback.
-
My suggestion would be to use the Dhall configuration language. It already has a maintained Rust implementation and would also completely solve the need to implement a custom language server or other language tooling (Dhall comes with a language server, formatter, linter and other tools). As a fellow Rust user, I assume you would also appreciate its static type system with excellent type inference. let some-var = "foo" : Text
let some-script =
eww.OutputScript::{
, interval = eww.unit.seconds 1
, callback = eww.runCommand "date | sed 's/:/X/g' | rev"
}
let some-widget =
\(class : Text) ->
eww.makeWidget
{ class, halign = eww.Layout.Start }
[ eww.makeTextWidget (eww.staticText "Click on the button!")
, eww.makeButtonWidget
{ onclick = eww.runCommand "notify-send 'test' 'message'" }
some-script
]
in eww.makeWindow
{ anchor = eww.Direction.Center
, width = eww.unit.pixels 100
, height = eww.unit.percent 10
}
[ (some-widget some-var) ]
This is a very naive API example I threw together in a few minutes. In this case, would expect the Of course this is just my suggestion, I get that the functional OCaml-like style might turn some people off to the idea. Just for the record, I think that using a lisp-style configuration would also be a fine idea, but using Dhall could possibly save you from a lot of uneccessary code duplication in implementing your own language and tooling from scratch. Cheers! :) |
Beta Was this translation helpful? Give feedback.
-
This kind of discussion is interesting so I am joining but I am not very familiar with eww.. so I don't know what I'm talking about. From what I can tell from the discussion you will have a turing complete configuration language so I suggest you look into using something pre-existing:
If you go custom then personally I think the RFC is a better choice because having a canonical representations is so important for cryptography but I am biased because I'm working on (what I hope will be) an XML-killer based on it. Actually; I'm very interested to see how this project develops, there is some overlap with what I am doing.. what is your communication / state management model? |
Beta Was this translation helpful? Give feedback.
-
As this change would be obviously a breaking one (maybe with a possibility to convert configs), I'd like to throw another idea in the room alongside. Oh and btw: @elkowar do you have a time frame in mind, when you want to settle this whole decision? |
Beta Was this translation helpful? Give feedback.
-
Something that use tabs, like Pug eww
definitions
def(name='something')
box(class='{{arg}}' halign='start')
| click this button:
button(onclick="notify-send 'test' 'message'")
| {{some_script}}
variables
var(name='some_var')
| foo
script-var(name='some_script' interval='1s')
| date | sed 's/:/X/g' | rev
windows
window(name='foo')
geometry(anchor='center' width='100px' height='10%')
widget
something(arg='{{some_var}}') XML can be converted to Pug easily (actually I just took your code and converted it via a website and fixed some things) There will probably be problems with the pipes of |
Beta Was this translation helpful? Give feedback.
-
I think at this point it's pretty clear that the S-expression syntax is the community (and my) favourite. Edited the original post to reflect that, and I'd say a decision has thus been made! |
Beta Was this translation helpful? Give feedback.
-
UPDATE
At this point, it seems like a clear winner has crystallized: the s-expression syntax!
I will most likely start implementing the new syntax soon! It will still take a while, but it's gonna happen.
Main post
XML Sucks. We all agree on that. While it works*, that asterisk is a very large one. Strings constantly cause issues, specifically in script-vars there are a ton of issues with escaping stuff properly. workarounds like
<
for comparisons are,.... disgusting.Thus: An alternative needs to be found.
I currently tend towards making the configuration language a form of s-expressions (the stuff you see in lisps). Sexpressions have a couple benefits:
-S-expressions are a very simple syntax, easy to parse and deal with, both from the code side as well as the user side - generating s-expressions from a script for use in
<literal>
would be extremely easy.They also have a big negative though, and that is that they look somewhat weird to people not yet exposed to them, and may be a turnoff for a couple (less serious) users. Depending on how the reactions to this are, that may be a dealbreaker.
I am thus also open for other ideas and proposals. If you have any concrete ideas or thoughts, please do comment here. This discussion thread is going to be the place to collect ideas and thoughts before I make a decision.
Please like the syntax proposals you enjoy, and do comment on what you like and dislike.
For a syntax proposal, please write equivalent of the following XML in your proposed syntax:
Also:
Given that I hate neither myself nor my users enough for that, I'm definitely_ not gonna do any indentation-sensitive language.
Also also:
Note that I may at some point write up a language-server for eww, or some other simpler validation scheme. This may be relevant for the syntax, as the option to optionally specify types may be provided in the future.
Beta Was this translation helpful? Give feedback.
All reactions