feat: configure command and search popup anchors
This commit is contained in:
+89
-4
@@ -1,4 +1,4 @@
|
||||
use crate::chrome::ChromeLine;
|
||||
use crate::chrome::{ChromeLine, PopupConfig};
|
||||
use crate::editor::{Context, Effect, Feature};
|
||||
use crate::plugin::{DocumentEvent, PluginEvent, PluginUpdate, UpdateEffect};
|
||||
use serde::{Deserialize, Serialize};
|
||||
@@ -40,6 +40,7 @@ pub struct Config {
|
||||
pub clipboard_mode: String,
|
||||
pub top_bar: ChromeLine,
|
||||
pub bottom_bar: ChromeLine,
|
||||
pub popup: PopupConfig,
|
||||
pub labels: BTreeMap<String, String>,
|
||||
pub diff_context_lines: usize,
|
||||
pub diff_expand_lines: usize,
|
||||
@@ -79,6 +80,7 @@ impl Default for Config {
|
||||
clipboard_mode: "system".into(),
|
||||
top_bar: ChromeLine::top(),
|
||||
bottom_bar: ChromeLine::bottom(),
|
||||
popup: PopupConfig::default(),
|
||||
labels: BTreeMap::new(),
|
||||
diff_context_lines: 10,
|
||||
diff_expand_lines: 15,
|
||||
@@ -104,6 +106,7 @@ pub fn load_config(path: &Path) -> Result<Config, String> {
|
||||
clipboard_mode,
|
||||
top_bar,
|
||||
bottom_bar,
|
||||
popup,
|
||||
labels,
|
||||
diff_context_lines,
|
||||
diff_expand_lines,
|
||||
@@ -131,6 +134,7 @@ pub fn load_config(path: &Path) -> Result<Config, String> {
|
||||
config.clipboard_mode = clipboard_mode;
|
||||
config.top_bar = top_bar;
|
||||
config.bottom_bar = bottom_bar;
|
||||
config.popup = popup;
|
||||
config.labels = labels;
|
||||
config.diff_context_lines = diff_context_lines;
|
||||
config.diff_expand_lines = diff_expand_lines;
|
||||
@@ -454,6 +458,7 @@ enum Response {
|
||||
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")]
|
||||
@@ -1183,9 +1188,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":{},"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":{},"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":{},"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}"#,
|
||||
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}"#,
|
||||
] {
|
||||
assert!(serde_json::from_str::<Response>(frame).is_err(), "{frame}");
|
||||
}
|
||||
@@ -1226,6 +1231,75 @@ end
|
||||
assert_eq!(loaded.labels["workspace"], "界 e\u{301} 👩🚀\t\n\u{1b}");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn popup_configuration_accepts_ruby_symbol_and_string_anchors_independently() {
|
||||
use crate::chrome::PopupAnchor;
|
||||
|
||||
let fixture = Fixture::new();
|
||||
let anchors = [
|
||||
("top_left", PopupAnchor::TopLeft),
|
||||
("top_center", PopupAnchor::TopCenter),
|
||||
("top_right", PopupAnchor::TopRight),
|
||||
("center_left", PopupAnchor::CenterLeft),
|
||||
("center", PopupAnchor::Center),
|
||||
("center_right", PopupAnchor::CenterRight),
|
||||
("bottom_left", PopupAnchor::BottomLeft),
|
||||
("bottom_center", PopupAnchor::BottomCenter),
|
||||
("bottom_right", PopupAnchor::BottomRight),
|
||||
];
|
||||
for (index, (command_name, command_anchor)) in anchors.iter().enumerate() {
|
||||
let (search_name, search_anchor) = anchors[(index + 1) % anchors.len()];
|
||||
let path = fixture.file(
|
||||
"config.rb",
|
||||
&format!(
|
||||
"Vamp.configure do |config|\n\
|
||||
config.popup.command = {{anchor: :{command_name}}}\n\
|
||||
config.popup.search = {{'anchor' => '{search_name}'}}\n\
|
||||
end"
|
||||
),
|
||||
);
|
||||
let loaded = load_config(&path).unwrap();
|
||||
assert_eq!(loaded.popup.command.anchor, *command_anchor);
|
||||
assert_eq!(loaded.popup.search.anchor, search_anchor);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn popup_configuration_rejects_unknown_options_anchors_callbacks_and_types() {
|
||||
let fixture = Fixture::new();
|
||||
for (value, expected) in [
|
||||
("[]", "must be a Hash"),
|
||||
("nil", "must be a Hash"),
|
||||
("7", "must be a Hash"),
|
||||
("{width: 72}", "unknown popup option"),
|
||||
("{callback: -> { 'center' }}", "unknown popup option"),
|
||||
("{anchor: :middle}", "unknown popup anchor"),
|
||||
("{anchor: 'TopLeft'}", "unknown popup anchor"),
|
||||
("{anchor: nil}", "must be a String"),
|
||||
("{anchor: 7}", "must be a String"),
|
||||
("{anchor: true}", "must be a String"),
|
||||
("{anchor: []}", "must be a String"),
|
||||
("{anchor: {}}", "must be a String"),
|
||||
("{anchor: -> { :center }}", "must be a String"),
|
||||
(
|
||||
"{anchor: :center, 'anchor' => :top_left}",
|
||||
"duplicate chrome key",
|
||||
),
|
||||
("{7 => :center}", "chrome key must be a String"),
|
||||
] {
|
||||
for mode in ["command", "search"] {
|
||||
let path = fixture.file(
|
||||
"config.rb",
|
||||
&format!("Vamp.configure {{ |config| config.popup.{mode} = {value} }}"),
|
||||
);
|
||||
let error = load_config(&path).unwrap_err();
|
||||
assert!(error.contains(expected), "{mode}={value}: {error}");
|
||||
}
|
||||
}
|
||||
let path = fixture.file("config.rb", "Vamp.configure { |config| config.popup = {} }");
|
||||
assert!(load_config(&path).unwrap_err().contains("undefined method"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn bar_namespace_is_stable_and_accepts_swapped_builtins() {
|
||||
let fixture = Fixture::new();
|
||||
@@ -1334,6 +1408,7 @@ end
|
||||
"bindings": [], "leader": "space", "file_explorer_side": "right",
|
||||
"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
|
||||
});
|
||||
for setting in ["diff_context_lines", "diff_expand_lines"] {
|
||||
@@ -1747,6 +1822,7 @@ end"#,
|
||||
"bindings": [], "leader": "space", "file_explorer_side": "right",
|
||||
"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
|
||||
});
|
||||
let Response::Config { lsp, .. } =
|
||||
@@ -1832,6 +1908,15 @@ end"#,
|
||||
"frame.delete('top_bar')",
|
||||
"frame.delete('bottom_bar')",
|
||||
"frame.delete('labels')",
|
||||
"frame.delete('popup')",
|
||||
"frame['popup'] = nil",
|
||||
"frame['popup'] = []",
|
||||
"frame['popup'] = {'selector' => {}}",
|
||||
"frame['popup'] = {'command' => nil}",
|
||||
"frame['popup'] = {'search' => 7}",
|
||||
"frame['popup'] = {'command' => {'anchor' => nil}}",
|
||||
"frame['popup'] = {'search' => {'anchor' => 'middle'}}",
|
||||
"frame['popup'] = {'command' => {'width' => 72}}",
|
||||
"frame['top_bar'] = 7",
|
||||
"frame['bottom_bar'] = []",
|
||||
"frame['labels'] = {'battery' => 7}",
|
||||
|
||||
Reference in New Issue
Block a user