aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoland Kovacs2022-04-05 00:56:14 +0000
committerGitHub2022-04-05 00:56:14 +0000
commitd962e06e91b997813092cc5e49a800cc9d4f0ee1 (patch)
tree9ccbee392cbee6d0dc5e9c30bd73e44d5c47a444
parent6fc6f87260a2f11a892f09678fc6c10b01e88e3f (diff)
Add runtime language configuration (#1794) (#1866)
* Add runtime language configuration (#1794) * Add set-language typable command to change the language of current buffer. * Add completer for available language options. * Update set-language to refresh language server as well * Add language id based config lookup on `syntax::Loader`. * Add `Document::set_language3` to set programming language based on language id. * Update `Editor::refresh_language_server` to try language detection only if language is not already set. * Remove language detection from Editor::refresh_language_server * Move document language detection to where the scratch buffer is saved. * Rename Document::set_language3 to Document::set_language_by_language_id. * Remove unnecessary clone in completers::language
-rw-r--r--book/src/generated/typable-cmd.md1
-rw-r--r--helix-core/src/syntax.rs11
-rw-r--r--helix-term/src/commands/typed.rs26
-rw-r--r--helix-term/src/ui/mod.rs21
-rw-r--r--helix-view/src/document.rs11
-rw-r--r--helix-view/src/editor.rs1
6 files changed, 70 insertions, 1 deletions
diff --git a/book/src/generated/typable-cmd.md b/book/src/generated/typable-cmd.md
index 85507b19..f9261a75 100644
--- a/book/src/generated/typable-cmd.md
+++ b/book/src/generated/typable-cmd.md
@@ -53,6 +53,7 @@
| `:hsplit-new`, `:hnew` | Open a scratch buffer in a horizontal split. |
| `:tutor` | Open the tutorial. |
| `:goto`, `:g` | Go to line number. |
+| `:set-language`, `:lang` | Set the language of current buffer. |
| `:set-option`, `:set` | Set a config option at runtime |
| `:sort` | Sort ranges in selection. |
| `:rsort` | Sort ranges in selection in reverse order. |
diff --git a/helix-core/src/syntax.rs b/helix-core/src/syntax.rs
index e736b370..bb0073e1 100644
--- a/helix-core/src/syntax.rs
+++ b/helix-core/src/syntax.rs
@@ -504,6 +504,13 @@ impl Loader {
.cloned()
}
+ pub fn language_config_for_language_id(&self, id: &str) -> Option<Arc<LanguageConfiguration>> {
+ self.language_configs
+ .iter()
+ .find(|config| config.language_id == id)
+ .cloned()
+ }
+
pub fn language_configuration_for_injection_string(
&self,
string: &str,
@@ -529,6 +536,10 @@ impl Loader {
None
}
+ pub fn language_configs(&self) -> impl Iterator<Item = &Arc<LanguageConfiguration>> {
+ self.language_configs.iter()
+ }
+
pub fn set_scopes(&self, scopes: Vec<String>) {
self.scopes.store(Arc::new(scopes));
diff --git a/helix-term/src/commands/typed.rs b/helix-term/src/commands/typed.rs
index 4c044793..8f74adb6 100644
--- a/helix-term/src/commands/typed.rs
+++ b/helix-term/src/commands/typed.rs
@@ -217,6 +217,7 @@ fn write_impl(cx: &mut compositor::Context, path: Option<&Cow<str>>) -> anyhow::
if path.is_some() {
let id = doc.id();
+ doc.detect_language(cx.editor.syn_loader.clone());
let _ = cx.editor.refresh_language_server(id);
}
Ok(())
@@ -931,6 +932,24 @@ fn setting(
Ok(())
}
+/// Change the language of the current buffer at runtime.
+fn language(
+ cx: &mut compositor::Context,
+ args: &[Cow<str>],
+ _event: PromptEvent,
+) -> anyhow::Result<()> {
+ if args.len() != 1 {
+ anyhow::bail!("Bad arguments. Usage: `:set-language language`");
+ }
+
+ let doc = doc_mut!(cx.editor);
+ doc.set_language_by_language_id(&args[0], cx.editor.syn_loader.clone());
+
+ let id = doc.id();
+ cx.editor.refresh_language_server(id);
+ Ok(())
+}
+
fn sort(
cx: &mut compositor::Context,
args: &[Cow<str>],
@@ -1409,6 +1428,13 @@ pub const TYPABLE_COMMAND_LIST: &[TypableCommand] = &[
completer: None,
},
TypableCommand {
+ name: "set-language",
+ aliases: &["lang"],
+ doc: "Set the language of current buffer.",
+ fun: language,
+ completer: Some(completers::language),
+ },
+ TypableCommand {
name: "set-option",
aliases: &["set"],
doc: "Set a config option at runtime",
diff --git a/helix-term/src/ui/mod.rs b/helix-term/src/ui/mod.rs
index a90debdb..2dca870b 100644
--- a/helix-term/src/ui/mod.rs
+++ b/helix-term/src/ui/mod.rs
@@ -298,6 +298,27 @@ pub mod completers {
})
}
+ pub fn language(editor: &Editor, input: &str) -> Vec<Completion> {
+ let matcher = Matcher::default();
+
+ let mut matches: Vec<_> = editor
+ .syn_loader
+ .language_configs()
+ .filter_map(|config| {
+ matcher
+ .fuzzy_match(&config.language_id, input)
+ .map(|score| (&config.language_id, score))
+ })
+ .collect();
+
+ matches.sort_unstable_by_key(|(_language, score)| Reverse(*score));
+
+ matches
+ .into_iter()
+ .map(|(language, _score)| ((0..), language.clone().into()))
+ .collect()
+ }
+
pub fn directory(_editor: &Editor, input: &str) -> Vec<Completion> {
filename_impl(input, |entry| {
let is_dir = entry.file_type().map_or(false, |entry| entry.is_dir());
diff --git a/helix-view/src/document.rs b/helix-view/src/document.rs
index c9c1e502..5d739af5 100644
--- a/helix-view/src/document.rs
+++ b/helix-view/src/document.rs
@@ -607,6 +607,17 @@ impl Document {
self.set_language(language_config, Some(config_loader));
}
+ /// Set the programming language for the file if you know the language but don't have the
+ /// [`syntax::LanguageConfiguration`] for it.
+ pub fn set_language_by_language_id(
+ &mut self,
+ language_id: &str,
+ config_loader: Arc<syntax::Loader>,
+ ) {
+ let language_config = config_loader.language_config_for_language_id(language_id);
+ self.set_language(language_config, Some(config_loader));
+ }
+
/// Set the LSP.
pub fn set_language_server(&mut self, language_server: Option<Arc<helix_lsp::Client>>) {
self.language_server = language_server;
diff --git a/helix-view/src/editor.rs b/helix-view/src/editor.rs
index 9a2b4297..c4e9ec28 100644
--- a/helix-view/src/editor.rs
+++ b/helix-view/src/editor.rs
@@ -448,7 +448,6 @@ impl Editor {
/// Refreshes the language server for a given document
pub fn refresh_language_server(&mut self, doc_id: DocumentId) -> Option<()> {
let doc = self.documents.get_mut(&doc_id)?;
- doc.detect_language(self.syn_loader.clone());
Self::launch_language_server(&mut self.language_servers, doc)
}