@@ -17,7 +17,7 @@ pub enum Mode {
17pub struct Document {
17pub struct Document {
18 pub state: State, // rope + selection
18 pub state: State, // rope + selection
19 /// File path on disk.
19 /// File path on disk.
20− pub path: Option<PathBuf>,
20+ path: Option<PathBuf>,
22 /// Current editing mode.
22 /// Current editing mode.
23 pub mode: Mode,
23 pub mode: Mode,
@@ -26,13 +26,16 @@ pub struct Document {
26 /// Tree-sitter AST tree
26 /// Tree-sitter AST tree
27 pub syntax: Option<Syntax>,
27 pub syntax: Option<Syntax>,
28 /// Corresponding language scope name. Usually `source.<lang>`.
28 /// Corresponding language scope name. Usually `source.<lang>`.
29− pub language: Option<String>,
29+ language: Option<String>,
31 /// Pending changes since last history commit.
31 /// Pending changes since last history commit.
32− pub changes: ChangeSet,
32+ changes: ChangeSet,
33+ /// State at last commit. Used for calculating reverts.
33− pub old_state: Option<State>,
34+ old_state: Option<State>,
34− pub history: History,
36+ history: History,
37+ /// Current document version, incremented at each change.
35− pub version: i32, // should be usize?
38+ version: i32, // should be usize?
37 pub diagnostics: Vec<Diagnostic>,
40 pub diagnostics: Vec<Diagnostic>,
38 pub language_server: Option<Arc<helix_lsp::Client>>,
41 pub language_server: Option<Arc<helix_lsp::Client>>,
@@ -90,23 +93,8 @@ impl Document {
91 let mut doc = Self::new(State::new(doc));
94 let mut doc = Self::new(State::new(doc));
93− if let Some(language_config) = LOADER.language_config_for_file_name(path.as_path()) {
96+ let language_config = LOADER.language_config_for_file_name(path.as_path());
94− let highlight_config = language_config.highlight_config(scopes).unwrap().unwrap();
97+ doc.set_language(language_config, scopes);
95− // TODO: config.configure(scopes) is now delayed, is that ok?
97− let syntax = Syntax::new(&doc.state.doc, highlight_config.clone());
99− doc.syntax = Some(syntax);
100− // TODO: maybe just keep an Arc<> pointer to the language_config?
101− doc.language = Some(language_config.scope().to_string());
103− // TODO: this ties lsp support to tree-sitter enabled languages for now. Language
104− // config should use Option<HighlightConfig> to let us have non-tree-sitter configs.
106− // TODO: circular dep: view <-> lsp
107− // helix_lsp::REGISTRY;
108− // view should probably depend on lsp
111 // canonicalize path to absolute value
99 // canonicalize path to absolute value
112 doc.path = Some(std::fs::canonicalize(path)?);
100 doc.path = Some(std::fs::canonicalize(path)?);
@@ -140,17 +128,35 @@ impl Document {
140 } // and_then notify save
128 } // and_then notify save
143− pub fn set_language(&mut self, scope: &str, scopes: &[String]) {
131+ pub fn set_language(
133+ language_config: Option<Arc<helix_core::syntax::LanguageConfiguration>>,
144− if let Some(language_config) = LOADER.language_config_for_scope(scope) {
136+ if let Some(language_config) = language_config {
137+ // TODO: maybe just keep an Arc<> pointer to the language_config?
138+ self.language = Some(language_config.scope().to_string());
140+ // TODO: this ties lsp support to tree-sitter enabled languages for now. Language
141+ // config should use Option<HighlightConfig> to let us have non-tree-sitter configs.
145 let highlight_config = language_config.highlight_config(scopes).unwrap().unwrap();
143 let highlight_config = language_config.highlight_config(scopes).unwrap().unwrap();
146 // TODO: config.configure(scopes) is now delayed, is that ok?
144 // TODO: config.configure(scopes) is now delayed, is that ok?
148 let syntax = Syntax::new(&self.state.doc, highlight_config.clone());
146 let syntax = Syntax::new(&self.state.doc, highlight_config.clone());
150 self.syntax = Some(syntax);
148 self.syntax = Some(syntax);
151+ self.language = None;
155+ pub fn set_language2(&mut self, scope: &str, scopes: &[String]) {
156+ let language_config = LOADER.language_config_for_scope(scope);
157+ self.set_language(language_config, scopes);
154 pub fn set_language_server(&mut self, language_server: Option<Arc<helix_lsp::Client>>) {
160 pub fn set_language_server(&mut self, language_server: Option<Arc<helix_lsp::Client>>) {
155 self.language_server = language_server;
161 self.language_server = language_server;
@@ -238,11 +244,44 @@ impl Document {
247+ pub fn append_changes_to_history(&mut self) {
248+ if self.changes.is_empty() {
252+ // TODO: change -> change -> undo -> change -> change fails, probably old_state needs reset
254+ let new_changeset = ChangeSet::new(self.text());
255+ let changes = std::mem::replace(&mut self.changes, new_changeset);
256+ // Instead of doing this messy merge we could always commit, and based on transaction
257+ // annotations either add a new layer or compose into the previous one.
258+ let transaction = Transaction::from(changes).with_selection(self.selection().clone());
260+ // increment document version
263+ // HAXX: we need to reconstruct the state as it was before the changes..
264+ let old_state = self.old_state.take().expect("no old_state available");
266+ self.history.commit_revision(&transaction, &old_state);
241 #[inline]
269 #[inline]
242 pub fn mode(&self) -> Mode {
270 pub fn mode(&self) -> Mode {
243 self.mode
271 self.mode
275+ /// Corresponding language scope name. Usually `source.<lang>`.
276+ pub fn language(&self) -> Option<&str> {
277+ self.language.as_ref().map(String::as_str)
281+ pub fn version(&self) -> i32 {
246 #[inline]
285 #[inline]
247 pub fn path(&self) -> Option<&PathBuf> {
286 pub fn path(&self) -> Option<&PathBuf> {
248 self.path.as_ref()
287 self.path.as_ref()