feat: add configurable diff modes and split orientation
This commit is contained in:
+75
-61
@@ -44,6 +44,8 @@ pub struct Config {
|
||||
pub labels: BTreeMap<String, String>,
|
||||
pub diff_context_lines: usize,
|
||||
pub diff_expand_lines: usize,
|
||||
pub diff_view_mode: crate::diff::ViewMode,
|
||||
pub diff_split_orientation: crate::panes::SplitAxis,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
@@ -84,6 +86,8 @@ impl Default for Config {
|
||||
labels: BTreeMap::new(),
|
||||
diff_context_lines: 10,
|
||||
diff_expand_lines: 15,
|
||||
diff_view_mode: crate::diff::ViewMode::Split,
|
||||
diff_split_orientation: crate::panes::SplitAxis::Vertical,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -95,23 +99,26 @@ pub fn load_config(path: &Path) -> Result<Config, String> {
|
||||
let mut host = Host::spawn("config", &path, &serde_json::json!({}))?;
|
||||
let response = host.receive(deadline)?;
|
||||
match response {
|
||||
Response::Config {
|
||||
plugins,
|
||||
lsp,
|
||||
bindings,
|
||||
leader,
|
||||
file_explorer_side,
|
||||
file_picker_view,
|
||||
file_explorer_view,
|
||||
clipboard_mode,
|
||||
top_bar,
|
||||
bottom_bar,
|
||||
popup,
|
||||
labels,
|
||||
diff_context_lines,
|
||||
diff_expand_lines,
|
||||
..
|
||||
} => {
|
||||
Response::Config(response) => {
|
||||
let ConfigFrame {
|
||||
plugins,
|
||||
lsp,
|
||||
bindings,
|
||||
leader,
|
||||
file_explorer_side,
|
||||
file_picker_view,
|
||||
file_explorer_view,
|
||||
clipboard_mode,
|
||||
top_bar,
|
||||
bottom_bar,
|
||||
popup,
|
||||
labels,
|
||||
diff_context_lines,
|
||||
diff_expand_lines,
|
||||
diff_view_mode,
|
||||
diff_split_orientation,
|
||||
..
|
||||
} = *response;
|
||||
let mut config = Config::default();
|
||||
let directory = path.parent().expect("absolute file has a parent");
|
||||
for plugin in plugins {
|
||||
@@ -138,6 +145,8 @@ pub fn load_config(path: &Path) -> Result<Config, String> {
|
||||
config.labels = labels;
|
||||
config.diff_context_lines = diff_context_lines;
|
||||
config.diff_expand_lines = diff_expand_lines;
|
||||
config.diff_view_mode = diff_view_mode;
|
||||
config.diff_split_orientation = diff_split_orientation;
|
||||
Ok(config)
|
||||
}
|
||||
Response::Error {
|
||||
@@ -429,6 +438,36 @@ fn diff_expand_lines<'de, D: serde::Deserializer<'de>>(deserializer: D) -> Resul
|
||||
diff_line_count(deserializer, "diff_expand_lines", 1)
|
||||
}
|
||||
|
||||
// Startup-only configuration does not inflate every queued plugin response.
|
||||
#[derive(Deserialize)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
struct ConfigFrame {
|
||||
version: u8,
|
||||
plugins: Vec<PluginConfig>,
|
||||
// Keep this wire field required; resolve its configuration after decoding.
|
||||
#[serde(deserialize_with = "serde_json::Value::deserialize")]
|
||||
lsp: serde_json::Value,
|
||||
bindings: Vec<Binding>,
|
||||
leader: String,
|
||||
file_explorer_side: String,
|
||||
file_picker_view: String,
|
||||
file_explorer_view: String,
|
||||
clipboard_mode: String,
|
||||
#[serde(deserialize_with = "crate::chrome::top")]
|
||||
top_bar: ChromeLine,
|
||||
#[serde(deserialize_with = "crate::chrome::bottom")]
|
||||
bottom_bar: ChromeLine,
|
||||
popup: PopupConfig,
|
||||
#[serde(deserialize_with = "crate::chrome::labels")]
|
||||
labels: BTreeMap<String, String>,
|
||||
#[serde(deserialize_with = "diff_context_lines")]
|
||||
diff_context_lines: usize,
|
||||
#[serde(deserialize_with = "diff_expand_lines")]
|
||||
diff_expand_lines: usize,
|
||||
diff_view_mode: crate::diff::ViewMode,
|
||||
diff_split_orientation: crate::panes::SplitAxis,
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
#[serde(tag = "type", deny_unknown_fields)]
|
||||
enum Response {
|
||||
@@ -442,30 +481,7 @@ enum Response {
|
||||
asynchronous: bool,
|
||||
},
|
||||
#[serde(rename = "config")]
|
||||
Config {
|
||||
version: u8,
|
||||
plugins: Vec<PluginConfig>,
|
||||
// Keep this wire field required; resolve its configuration after decoding.
|
||||
#[serde(deserialize_with = "serde_json::Value::deserialize")]
|
||||
lsp: serde_json::Value,
|
||||
bindings: Vec<Binding>,
|
||||
leader: String,
|
||||
file_explorer_side: String,
|
||||
file_picker_view: String,
|
||||
file_explorer_view: String,
|
||||
clipboard_mode: String,
|
||||
#[serde(deserialize_with = "crate::chrome::top")]
|
||||
top_bar: ChromeLine,
|
||||
#[serde(deserialize_with = "crate::chrome::bottom")]
|
||||
bottom_bar: ChromeLine,
|
||||
popup: PopupConfig,
|
||||
#[serde(deserialize_with = "crate::chrome::labels")]
|
||||
labels: BTreeMap<String, String>,
|
||||
#[serde(deserialize_with = "diff_context_lines")]
|
||||
diff_context_lines: usize,
|
||||
#[serde(deserialize_with = "diff_expand_lines")]
|
||||
diff_expand_lines: usize,
|
||||
},
|
||||
Config(Box<ConfigFrame>),
|
||||
#[serde(rename = "result")]
|
||||
Result {
|
||||
version: u8,
|
||||
@@ -497,10 +513,10 @@ impl Response {
|
||||
fn version(&self) -> u8 {
|
||||
match self {
|
||||
Self::Manifest { version, .. }
|
||||
| Self::Config { version, .. }
|
||||
| Self::Result { version, .. }
|
||||
| Self::Update { version, .. }
|
||||
| Self::Error { version, .. } => *version,
|
||||
Self::Config(config) => config.version,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1188,9 +1204,9 @@ end
|
||||
assert!(load_config(&path).unwrap_err().contains(error), "{value}");
|
||||
}
|
||||
for frame in [
|
||||
r#"{"type":"config","version":1,"plugins":[],"lsp":{},"bindings":[],"file_explorer_side":"right","file_picker_view":"list","file_explorer_view":"tree","clipboard_mode":"system","top_bar":{},"bottom_bar":{},"popup":{"command":{},"search":{}},"labels":{},"diff_context_lines":10,"diff_expand_lines":15}"#,
|
||||
r#"{"type":"config","version":1,"plugins":[],"lsp":{},"bindings":[],"leader":null,"file_explorer_side":"right","file_picker_view":"list","file_explorer_view":"tree","clipboard_mode":"system","top_bar":{},"bottom_bar":{},"popup":{"command":{},"search":{}},"labels":{},"diff_context_lines":10,"diff_expand_lines":15}"#,
|
||||
r#"{"type":"config","version":1,"plugins":[],"lsp":{},"bindings":[],"leader":7,"file_explorer_side":"right","file_picker_view":"list","file_explorer_view":"tree","clipboard_mode":"system","top_bar":{},"bottom_bar":{},"popup":{"command":{},"search":{}},"labels":{},"diff_context_lines":10,"diff_expand_lines":15}"#,
|
||||
r#"{"type":"config","version":1,"plugins":[],"lsp":{},"bindings":[],"file_explorer_side":"right","file_picker_view":"list","file_explorer_view":"tree","clipboard_mode":"system","top_bar":{},"bottom_bar":{},"popup":{"command":{},"search":{}},"labels":{},"diff_context_lines":10,"diff_expand_lines":15,"diff_view_mode":"split","diff_split_orientation":"left_right"}"#,
|
||||
r#"{"type":"config","version":1,"plugins":[],"lsp":{},"bindings":[],"leader":null,"file_explorer_side":"right","file_picker_view":"list","file_explorer_view":"tree","clipboard_mode":"system","top_bar":{},"bottom_bar":{},"popup":{"command":{},"search":{}},"labels":{},"diff_context_lines":10,"diff_expand_lines":15,"diff_view_mode":"split","diff_split_orientation":"left_right"}"#,
|
||||
r#"{"type":"config","version":1,"plugins":[],"lsp":{},"bindings":[],"leader":7,"file_explorer_side":"right","file_picker_view":"list","file_explorer_view":"tree","clipboard_mode":"system","top_bar":{},"bottom_bar":{},"popup":{"command":{},"search":{}},"labels":{},"diff_context_lines":10,"diff_expand_lines":15,"diff_view_mode":"split","diff_split_orientation":"left_right"}"#,
|
||||
] {
|
||||
assert!(serde_json::from_str::<Response>(frame).is_err(), "{frame}");
|
||||
}
|
||||
@@ -1408,7 +1424,8 @@ end
|
||||
"file_picker_view": "tree", "file_explorer_view": "tree",
|
||||
"top_bar": {}, "bottom_bar": {}, "labels": {},
|
||||
"popup": {"command": {}, "search": {}},
|
||||
"clipboard_mode": "system", "diff_context_lines": 0, "diff_expand_lines": 7
|
||||
"clipboard_mode": "system", "diff_context_lines": 0, "diff_expand_lines": 7,
|
||||
"diff_view_mode": "split", "diff_split_orientation": "left_right"
|
||||
});
|
||||
for setting in ["diff_context_lines", "diff_expand_lines"] {
|
||||
for value in [
|
||||
@@ -1822,22 +1839,21 @@ end"#,
|
||||
"file_picker_view": "tree", "file_explorer_view": "tree",
|
||||
"top_bar": {}, "bottom_bar": {}, "labels": {},
|
||||
"popup": {"command": {}, "search": {}},
|
||||
"clipboard_mode": "system", "diff_context_lines": 10, "diff_expand_lines": 15
|
||||
"clipboard_mode": "system", "diff_context_lines": 10, "diff_expand_lines": 15,
|
||||
"diff_view_mode": "split", "diff_split_orientation": "left_right"
|
||||
});
|
||||
let Response::Config { lsp, .. } =
|
||||
serde_json::from_value::<Response>(frame.clone()).unwrap()
|
||||
let Response::Config(config) = serde_json::from_value::<Response>(frame.clone()).unwrap()
|
||||
else {
|
||||
panic!("expected config frame");
|
||||
};
|
||||
assert!(crate::lsp_config::resolve(lsp).unwrap().is_empty());
|
||||
assert!(crate::lsp_config::resolve(config.lsp).unwrap().is_empty());
|
||||
frame["lsp"] = serde_json::json!({"rust": true});
|
||||
let Response::Config { lsp, .. } =
|
||||
serde_json::from_value::<Response>(frame.clone()).unwrap()
|
||||
let Response::Config(config) = serde_json::from_value::<Response>(frame.clone()).unwrap()
|
||||
else {
|
||||
panic!("expected config frame");
|
||||
};
|
||||
assert_eq!(
|
||||
crate::lsp_config::resolve(lsp).unwrap()[0].command,
|
||||
crate::lsp_config::resolve(config.lsp).unwrap()[0].command,
|
||||
["rust-analyzer"]
|
||||
);
|
||||
for value in [
|
||||
@@ -1861,12 +1877,12 @@ end"#,
|
||||
serde_json::json!({"python": {"servers": [{"command": ["server"]}], "settings": {}}}),
|
||||
] {
|
||||
frame["lsp"] = value;
|
||||
let Response::Config { lsp, .. } =
|
||||
let Response::Config(config) =
|
||||
serde_json::from_value::<Response>(frame.clone()).unwrap()
|
||||
else {
|
||||
panic!("expected config frame");
|
||||
};
|
||||
assert!(crate::lsp_config::resolve(lsp).is_err(), "{frame}");
|
||||
assert!(crate::lsp_config::resolve(config.lsp).is_err(), "{frame}");
|
||||
}
|
||||
let mut languages: serde_json::Map<String, serde_json::Value> = (0..14)
|
||||
.map(|index| {
|
||||
@@ -1878,20 +1894,18 @@ end"#,
|
||||
.collect();
|
||||
languages.insert("python".into(), serde_json::json!(true));
|
||||
frame["lsp"] = serde_json::Value::Object(languages);
|
||||
let Response::Config { lsp, .. } =
|
||||
serde_json::from_value::<Response>(frame.clone()).unwrap()
|
||||
let Response::Config(config) = serde_json::from_value::<Response>(frame.clone()).unwrap()
|
||||
else {
|
||||
panic!("expected config frame");
|
||||
};
|
||||
assert_eq!(crate::lsp_config::resolve(lsp).unwrap().len(), 16);
|
||||
assert_eq!(crate::lsp_config::resolve(config.lsp).unwrap().len(), 16);
|
||||
frame["lsp"]["ruby"] = serde_json::json!(true);
|
||||
let Response::Config { lsp, .. } =
|
||||
serde_json::from_value::<Response>(frame.clone()).unwrap()
|
||||
let Response::Config(config) = serde_json::from_value::<Response>(frame.clone()).unwrap()
|
||||
else {
|
||||
panic!("expected config frame");
|
||||
};
|
||||
assert_eq!(
|
||||
crate::lsp_config::resolve(lsp).unwrap_err(),
|
||||
crate::lsp_config::resolve(config.lsp).unwrap_err(),
|
||||
"LSP configuration supports at most 16 configured servers"
|
||||
);
|
||||
frame.as_object_mut().unwrap().remove("lsp");
|
||||
|
||||
Reference in New Issue
Block a user