-
-
Notifications
You must be signed in to change notification settings - Fork 2.5k
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 ability to switch themes #267
Conversation
@@ -144,34 +142,30 @@ fn read_query(language: &str, filename: &str) -> String { | |||
|
|||
impl LanguageConfiguration { | |||
pub fn highlight_config(&self, scopes: &[String]) -> Option<Arc<HighlightConfiguration>> { | |||
self.highlight_config |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the idea here was to only recalculate highlight_config
if absolutely necessary (we only need to do this if the theme changed and we have different scopes now). HighlightConfiguration
isn't cheap to construct and it also takes several fs
reads so ideally we want to reuse them across files if they're the same language.
helix-term/src/main.rs
Outdated
use helix_core::syntax; | ||
|
||
// load $HOME/.config/helix/languages.toml, fallback to default config | ||
let lang_config = std::fs::read(conf_dir.join("languages.toml")); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think all this was recently moved into Application::new
, can we just do it there?
helix-term/src/main.rs
Outdated
@@ -91,8 +92,39 @@ FLAGS: | |||
|
|||
setup_logging(logpath, args.verbosity).context("failed to initialize logging")?; | |||
|
|||
let themes = std::sync::Arc::new(Themes::load()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should really be delayed, we don't want to load all available themes into memory. list-themes
should read the directory entries (I think we should move contrib/themes
under runtime/themes
), then when setting the theme we actually read the file.
helix-term/src/main.rs
Outdated
let app_config = application::Configuration { theme: None }; | ||
let app_config = std::fs::read(conf_dir.join("config.toml")) | ||
.map(|v| toml::from_slice(v.as_slice())) | ||
.unwrap_or_else(|_| Ok(app_config.clone())) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't quite follow the double unwrap. I think the .map
on the previous line should be a and_then
helix-term/src/main.rs
Outdated
.unwrap_or_else(|_| Ok(app_config.clone())) | ||
.unwrap_or_else(|_| app_config); | ||
|
||
let theme = if let Some(theme) = &app_config.theme { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
let theme = app_config.theme.as_ref().map(|theme| themes.get(theme)).unwrap_or_else(|_| themes.default())
helix-term/src/application.rs
Outdated
use helix_view::editor::Action; | ||
let mut compositor = Compositor::new()?; | ||
let size = compositor.size(); | ||
let mut editor = Editor::new(size); | ||
let theme = if let Some(theme) = &config.theme { | ||
if let Some(theme) = themes.get(theme) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ditto here, also the to_owned
branch is followed by a clone
which is not ideal (it's a double clone)
helix-term/src/ui/completion.rs
Outdated
option.detail.as_deref().unwrap_or_default(), | ||
contents.clone() | ||
), | ||
cx.editor.config_loader.clone(), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah so this is why I switched to a global loader, it was annoying to pass it around everywhere
helix-view/src/editor.rs
Outdated
pub fn set_theme(&mut self, theme: Theme) { | ||
let config_loader = self.config_loader.clone(); | ||
let (_, doc) = self.current(); | ||
doc.detect_language(Some(&theme), config_loader); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This really needs to be done in all documents, since the list of scopes might have changed. We also don't need to trash the whole syntax tree, simply update the highlight configuration on it I think.
helix-view/src/editor.rs
Outdated
@@ -161,7 +174,7 @@ impl Editor { | |||
let id = if let Some(id) = id { | |||
id | |||
} else { | |||
let mut doc = Document::load(path)?; | |||
let mut doc = Document::load(path, Some(self.config_loader.clone()))?; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There's no need to clone an arc around if you're just passing it as a reference (cloning then dropping results in extra operations to modify the refcount inside the Arc). &self.config_loader
and then using &Loader
on the type would work.
helix-term/src/application.rs
Outdated
@@ -32,19 +36,41 @@ pub type LspCallback = | |||
pub type LspCallbacks = FuturesUnordered<LspCallback>; | |||
pub type LspCallbackWrapper = Box<dyn FnOnce(&mut Editor, &mut Compositor) + Send>; | |||
|
|||
#[derive(Clone, Debug, Serialize, Deserialize)] | |||
pub struct Configuration { | |||
pub theme: Option<String>, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this is good and can also hold the keymap from #268 later, \cc @PabloMansanet
d7aae56
to
b3b6601
Compare
Just want to comment that I'm definitely in favor of the general approach, from a user perspective. Haven't had a chance to look at the code itself yet. |
#268 landed so this can now share the config type :) |
Not sure what to do about the helix/helix-core/src/syntax.rs Lines 145 to 175 in 103bd14
|
7170494
to
136286a
Compare
I managed to come up with a solution that doesn't require mutating the |
I think we'll need to do the fix in a different way. We can't have a fixed set of scopes, because it's up to the theme to pick a range of scopes to support. For example, one can define a |
(see part 12.4: https://macromates.com/manual/en/language_grammars) |
Maybe we could use |
If you replace the Arc contained inside helix/helix-core/src/syntax.rs Line 279 in ca806d4
|
But initializing |
Note: if you add a custom completer then we can also offer themes as completions on |
I do plan to add a completer once we figure out a good way to have multiple highlight configs. |
Yeah it's precisely because the highlight query needs to be reloaded and re-analyzed to support the new scopes. It's shared across all files of the same language though. Should be much faster in |
Doing just One thing that I'm also wondering is if we were to have multiple |
Also, it's possible you're iterating over all languages over |
Yeah all the files of the same type share a single highlight config inside an Arc, so iterating only over |
There is one thing I always want in switching theme, like previewing themes dynamically. I have the same issue in vim, neovim, kakoune, doom emacs. I need to manually type in the command to switch the theme one by one, I wish I can just tab and the whole thing is being previewed to that theme, of course we need some extra handler around the prompt if we want to do this. Usually these require addons and if I do it by hand it is going to be tedious. Only vscode get this right. |
6685f4b
to
16126e8
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Verified on local. Thanks!
I know the scope of this PR might be a bit too wide so I'm very much open to agressively adjusting the goal. In the process of adding the ability to switch themes using a command I went into a pretty deep hole of static variables accessed from a few places where it's not as obvious how to pass the necessary values to the function. In the process I got rid of the static
syntax::LOADER
inhelix-core
and added the loader to main and most of the function signatures that used it. Thehighlight_config
field ofDocument
got removed as well, now callinghighlight_config
recomputes the configuration on each call and this is the part that I don't have figured out yet.A global configuration file in
~/.config/helix/config.toml
is added where users can specify the theme they want to use by default. Themes are now placed in~/.config/helix/themes
. During runtime one can set the theme with:theme <name>
or list themes with:list-themes
. For now the listing is pretty naive and just displays the names in status bar.I'm looking for general comments on this approach, perhaps it's undesired to get rid of static variables I might be uninformed here.