on master help sign in
Try to detect language when document file path is set
06d8d3fBlaž Hrastnik
helix-core/src/indent.rs+19−16
@@ -251,22 +251,25 @@ where
251 Configuration, IndentationConfiguration, Lang, LanguageConfiguration, Loader,
251 Configuration, IndentationConfiguration, Lang, LanguageConfiguration, Loader,
252 };
252 };
253 use once_cell::sync::OnceCell;
253 use once_cell::sync::OnceCell;
254− let loader = Loader::new(Configuration {
254+ let loader = Loader::new(
255+ Configuration {
255− language: vec![LanguageConfiguration {
256+ language: vec![LanguageConfiguration {
256− scope: "source.rust".to_string(),
257+ scope: "source.rust".to_string(),
257− file_types: vec!["rs".to_string()],
258+ file_types: vec!["rs".to_string()],
258− language_id: Lang::Rust,
259+ language_id: Lang::Rust,
259− highlight_config: OnceCell::new(),
260+ highlight_config: OnceCell::new(),
260− //
261+ //
261− roots: vec![],
262+ roots: vec![],
262− language_server: None,
263+ language_server: None,
263− indent: Some(IndentationConfiguration {
264+ indent: Some(IndentationConfiguration {
264− tab_width: 4,
265+ tab_width: 4,
265− unit: String::from(" "),
266+ unit: String::from(" "),
266− }),
267+ }),
267− indent_query: OnceCell::new(),
268+ indent_query: OnceCell::new(),
268− }],
269+ }],
270+ },
271+ Vec::new(),
269− });
272+ );
270
273
271 // set runtime path so we can find the queries
274 // set runtime path so we can find the queries
272 let mut runtime = std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR"));
275 let mut runtime = std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR"));
helix-core/src/syntax.rs+7−1
@@ -166,13 +166,15 @@ pub struct Loader {
166 // highlight_names ?
166 // highlight_names ?
167 language_configs: Vec<Arc<LanguageConfiguration>>,
167 language_configs: Vec<Arc<LanguageConfiguration>>,
168 language_config_ids_by_file_type: HashMap<String, usize>, // Vec<usize>
168 language_config_ids_by_file_type: HashMap<String, usize>, // Vec<usize>
169+ scopes: Vec<String>,
169}
170}
170
171
171impl Loader {
172impl Loader {
172− pub fn new(config: Configuration) -> Self {
173+ pub fn new(config: Configuration, scopes: Vec<String>) -> Self {
173 let mut loader = Self {
174 let mut loader = Self {
174 language_configs: Vec::new(),
175 language_configs: Vec::new(),
175 language_config_ids_by_file_type: HashMap::new(),
176 language_config_ids_by_file_type: HashMap::new(),
177+ scopes,
176 };
178 };
177
179
178 for config in config.language {
180 for config in config.language {
@@ -192,6 +194,10 @@ impl Loader {
192 loader
194 loader
193 }
195 }
194
196
197+ pub fn scopes(&self) -> &[String] {
198+ &self.scopes
199+ }
200+
195 pub fn language_config_for_file_name(&self, path: &Path) -> Option<Arc<LanguageConfiguration>> {
201 pub fn language_config_for_file_name(&self, path: &Path) -> Option<Arc<LanguageConfiguration>> {
196 // Find all the language configurations that match this file name
202 // Find all the language configurations that match this file name
197 // or a suffix of the file name.
203 // or a suffix of the file name.
helix-term/src/main.rs−12
@@ -152,18 +152,6 @@ FLAGS:
152
152
153 setup_logging(logpath, args.verbosity).context("failed to initialize logging")?;
153 setup_logging(logpath, args.verbosity).context("failed to initialize logging")?;
154
154
155− // initialize language registry
156− use helix_core::syntax::{Loader, LOADER};
157−
158− // load $HOME/.config/helix/languages.toml, fallback to default config
159− let config = std::fs::read(helix_core::config_dir().join("languages.toml"));
160− let toml = config
161− .as_deref()
162− .unwrap_or(include_bytes!("../../languages.toml"));
163−
164− let config = toml::from_slice(toml).context("Could not parse languages.toml")?;
165− LOADER.get_or_init(|| Loader::new(config));
166−
167 // TODO: use the thread local executor to spawn the application task separately from the work pool
155 // TODO: use the thread local executor to spawn the application task separately from the work pool
168 let mut app = Application::new(args).context("unable to create new appliction")?;
156 let mut app = Application::new(args).context("unable to create new appliction")?;
169 app.run().await;
157 app.run().await;
helix-view/src/document.rs+20−13
@@ -131,9 +131,8 @@ impl Document {
131 }
131 }
132 }
132 }
133
133
134− // TODO: passing scopes here is awkward
135 // TODO: async fn?
134 // TODO: async fn?
136− pub fn load(path: PathBuf, scopes: &[String]) -> Result<Self, Error> {
135+ pub fn load(path: PathBuf) -> Result<Self, Error> {
137 use std::{env, fs::File, io::BufReader};
136 use std::{env, fs::File, io::BufReader};
138 let _current_dir = env::current_dir()?;
137 let _current_dir = env::current_dir()?;
139
138
@@ -143,15 +142,8 @@ impl Document {
143 // TODO: create if not found
142 // TODO: create if not found
144
143
145 let mut doc = Self::new(doc);
144 let mut doc = Self::new(doc);
146−
145+ // set the path and try detecting the language
147− let language_config = LOADER
146+ doc.set_path(&path)?;
148− .get()
149− .unwrap()
150− .language_config_for_file_name(path.as_path());
151− doc.set_language(language_config, scopes);
152−
153− // canonicalize path to absolute value
154− doc.path = Some(std::fs::canonicalize(path)?);
155
147
156 Ok(doc)
148 Ok(doc)
157 }
149 }
@@ -218,6 +210,15 @@ impl Document {
218 }
210 }
219 }
211 }
220
212
213+ fn detect_language(&mut self) {
214+ if let Some(path) = self.path() {
215+ let loader = LOADER.get().unwrap();
216+ let language_config = loader.language_config_for_file_name(path);
217+ let scopes = loader.scopes();
218+ self.set_language(language_config, scopes);
219+ }
220+ }
221+
221 pub fn set_path(&mut self, path: &Path) -> Result<(), std::io::Error> {
222 pub fn set_path(&mut self, path: &Path) -> Result<(), std::io::Error> {
222 // canonicalize path to absolute value
223 // canonicalize path to absolute value
223 let current_dir = std::env::current_dir()?;
224 let current_dir = std::env::current_dir()?;
@@ -229,6 +230,10 @@ impl Document {
229 self.path = Some(path);
230 self.path = Some(path);
230 }
231 }
231 }
232 }
233+
234+ // try detecting the language based on filepath
235+ self.detect_language();
236+
232 Ok(())
237 Ok(())
233 }
238 }
234
239
@@ -251,8 +256,10 @@ impl Document {
251 };
256 };
252 }
257 }
253
258
254− pub fn set_language2(&mut self, scope: &str, scopes: &[String]) {
259+ pub fn set_language2(&mut self, scope: &str) {
260+ let loader = LOADER.get().unwrap();
255− let language_config = LOADER.get().unwrap().language_config_for_scope(scope);
261+ let language_config = loader.language_config_for_scope(scope);
262+ let scopes = loader.scopes();
256
263
257 self.set_language(language_config, scopes);
264 self.set_language(language_config, scopes);
258 }
265 }
helix-view/src/editor.rs+13−1
@@ -36,6 +36,18 @@ impl Editor {
36 .unwrap_or(include_bytes!("../../theme.toml"));
36 .unwrap_or(include_bytes!("../../theme.toml"));
37 let theme: Theme = toml::from_slice(toml).expect("failed to parse theme.toml");
37 let theme: Theme = toml::from_slice(toml).expect("failed to parse theme.toml");
38
38
39+ // initialize language registry
40+ use helix_core::syntax::{Loader, LOADER};
41+
42+ // load $HOME/.config/helix/languages.toml, fallback to default config
43+ let config = std::fs::read(helix_core::config_dir().join("languages.toml"));
44+ let toml = config
45+ .as_deref()
46+ .unwrap_or(include_bytes!("../../languages.toml"));
47+
48+ let config = toml::from_slice(toml).expect("Could not parse languages.toml");
49+ LOADER.get_or_init(|| Loader::new(config, theme.scopes().to_vec()));
50+
39 let language_servers = helix_lsp::Registry::new();
51 let language_servers = helix_lsp::Registry::new();
40
52
41 // HAXX: offset the render area height by 1 to account for prompt/commandline
53 // HAXX: offset the render area height by 1 to account for prompt/commandline
@@ -135,7 +147,7 @@ impl Editor {
135 let id = if let Some(id) = id {
147 let id = if let Some(id) = id {
136 id
148 id
137 } else {
149 } else {
138− let mut doc = Document::load(path, self.theme.scopes())?;
150+ let mut doc = Document::load(path)?;
139
151
140 // try to find a language server based on the language name
152 // try to find a language server based on the language name
141 let language_server = doc
153 let language_server = doc