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

Add state field to app, mapping widgets to last selection #227

Open
KronosTheLate opened this issue Jun 9, 2023 · 7 comments
Open

Add state field to app, mapping widgets to last selection #227

KronosTheLate opened this issue Jun 9, 2023 · 7 comments

Comments

@KronosTheLate
Copy link
Contributor

A toy app to exemplify. I did not end up referring to it much, but you may want to.
App(
    # Layout: 3 columns (a b c), with b split in the middle
    :(a(10, 0.2) * (b1(5, 0.2) / b2(5, 0.2)) * c(10, 0.2) * d(10, 0.2)); 
    widgets = Dict(
        :a => TextWidget("Box 1", as_panel=true),
        :b1 => TextWidget("Box 2.1", as_panel=true),
        :b2 => TextWidget("Box 2.2", as_panel=true),
        :c => SimpleMenu(["Option 1", "Option 2", "Option 3"]),
        :d => MultiSelectMenu(["Option 1", "Option 2", "Option 3"]),
    ), transition_rules = Dict(
        ArrowRight() => Dict(:a => :b1, :b1=>:c, :b2=>:c, :c=>:d),
        ArrowLeft() => Dict(:c => :b1, :b1=>:a, :b2=>:a, :d=>:c),
        ArrowDown() => Dict(:b1 => :b2),
        ArrowUp() => Dict(:b2 => :b1),
    )
) |> play

Current problems

  • If I have multiple menus in an app, the returned value only contains the selections of the one selected when I press enter. I generally want the state of all widgets back
  • If I would want to play an app several times, I would bind it to a variable. To access the states between selections, I would have to bind them to an extra variable
  • I can not update the state of a widget without closing it, when the state is only returned upon enter, which closes the app
  • I can not change the selection programically, to a) set defaults, or b) change the state in non-interactive settings. This last point is useful if the app is used as "the holder of all settings", and for some functions, you also have to change certain settings.
  • If I use an app to set some settings, I want to keep them the next time I open the app, as I am likely to only want to make small changes.

Proposed solution

I think it would be really nice to have a persistent state as a field of the app. This field of the app should map the widgets (by the symbol that defines the layout) to its state. This would allow syntax like my_app.state[:c] or my_app[:c] for querying the state, which is rather intuitive. It would also fix all the issues above.

Note that this idea is probably in my head from TerminalMenus, which uses internal states. And I found that great, and one of the biggest potential problems with Term apps.

Separate but related - change default keybindings for Menus

It seems to me like there should be an option to make selections in menus without closing the app. This would particularly couple well with a persistent state, but I think it would be an improvement regardless. Something like the keybindings from TerminalMenus seem appropriate for this:

julia> println("Select channels:"); request(menu)
Select channels:
[press: Enter=toggle, a=all, n=none, d=done, q=abort]
[X] 0
[ ] 1
[ ] 2
[ ] 3
[X] 4
[ ] 5
[ ] 6
> [X] 7

The keybindings here are more like "use enter to toggle/select stuff, and press d when you are done". This feels better to me than the current default bindings of "use space to toggle multi-select menus, but for single select menus, use enter. And enter "sends" the selection and closes the app in both cases". It is not even clear to me how one would change the selection for two single-select widgets inside the same app at the same time. I would be fine with using space to toggle and enter to finish and close. But I do feel like space is more for typing than for triggering some effect, and that the coupling between enter and a toggle seems appropriate. And since you only want to close the app once, and be intentional about it, a smaller character like "d" seems appropriate and less likely to be pressed accidentally (when a user is trying to toggle). But it is also more breaking than necessary, and can always be overwritten by the user, so this is a smaller point. Togglability of single-select menus is the important matter.

Does it seem like an improvement to handle add a presistent state to apps, accessible by keys? I think so, but it is also my suggestion xD.

Disclaimer - I am just very interested in the Apps creatable by Term, and the TerminalMenus library. I have not actually used them for anything real yet, so I may be blind to some aspects.

@KronosTheLate
Copy link
Contributor Author

In particular, I would love to be able to press a button to start e.g. sampling for a period set by an InputBox, with settings specified in different menus (so access to their state. A button callback should perhaps take the state as an argument, allowing the current state of the settings panel to be used to select e.g. the sampling rate, oscilloscope-trigger etc.)

@FedeClaudi
Copy link
Owner

Hey,

Thank for the input. Yeah states sound like a great idea, I would need to think about how to best implement them though.
I think some of the problems (e.g. selecting which widgets should be active when starting an app) should be already doable, but for sure having access to all states would be useful. Especially when closing the app.

The menus key bindings changes also make a lot of sense.

Disclaimer - I am just very interested in the Apps creatable by Term, and the TerminalMenus library. I have not actually used them for anything real yet, so I may be blind to some aspects.

Great to hear! I create Term.jl mostly because I wanted something like it in Julia. The App idea came on towards the end as I was thinking of more useful features to add, but I haven't used them and, until now, I didn't know if anyone else cared for them. So the result is that I developed them up to a point where I hoped would show that there's potential for something else but they are far from finished or complete in any sense. So this really helps!

@KronosTheLate
Copy link
Contributor Author

KronosTheLate commented Jun 14, 2023

Great to hear! I create Term.jl mostly because I wanted something like it in Julia. The App idea came on towards the end as I was thinking of more useful features to add, but I haven't used them and, until now, I didn't know if anyone else cared for them. So the result is that I developed them up to a point where I hoped would show that there's potential for something else but they are far from finished or complete in any sense. So this really helps!

That is really cool to hear. The potential to create and run apps in terminal is really, cool, because an intuitive UI is exactly what the REPL/terminal UI is lacking, that notebooks and web-apps have as an advantage. So these apps bring the terminal-approach to a point where I feel like they can compete with notebooks and web-apps in terms of usability, while retaining the easy setup and low overhead we love from the terminal. I would love to see many packages use apps to create interfaces to complicated functions with large numbers of settings.

Warning - the two long paragraphs below are essentially just me painting out my pie-in-the-sky dreams/hopes, and partly repeat what I wrote above.

Just to map out my use case, I am using a DAQC2 Raspberry Pi Plate/HAT that I control via SSH. I had some issues with VSCode's SSH integration, and found the straight terminal interface more stable and responsive, which is key for usability. The current inerface could creatly benefit from a using a Term.jl app. This app would make the user select between 3 modes - legacy, function generator or oscilloscope. Upon selection, a new app would open, showing the current inputs/outputs in a terminal dashboard. Ideally, for the legacy mode (everything DC-related + PWM), the user could change the analog outputs/toggle digital outputs, while observing the analog/digital inputs. For the function generator, I would want to include settings like frequency, waveform, amplitude and channel, and a) print the settings in a list, or b) plot the signal, whenever the output is turned on. For option "b", I imagine an app panel with a little terminal plot of the waveform generated. For the oscilloscope, it has a bunch of settings, like channel, trigger-channel, frequency, trigger type, trigger level etc, and also wants a plot that updates in real time, ideally inside the app. If your terminal apps would allow all of this, it would be super cool, and also a really good showcase of the potential of your really cool terminal apps. I can imagine several Julia packages that would benefit from for instance interactive function fitting and plotting, in an interactive interface like this.

In fact, I feel as if the lack of easy and intuitive UI is the largest barrier of entry to programming in general. The blank prompt is a world of possibilities, all hidden inside default values and documentation. I really believe that terminal apps could create a few canonical entry-points to many packages via menus/dashboards, showing possible values in an easy-to-overview manner, and uniting the locations of where you discover the options, and where you make a selection.

@FedeClaudi
Copy link
Owner

Yeah, for sure!

I agree that a proper interactive UI system would be awesome. It's just that at this point it's hard for me to justify investing the time and effort it would take - this is still just a side project after all. If there was a clear interest and a bunch of folks that want to work on this I would be more than happy to participate though.

That said, Julia interfaces with Python really easily and python has the AWESOME Textualize: https://github.com/Textualize/textual so it's also hard to justify reinventing the wheel in that sense.

@KronosTheLate
Copy link
Contributor Author

That said, Julia interfaces with Python really easily and python has the AWESOME Textualize: https://github.com/Textualize/textual so it's also hard to justify reinventing the wheel in that sense.

Okay that demo is really really cool. I really see your point, and it is important to respect your time, not poring yourself into something that is used once or twice. Unless there is significant interest, I agree that efforts should be limited. Also GenieBuilder is also available for no-code app building, which is related. It indeed seems like between web-apps and python alternatives, there is not much market share left for Term.jl apps.

@FedeClaudi
Copy link
Owner

Yeah. Developing Term has been an interesting experience, as I said I mostly did it because it was fun and I wanted something like this, but also in the hope of making something useful for the community. And while I received really positive feedback from a few folks like you, it's hard to say how "useful" it actually is: how many people use it and so on...

So after the core features became mature enough it became increasingly hard to justify the time spent on this, unfortunately.
I do hope to attract some other developer with more free time that want to carry this further though 😬

@KronosTheLate
Copy link
Contributor Author

That would be great. I can not offer myself up as a "developer", but if I continue to find Term useful, I will continue as an enthusiastic user xD. Thanks for all your hard work. I really prefer working in Julia, so having a Julia alternative really is key for me.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants