@@ -17,7 +17,7 @@ pub enum Mode {
1717pub struct Document {
1818 pub state: State, // rope + selection
1919 /// File path on disk.
20− pub path: Option<PathBuf>,
20+ path: Option<PathBuf>,
2121
2222 /// Current editing mode.
2323 pub mode: Mode,
@@ -26,13 +26,16 @@ pub struct Document {
2626 /// Tree-sitter AST tree
2727 pub syntax: Option<Syntax>,
2828 /// Corresponding language scope name. Usually `source.<lang>`.
29− pub language: Option<String>,
29+ language: Option<String>,
3030
3131 /// Pending changes since last history commit.
32− pub changes: ChangeSet,
33− pub old_state: Option<State>,
34− pub history: History,
35− pub version: i32, // should be usize?
32+ changes: ChangeSet,
33+ /// State at last commit. Used for calculating reverts.
34+ old_state: Option<State>,
35+ /// Undo tree.
36+ history: History,
37+ /// Current document version, incremented at each change.
38+ version: i32, // should be usize?
3639
3740 pub diagnostics: Vec<Diagnostic>,
3841 pub language_server: Option<Arc<helix_lsp::Client>>,
@@ -90,23 +93,8 @@ impl Document {
9093
9194 let mut doc = Self::new(State::new(doc));
9295
93− if let Some(language_config) = LOADER.language_config_for_file_name(path.as_path()) {
94− let highlight_config = language_config.highlight_config(scopes).unwrap().unwrap();
95− // TODO: config.configure(scopes) is now delayed, is that ok?
96−
97− let syntax = Syntax::new(&doc.state.doc, highlight_config.clone());
98−
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());
102−
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.
105−
106− // TODO: circular dep: view <-> lsp
107− // helix_lsp::REGISTRY;
108− // view should probably depend on lsp
109− };
96+ let language_config = LOADER.language_config_for_file_name(path.as_path());
97+ doc.set_language(language_config, scopes);
11098
11199 // canonicalize path to absolute value
112100 doc.path = Some(std::fs::canonicalize(path)?);
@@ -140,17 +128,35 @@ impl Document {
140128 } // and_then notify save
141129 }
142130
143− pub fn set_language(&mut self, scope: &str, scopes: &[String]) {
144− if let Some(language_config) = LOADER.language_config_for_scope(scope) {
131+ pub fn set_language(
132+ &mut self,
133+ language_config: Option<Arc<helix_core::syntax::LanguageConfiguration>>,
134+ scopes: &[String],
135+ ) {
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());
139+
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.
142+
145143 let highlight_config = language_config.highlight_config(scopes).unwrap().unwrap();
146144 // TODO: config.configure(scopes) is now delayed, is that ok?
147145
148146 let syntax = Syntax::new(&self.state.doc, highlight_config.clone());
149147
150148 self.syntax = Some(syntax);
149+ } else {
150+ self.syntax = None;
151+ self.language = None;
151152 };
152153 }
153154
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);
158+ }
159+
154160 pub fn set_language_server(&mut self, language_server: Option<Arc<helix_lsp::Client>>) {
155161 self.language_server = language_server;
156162 }
@@ -238,11 +244,44 @@ impl Document {
238244 false
239245 }
240246
247+ pub fn append_changes_to_history(&mut self) {
248+ if self.changes.is_empty() {
249+ return;
250+ }
251+
252+ // TODO: change -> change -> undo -> change -> change fails, probably old_state needs reset
253+
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());
259+
260+ // increment document version
261+ self.version += 1;
262+
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");
265+
266+ self.history.commit_revision(&transaction, &old_state);
267+ }
268+
241269 #[inline]
242270 pub fn mode(&self) -> Mode {
243271 self.mode
244272 }
245273
274+ #[inline]
275+ /// Corresponding language scope name. Usually `source.<lang>`.
276+ pub fn language(&self) -> Option<&str> {
277+ self.language.as_ref().map(String::as_str)
278+ }
279+
280+ #[inline]
281+ pub fn version(&self) -> i32 {
282+ self.version
283+ }
284+
246285 #[inline]
247286 pub fn path(&self) -> Option<&PathBuf> {
248287 self.path.as_ref()