-
Notifications
You must be signed in to change notification settings - Fork 43
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
[RFC] feature/status_components #233
base: dev
Are you sure you want to change the base?
Conversation
Updated description. See also docstrings inside statusbar.py. |
Love this compatibility 👍 Seems like a rather thought out and solid implementation. I'll test it tomorrow and check out the other needed PR's first. Thanks :) |
I found a slight bug: when lots of files are opened and they don't fit in the top bar, the clock is still shown correctly but the left most items are hidden and some files aren't visible. I tried it with this:
I love the coloring though, makes everything a lot more structured and readable. EDIT: |
This is because of the truncate=left setting for top_bar. There is another setting which may be more useful for those cases though:
See modules/filelist.py get_default_config() |
Ah, ok! I'd forgot that the current version of suplemon doesn't handle that. The entire status line is just truncated if it's too long... It would be nice to somehow limit the file list length as it's probably potentially the longest item. Not sure what the best solution could be though. |
Maybe it might make sense to default to filelist rotate: true and top_bar truncate: right so at least the current file will always be visible? Or keep the default for those like it is now but mention it in readme / internal help? Personally I prefer the non rotated filelist but you are right, if the screen is too small (e.g. a small tmux pane) or there are too many files open you won't even see which file is selected. |
Or maybe.. StatusComponents could provide another flag which allows them to indicate if they can be hidden in case of truncating? Then truncating would first go through all the components and check that flag and if set remove the component. And only if there still is not enough room to render the remaining ones start removing the components from the left/right (based on setting) regardless of that flag until the bar is small enough. Edit:
This would actually be a nice feature for the filelist module, regardless of the truncating issue. Edit2: implemented |
Yes I noticed that as well, StatusBar binds to the config changed event to reload its settings but for some reason the state is not invalidated (or it is actually invalidated, then rendered and finally erased by some other part). Once you do something to invalidate a bar (like changing or switching to another file (filelist), moving the cursor (document_position) or resizing the window (both bars)) it will get redrawn. This needs investigation and is listed in "Things to do" as
Edit: |
Implemented: app_status, current file and lintlogo have a priority of 2, the default is 1 and for filelist all files other than the current one have a priority of 0. |
Implemented: 2 config options to configure this:
I have set the default to liststyle: linear and limit: 5. Regardless of any of the options, if the screen is too small to show all of the files based on this options the statusbar truncating will still kick in and may remove components on its own. This is completely independent from the filelist module. |
Hey thanks! The default behavior and colors now look really nice. Way fancier than what I had implemented. |
A few comments that I thought of when testing this:
Overall I think the implementation is solid! |
I think I got all the spammy ones.
Renamed the old StatusComponent (which only shows the raw number) to "cursor_count" and added a new one called "cursors" which additionally creates the "Cursors: " prefix inside the component. Default top bar is changed to use the new cursors component.
added There are still quite some FIXME's and TODO's inside the code and also some other outstanding issues (as listed in first post) with this PR. |
761d1b7
to
680826b
Compare
… old style classes)
… to center: False, rotate: False, limit: 5
…nd rotate booleans by single liststyle var
…used before forcing a redraw
…ault instead of 'cursor_count'
680826b
to
03cb939
Compare
I implemented a new StatusBar architecture, the end result is you have status components which can be exposed by any module and used by any statusbar.
The system consists of following classes:
The StatusBarManager tries to call get_components() for each loaded module which may return a list of (name, StatusComponent class). It then instantiates each component and stores the instance in an internal dict. If a module does not offer get_components() but offers the old interface (options["status"], get_status) it will wrap those functions in a StatusComponentShim.
StatusBar is responsible for rendering a specific statusbar. The constructor gets a reference to a curses window, a reference to app and a key which defines it's section inside the config. Using the key it gets and parses it's component config string and requests the component instances from StatusBarManager.
A derived StatusComponent class provides (among others) following properties
which will be used by StatusBar.render(). It also provides a compute() function which gets called on every render() tick. compute() allows the component to update it's internal state and returns an opaque value (a serial in the default implementation). The caller can then compare this return value to the one it got at the previous tick and if it differs the component has been changed. This allows the caller to not do anything at all if none of the components report a change.
A derived StatusComponentGenerator class provides a compute() function which works the same as in the StatusComponent class but does neither provide a .text nor .style property. Instead, it provides a get_components() function which returns a list of own StatusComponent instances. This is useful for e.g. the filelist where each sub component may have it's own .style property.
StatusComponentFill will not be instantiated but serves as a placeholder for rendering calculations. The renderer will calculate the unused terminal cell width (using component.cells property) and distribute it evenly between the fill components. This allows a component config string like "fill clock fill" to be rendered with a single clock in the middle of the statusbar.
ui.py instantiates StatusBarManager which offers a add() function which creates new StatusBar instances. ui.py is responsible to add statusbars using this method but only interacts with the manager which in turn interacts with the statusbar instances.
On ui.py refresh() StatusBarManager.render() is called which in turn calls .render() for all StatusBar instances it is responsible for.
My personal config contains this definition of status bars:
Lintlogo is actually quite useful :)
It is the usual editor logo but if a file contains lint errors it changes color to red and appends the number of lint errors.
The default config looks like this:
If a user wants to change it (e.g. remove the cursor count and move the lint error count to the left) all s/he needs to do is something like:
I primarily made this for my own usage but would like to upstream those changes after cleaning up and polishing it a bit if the design sounds reasonable.
As this branch requires PRs #218 and #221 I based it on a local dev-next branch but will rebase it once they are merged into dev.
Things to do:
add StatusComponent truncate prioritiesadd config option for filelist to only show up to x files (+ something like [y more files])figure out why statusbars don't invalidate state after config_changed eventfix statusbar invalidation after prompt exit