use futures::{future, Future};
use serde_json::Value;
use errors::ClientError;
use protocol;
use serde_json::{from_value, to_value};
use serde::Serialize;
use structs::ViewId;
pub type ClientResult<T> = Box<Future<Item = T, Error = ClientError>>;
#[derive(Clone)]
pub struct Client(pub protocol::Client);
fn get_edit_params<T: Serialize>(
view_id: ViewId,
method: &str,
params: Option<T>,
) -> Result<Value, ClientError> {
let params_value = if let Some(params) = params {
to_value(params)?
} else {
json!([])
};
Ok(json!({
"method": method,
"view_id": view_id,
"params": params_value,
}))
}
impl Client {
pub fn notify(&mut self, method: &str, params: Value) -> ClientResult<()> {
info!(">>> notification: method={}, params={}", method, ¶ms);
Box::new(
self.0
.notify(method, params)
.map_err(|_| ClientError::NotifyFailed),
)
}
pub fn request(&mut self, method: &str, params: Value) -> ClientResult<Value> {
info!(">>> request : method={}, params={}", method, ¶ms);
Box::new(self.0.request(method, params).then(
|response| match response {
Ok(Ok(value)) => Ok(value),
Ok(Err(value)) => Err(ClientError::ErrorReturned(value)),
Err(_) => Err(ClientError::RequestFailed),
},
))
}
pub fn edit<T: Serialize>(
&mut self,
view_id: ViewId,
method: &str,
params: Option<T>,
) -> ClientResult<()> {
match get_edit_params(view_id, method, params) {
Ok(value) => self.notify("edit", value),
Err(e) => Box::new(future::err(e)),
}
}
pub fn scroll(&mut self, view_id: ViewId, first_line: u64, last_line: u64) -> ClientResult<()> {
self.edit(view_id, "scroll", Some(json!([first_line, last_line])))
}
pub fn left(&mut self, view_id: ViewId) -> ClientResult<()> {
self.edit(view_id, "move_left", None as Option<Value>)
}
pub fn left_sel(&mut self, view_id: ViewId) -> ClientResult<()> {
self.edit(
view_id,
"move_left_and_modify_selection",
None as Option<Value>,
)
}
pub fn right(&mut self, view_id: ViewId) -> ClientResult<()> {
self.edit(view_id, "move_right", None as Option<Value>)
}
pub fn right_sel(&mut self, view_id: ViewId) -> ClientResult<()> {
self.edit(
view_id,
"move_right_and_modify_selection",
None as Option<Value>,
)
}
pub fn up(&mut self, view_id: ViewId) -> ClientResult<()> {
self.edit(view_id, "move_up", None as Option<Value>)
}
pub fn up_sel(&mut self, view_id: ViewId) -> ClientResult<()> {
self.edit(
view_id,
"move_up_and_modify_selection",
None as Option<Value>,
)
}
pub fn down(&mut self, view_id: ViewId) -> ClientResult<()> {
self.edit(view_id, "move_down", None as Option<Value>)
}
pub fn down_sel(&mut self, view_id: ViewId) -> ClientResult<()> {
self.edit(
view_id,
"move_down_and_modify_selection",
None as Option<Value>,
)
}
pub fn backspace(&mut self, view_id: ViewId) -> ClientResult<()> {
self.del(view_id)
}
pub fn delete(&mut self, view_id: ViewId) -> ClientResult<()> {
self.edit(view_id, "delete_forward", None as Option<Value>)
}
pub fn del(&mut self, view_id: ViewId) -> ClientResult<()> {
self.edit(view_id, "delete_backward", None as Option<Value>)
}
pub fn page_up(&mut self, view_id: ViewId) -> ClientResult<()> {
self.edit(view_id, "scroll_page_up", None as Option<Value>)
}
pub fn page_up_sel(&mut self, view_id: ViewId) -> ClientResult<()> {
self.edit(
view_id,
"scroll_page_up_and_modify_selection",
None as Option<Value>,
)
}
pub fn page_down(&mut self, view_id: ViewId) -> ClientResult<()> {
self.edit(view_id, "scroll_page_down", None as Option<Value>)
}
pub fn page_down_sel(&mut self, view_id: ViewId) -> ClientResult<()> {
self.edit(
view_id,
"scroll_page_down_and_modify_selection",
None as Option<Value>,
)
}
pub fn insert_newline(&mut self, view_id: ViewId) -> ClientResult<()> {
self.edit(view_id, "insert_newline", None as Option<Value>)
}
pub fn f1(&mut self, view_id: ViewId) -> ClientResult<()> {
self.edit(view_id, "debug_rewrap", None as Option<Value>)
}
pub fn f2(&mut self, view_id: ViewId) -> ClientResult<()> {
self.edit(view_id, "debug_test_fg_spans", None as Option<Value>)
}
pub fn char(&mut self, view_id: ViewId, ch: char) -> ClientResult<()> {
self.edit(view_id, "insert", Some(json!({ "chars": ch })))
}
pub fn click(&mut self, view_id: ViewId, line: u64, column: u64) -> ClientResult<()> {
self.edit(view_id, "click", Some(json!([line, column, 0, 1])))
}
pub fn drag(&mut self, view_id: ViewId, line: u64, column: u64) -> ClientResult<()> {
self.edit(view_id, "drag", Some(json!([line, column, 0])))
}
pub fn new_view(&mut self, file_path: Option<String>) -> ClientResult<ViewId> {
let params = if let Some(file_path) = file_path {
json!({ "file_path": file_path })
} else {
json!({})
};
let result = self.request("new_view", params)
.and_then(|result| from_value::<ViewId>(result).map_err(From::from));
Box::new(result)
}
pub fn close_view(&mut self, view_id: ViewId) -> ClientResult<()> {
self.notify("close_view", json!({ "view_id": view_id }))
}
pub fn save(&mut self, view_id: ViewId, file_path: &str) -> ClientResult<()> {
let params = json!({"view_id": view_id, "file_path": file_path});
Box::new(self.notify("save", params).and_then(|_| Ok(())))
}
pub fn set_theme(&mut self, theme: &str) -> ClientResult<()> {
let params = json!({ "theme_name": theme });
Box::new(self.notify("set_theme", params).and_then(|_| Ok(())))
}
pub fn client_started(&mut self, config_dir: Option<&str>) -> ClientResult<()> {
let params = match config_dir {
Some(path) => json!({"config_dir":path}),
None => json!({})
};
self.notify("client_started", params)
}
pub fn start_plugin(&mut self, view_id: ViewId, name: &str) -> ClientResult<()> {
let params = json!({"view_id": view_id, "plugin_name": name});
Box::new(self.notify("start", params).and_then(|_| Ok(())))
}
pub fn stop_plugin(&mut self, view_id: ViewId, name: &str) -> ClientResult<()> {
let params = json!({"view_id": view_id, "plugin_name": name});
Box::new(self.notify("stop", params).and_then(|_| Ok(())))
}
pub fn notify_plugin(
&mut self,
view_id: ViewId,
plugin: &str,
method: &str,
params: &Value,
) -> ClientResult<()> {
let params = json!({
"view_id": view_id,
"receiver": plugin,
"notification": {
"method": method,
"params": params,
}
});
Box::new(self.notify("plugin_rpc", params).and_then(|_| Ok(())))
}
}