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 runtime language configuration (#1794) #1866

Merged
merged 4 commits into from
Apr 5, 2022
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions book/src/generated/typable-cmd.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,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. |
Expand Down
11 changes: 11 additions & 0 deletions helix-core/src/syntax.rs
Original file line number Diff line number Diff line change
Expand Up @@ -512,6 +512,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,
Expand All @@ -537,6 +544,10 @@ impl Loader {
None
}

pub fn language_configs(&self) -> impl Iterator<Item = &Arc<LanguageConfiguration>> {
Copy link
Member

@kirawi kirawi Mar 25, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think creating a function like language_config_for_scope would be more homogenous with the code.

Edit: Ah, you're using fuzzy finding. Never mind.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes. 🙂 Though, now that you mentioned it, I could've added a language_config_for_id functions which could've been useful in the actual command implementation...

self.language_configs.iter()
}

pub fn set_scopes(&self, scopes: Vec<String>) {
self.scopes.store(Arc::new(scopes));

Expand Down
26 changes: 26 additions & 0 deletions helix-term/src/commands/typed.rs
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,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(())
Expand Down Expand Up @@ -913,6 +914,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>],
Expand Down Expand Up @@ -1376,6 +1395,13 @@ pub const TYPABLE_COMMAND_LIST: &[TypableCommand] = &[
fun: goto_line_number,
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"],
Expand Down
21 changes: 21 additions & 0 deletions helix-term/src/ui/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -284,6 +284,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.clone(), score))
zen3ger marked this conversation as resolved.
Show resolved Hide resolved
})
.collect();

matches.sort_unstable_by_key(|(_language, score)| Reverse(*score));

matches
.into_iter()
.map(|(language, _score)| ((0..), language.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());
Expand Down
11 changes: 11 additions & 0 deletions helix-view/src/document.rs
Original file line number Diff line number Diff line change
Expand Up @@ -603,6 +603,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;
Expand Down
1 change: 0 additions & 1 deletion helix-view/src/editor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -440,7 +440,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)
}

Expand Down