Skip to content

Commit

Permalink
Merge pull request #459 from cmyr/feature/poc-autoindent
Browse files Browse the repository at this point in the history
very, very, really quite basic auto indent
  • Loading branch information
cmyr committed Jan 4, 2018
2 parents c43c805 + 85ef6d4 commit 53f4267
Show file tree
Hide file tree
Showing 10 changed files with 179 additions and 32 deletions.
3 changes: 3 additions & 0 deletions rust/core-lib/assets/client_example.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,6 @@ plugin_search_path = []
font_face = "InconsolataGo"
# In points
font_size = 14

# automatically match current indentation level on newline
auto_indent = true
2 changes: 2 additions & 0 deletions rust/core-lib/assets/defaults.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,5 @@ font_face = "InconsolataGo"
font_size = 14

line_ending = "\n"

auto_indent = true
2 changes: 2 additions & 0 deletions rust/core-lib/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ mod defaults {
"translate_tabs_to_spaces",
"font_face",
"font_size",
"auto_indent",
];
/// config keys that are only legal at the top level
pub const TOP_LEVEL_KEYS: &'static [&'static str] = &[
Expand Down Expand Up @@ -187,6 +188,7 @@ pub struct BufferItems {
pub translate_tabs_to_spaces: bool,
pub font_face: String,
pub font_size: f32,
pub auto_indent: bool,
}

pub type BufferConfig = Config<BufferItems>;
Expand Down
13 changes: 10 additions & 3 deletions rust/core-lib/src/editor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ use plugins::rpc::{PluginUpdate, PluginEdit, ScopeSpan, PluginBufferInfo,
ClientPluginInfo};
use plugins::{PluginPid, Command};
use layers::Scopes;
use config::BufferConfig;
use config::{BufferConfig, Table};


#[cfg(not(target_os = "fuchsia"))]
Expand Down Expand Up @@ -176,10 +176,15 @@ impl Editor {
}
}

pub fn set_config(&mut self, conf: BufferConfig) {
/// Sets the config for this buffer. If the new config differs
/// from the existing config, returns the modified items.
pub fn set_config(&mut self, conf: BufferConfig) -> Option<Table> {
if let Some(changes) = conf.changes_from(Some(&self.config)) {
self.config = conf;
self.doc_ctx.config_changed(&self.view.view_id, &changes);
Some(changes)
} else {
None
}
}

Expand Down Expand Up @@ -218,9 +223,11 @@ impl Editor {
pub fn plugin_init_info(&self) -> PluginBufferInfo {
let nb_lines = self.text.measure::<LinesMetric>() + 1;
let views = vec![self.view.view_id];
let config = self.config.to_table();
PluginBufferInfo::new(self.buffer_id, &views,
self.engine.get_head_rev_id().token(), self.text.len(),
nb_lines, self.path.clone(), self.syntax.clone())
nb_lines, self.path.clone(), self.syntax.clone(),
config)
}

/// Send initial config state to the client.
Expand Down
1 change: 1 addition & 0 deletions rust/core-lib/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ pub use plugins::rpc as plugin_rpc;
pub use plugins::PluginPid;
pub use tabs::ViewIdentifier;
pub use syntax::SyntaxDefinition;
pub use config::{BufferItems as BufferConfig, Table as ConfigTable};

use internal::tabs;
use internal::editor;
Expand Down
8 changes: 8 additions & 0 deletions rust/core-lib/src/plugins/manager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ use serde_json::{self, Value};
use xi_rpc::{RpcCtx, Handler, RemoteError};

use tabs::{BufferIdentifier, ViewIdentifier, BufferContainerRef};
use config::Table;

use super::{PluginCatalog, PluginRef, start_plugin_process, PluginPid};
use super::rpc::{PluginNotification, PluginRequest, PluginCommand,
Expand Down Expand Up @@ -474,6 +475,13 @@ impl PluginManagerRef {
self.start_plugins(view_id, &init_info, &to_run);
}

/// Notifies plugins of a user config change
pub fn document_config_changed(&self, view_id: ViewIdentifier,
changes: &Table) {
self.lock().notify_plugins(view_id, false, "config_changed",
&json!({"view_id": view_id, "changes": changes}));
}

/// Launches and initializes the named plugin.
pub fn start_plugin(&self,
view_id: ViewIdentifier,
Expand Down
12 changes: 9 additions & 3 deletions rust/core-lib/src/plugins/rpc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ use serde_json::{self, Value};
use super::PluginPid;
use syntax::SyntaxDefinition;
use tabs::{BufferIdentifier, ViewIdentifier};
use config::Table;

//TODO: At the moment (May 08, 2017) this is all very much in flux.
// At some point, it will be stabalized and then perhaps will live in another crate,
Expand All @@ -45,6 +46,7 @@ pub struct PluginBufferInfo {
#[serde(skip_serializing_if = "Option::is_none")]
pub path: Option<String>,
pub syntax: SyntaxDefinition,
pub config: Table,
}

//TODO: very likely this should be merged with PluginDescription
Expand Down Expand Up @@ -100,6 +102,7 @@ pub enum HostNotification {
Ping(EmptyStruct),
Initialize { plugin_id: PluginPid, buffer_info: Vec<PluginBufferInfo> },
DidSave { view_id: ViewIdentifier, path: PathBuf },
ConfigChanged { view_id: ViewIdentifier, changes: Table },
NewBuffer { buffer_info: Vec<PluginBufferInfo> },
DidClose { view_id: ViewIdentifier },
Shutdown(EmptyStruct),
Expand Down Expand Up @@ -201,11 +204,13 @@ impl<'de, T: Deserialize<'de>> Deserialize<'de> for PluginCommand<T>
impl PluginBufferInfo {
pub fn new(buffer_id: BufferIdentifier, views: &[ViewIdentifier],
rev: u64, buf_size: usize, nb_lines: usize,
path: Option<PathBuf>, syntax: SyntaxDefinition) -> Self {
path: Option<PathBuf>, syntax: SyntaxDefinition,
config: Table) -> Self {
//TODO: do make any current assertions about paths being valid utf-8? do we want to?
let path = path.map(|p| p.to_str().unwrap().to_owned());
let views = views.to_owned();
PluginBufferInfo { buffer_id, views, rev, buf_size, nb_lines, path, syntax }
PluginBufferInfo { buffer_id, views, rev, buf_size,
nb_lines, path, syntax, config }
}
}

Expand Down Expand Up @@ -260,7 +265,8 @@ mod tests {
"buf_size": 20,
"nb_lines": 5,
"path": "some_path",
"syntax": "toml"}"#;
"syntax": "toml",
"config": {"some_key": 420}}"#;

let val: PluginBufferInfo = match serde_json::from_str(json) {
Ok(val) => val,
Expand Down
23 changes: 16 additions & 7 deletions rust/core-lib/src/tabs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -699,13 +699,22 @@ impl Documents {

/// Notify editors/views/plugins of config changes.
fn after_config_change(&self) {
let mut editors = self.buffers.lock();
for ed in editors.iter_editors_mut() {
let syntax = ed.get_syntax().to_owned();
let identifier = ed.get_main_view_id();
let new_config = self.config_manager.get_buffer_config(syntax,
identifier);
ed.set_config(new_config)
let mut to_notify = Vec::new();
{
let mut editors = self.buffers.lock();
for ed in editors.iter_editors_mut() {
let syntax = ed.get_syntax().to_owned();
let identifier = ed.get_main_view_id();
let new_config = self.config_manager.get_buffer_config(syntax,
identifier);
if let Some(changes) = ed.set_config(new_config) {
to_notify.push((identifier, changes));
}
}
}
// update plugins after releasing the lock
for (view_id, changes) in to_notify.drain(..) {
self.plugins.document_config_changed(view_id, &changes);
}
}
}
Expand Down
64 changes: 46 additions & 18 deletions rust/plugin-lib/src/state_cache.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,12 @@
//! A more sophisticated cache that manages user state.

use std::path::PathBuf;
use serde_json::Value;
use serde_json::{self, Value};
use bytecount;
use rand::{thread_rng, Rng};

use xi_core::{PluginPid, ViewIdentifier, SyntaxDefinition, plugin_rpc};
use xi_core::{PluginPid, ViewIdentifier, SyntaxDefinition, plugin_rpc,
ConfigTable, BufferConfig};
use xi_rpc::{RemoteError, ReadError};

use plugin_base;
Expand All @@ -36,7 +37,9 @@ pub trait Plugin {
type State: Default + Clone;

fn initialize(&mut self, ctx: PluginCtx<Self::State>, buf_size: usize);
fn update(&mut self, ctx: PluginCtx<Self::State>);
fn update(&mut self, ctx: PluginCtx<Self::State>, start: usize,
end: usize, new_len: usize, rev: usize, text: &Option<String>)
-> Option<Value>;
fn did_save(&mut self, ctx: PluginCtx<Self::State>);
#[allow(unused_variables)]
fn idle(&mut self, ctx: PluginCtx<Self::State>, token: usize) {}
Expand Down Expand Up @@ -70,6 +73,8 @@ struct CacheState<S> {
frontier: Vec<usize>,

syntax: SyntaxDefinition,
config_table: ConfigTable,
config: Option<BufferConfig>,
path: Option<PathBuf>,
}

Expand All @@ -93,11 +98,11 @@ impl<'a, P: Plugin> plugin_base::Handler for CacheHandler<'a, P> {
};
match rpc {
Ping( .. ) => (),
Initialize { plugin_id, ref buffer_info } => {
let info = buffer_info.first()
.expect("buffer_info always contains at least one item");
Initialize { plugin_id, mut buffer_info } => {
let info = buffer_info.remove(0);
ctx.do_initialize(info, plugin_id, self.handler);
}
ConfigChanged { changes, .. } => ctx.do_config_changed(changes),
DidSave { ref path, .. } => ctx.do_did_save(path, self.handler),
NewBuffer { .. } | DidClose { .. } => eprintln!("Rust plugin lib \
does not support global plugins"),
Expand Down Expand Up @@ -137,19 +142,34 @@ pub fn mainloop<P: Plugin>(handler: &mut P) -> Result<(), ReadError> {
}

impl<'a, S: Default + Clone> PluginCtx<'a, S> {
fn do_initialize<P>(mut self, init_info: &plugin_rpc::PluginBufferInfo,
fn do_initialize<P>(mut self, init_info: plugin_rpc::PluginBufferInfo,
plugin_id: PluginPid, handler: &mut P)
where P: Plugin<State = S>
{
let plugin_rpc::PluginBufferInfo {
mut views, rev, buf_size,
path, syntax, config, ..
} = init_info;

self.state.plugin_id = plugin_id;
self.state.buf_size = init_info.buf_size;
assert_eq!(init_info.views.len(), 1);
self.state.view_id = init_info.views[0].clone();
self.state.rev = init_info.rev;
self.state.syntax = init_info.syntax.clone();
self.state.path = init_info.path.clone().map(|p| PathBuf::from(p));
self.state.buf_size = buf_size;
assert_eq!(views.len(), 1);
self.state.view_id = views.remove(0);
self.state.rev = rev;
self.state.syntax = syntax;
self.state.config_table = config.clone();
self.state.config = serde_json::from_value(Value::Object(config)).unwrap();
self.state.path = path.map(|p| PathBuf::from(p));
self.truncate_frontier(0);
handler.initialize(self, init_info.buf_size);
handler.initialize(self, buf_size);
}

fn do_config_changed(self, changes: ConfigTable) {
for (key, value) in changes.iter() {
self.state.config_table.insert(key.to_owned(), value.to_owned());
}
let conf = serde_json::from_value(Value::Object(self.state.config_table.clone()));
self.state.config = conf.unwrap();
}

fn do_did_save<P: Plugin<State = S>>(self, path: &PathBuf, handler: &mut P) {
Expand All @@ -163,7 +183,7 @@ impl<'a, S: Default + Clone> PluginCtx<'a, S> {
let plugin_rpc::PluginUpdate { start, end, new_len, text, rev, .. } = update;
self.state.buf_size = self.state.buf_size - (end - start) + new_len;
self.state.rev = rev;
if let Some(text) = text {
if let Some(ref text) = text {
let off = self.state.chunk_offset;
if start >= off && start <= off + self.state.chunk.len() {
let nlc_tail = if end <= off + self.state.chunk.len() {
Expand Down Expand Up @@ -193,8 +213,8 @@ impl<'a, S: Default + Clone> PluginCtx<'a, S> {
self.state.chunk_offset = 0;
self.truncate_cache(start);
}
handler.update(self);
Value::from(0i32)
handler.update(self, start, end, new_len, rev as usize, &text)
.unwrap_or(Value::from(0i32))
}

pub fn get_path(&self) -> Option<&PathBuf> {
Expand All @@ -204,6 +224,14 @@ impl<'a, S: Default + Clone> PluginCtx<'a, S> {
}
}

pub fn get_config(&self) -> &BufferConfig {
self.state.config.as_ref().unwrap()
}

pub fn get_syntax(&self) -> SyntaxDefinition {
self.state.syntax
}

pub fn add_scopes(&self, scopes: &Vec<Vec<String>>) {
self.peer.add_scopes(self.state.plugin_id, &self.state.view_id, scopes)
}
Expand Down Expand Up @@ -233,7 +261,7 @@ impl<'a, S: Default + Clone> PluginCtx<'a, S> {
}

/// Find an entry in the cache by offset. Similar to `find_line`.
fn find_offset(&self, offset: usize) -> Result<usize, usize> {
pub fn find_offset(&self, offset: usize) -> Result<usize, usize> {
self.state.state_cache.binary_search_by(|probe| probe.offset.cmp(&offset))
}

Expand Down
Loading

0 comments on commit 53f4267

Please sign in to comment.