Shared: generic undo History, OverflowMenu icon and tooltip, StatusBarItem leading, six Lucide icons.
209 lines
7.2 KiB
Rust
209 lines
7.2 KiB
Rust
use ely_gpui_component::{
|
|
editor::{
|
|
KeySource, Keybinding, KeybindingsEditor, Setting, SettingValue, SettingsEditor,
|
|
settings_json,
|
|
},
|
|
forms::{TextInput, json_highlights},
|
|
};
|
|
use gpui::{App, IntoElement, ParentElement, SharedString, Styled, Window, div, px};
|
|
|
|
use crate::ui::{keep, section, set};
|
|
|
|
fn settings() -> Vec<(SharedString, Vec<Setting>)> {
|
|
let number = |value, min, max| SettingValue::Number {
|
|
value,
|
|
min,
|
|
max,
|
|
step: 1.0,
|
|
};
|
|
let choice = |value: &str, choices: &[&str]| SettingValue::Choice {
|
|
value: value.to_string().into(),
|
|
choices: choices
|
|
.iter()
|
|
.map(|choice| SharedString::from(choice.to_string()))
|
|
.collect(),
|
|
};
|
|
let setting = |key: &str, title: &str, description: &str, value: SettingValue| Setting {
|
|
key: key.to_string().into(),
|
|
title: title.to_string().into(),
|
|
description: description.to_string().into(),
|
|
default: value.clone(),
|
|
value,
|
|
};
|
|
vec![
|
|
(
|
|
"Editor".into(),
|
|
vec![
|
|
setting(
|
|
"editor.fontSize",
|
|
"Font size",
|
|
"Code text size in pixels.",
|
|
number(14.0, 8.0, 32.0),
|
|
),
|
|
setting(
|
|
"editor.minimap",
|
|
"Minimap",
|
|
"A narrow map of the file beside the code.",
|
|
SettingValue::Bool(true),
|
|
),
|
|
setting(
|
|
"editor.cursorStyle",
|
|
"Cursor style",
|
|
"How the cursor draws.",
|
|
choice("line", &["line", "block", "underline"]),
|
|
),
|
|
],
|
|
),
|
|
(
|
|
"Files".into(),
|
|
vec![
|
|
setting(
|
|
"files.autoSave",
|
|
"Auto save",
|
|
"When files save themselves.",
|
|
choice("afterDelay", &["off", "afterDelay", "onFocusChange"]),
|
|
),
|
|
setting(
|
|
"files.trimTrailingWhitespace",
|
|
"Trim trailing whitespace",
|
|
"Drops spaces at line ends on save.",
|
|
SettingValue::Bool(false),
|
|
),
|
|
],
|
|
),
|
|
]
|
|
}
|
|
|
|
pub fn settings_and_keys(window: &mut Window, cx: &mut App) -> impl IntoElement + use<> {
|
|
let groups = keep("panels-settings", settings, window, cx);
|
|
let section_now = keep("panels-section", || 0usize, window, cx);
|
|
let json = keep("panels-json", || false, window, cx);
|
|
let json_field = window.use_keyed_state("panels-json-field", cx, |window, cx| {
|
|
TextInput::new(window, cx)
|
|
.multi_line(6, 12)
|
|
.highlighter(json_highlights)
|
|
});
|
|
let (now_groups, now_section, now_json) = (
|
|
groups.read(cx).clone(),
|
|
*section_now.read(cx),
|
|
*json.read(cx),
|
|
);
|
|
let (change, pick, flip, seed, source) = (
|
|
groups.clone(),
|
|
section_now.clone(),
|
|
json.clone(),
|
|
json_field.clone(),
|
|
groups.clone(),
|
|
);
|
|
let recording = keep("panels-recording", || None::<SharedString>, window, cx);
|
|
let bindings = keep(
|
|
"panels-bindings",
|
|
|| {
|
|
let binding =
|
|
|command: &str, title: &str, keys: Option<&str>, when: Option<&str>, source| {
|
|
Keybinding {
|
|
command: command.to_string().into(),
|
|
title: title.to_string().into(),
|
|
keys: keys.map(|keys| keys.to_string().into()),
|
|
when: when.map(|when| when.to_string().into()),
|
|
source,
|
|
}
|
|
};
|
|
vec![
|
|
binding(
|
|
"editor.save",
|
|
"Save",
|
|
Some("secondary-s"),
|
|
None,
|
|
KeySource::Default,
|
|
),
|
|
binding(
|
|
"editor.sortLines",
|
|
"Sort lines",
|
|
Some("secondary-s"),
|
|
None,
|
|
KeySource::User,
|
|
),
|
|
binding(
|
|
"editor.comment",
|
|
"Toggle comment",
|
|
Some("secondary-/"),
|
|
Some("editorFocus"),
|
|
KeySource::Default,
|
|
),
|
|
binding(
|
|
"editor.selectNext",
|
|
"Select next match",
|
|
Some("secondary-d"),
|
|
Some("editorFocus"),
|
|
KeySource::Default,
|
|
),
|
|
binding(
|
|
"terminal.split",
|
|
"Split terminal",
|
|
Some("secondary-s"),
|
|
Some("terminalFocus"),
|
|
KeySource::User,
|
|
),
|
|
binding(
|
|
"editor.fold",
|
|
"Fold",
|
|
None,
|
|
Some("editorFocus"),
|
|
KeySource::Default,
|
|
),
|
|
]
|
|
},
|
|
window,
|
|
cx,
|
|
);
|
|
let (now_recording, now_bindings) = (recording.read(cx).clone(), bindings.read(cx).clone());
|
|
let (record, bind, done) = (recording.clone(), bindings.clone(), recording.clone());
|
|
let editor = SettingsEditor::new("panels-settings-editor", now_groups.clone())
|
|
.section(now_section)
|
|
.on_section(move |ix, _, cx| set(&pick, ix, cx))
|
|
.on_json(move |on, _, cx| {
|
|
if on {
|
|
let text = settings_json(source.read(cx));
|
|
seed.update(cx, |field, cx| field.set_text(text, cx));
|
|
}
|
|
set(&flip, on, cx)
|
|
})
|
|
.on_change(move |key, value, _, cx| {
|
|
let mut next = change.read(cx).clone();
|
|
for (_, list) in &mut next {
|
|
for setting in list.iter_mut().filter(|setting| setting.key == *key) {
|
|
setting.value = value.clone();
|
|
}
|
|
}
|
|
set(&change, next, cx)
|
|
});
|
|
let editor = if now_json {
|
|
editor.json(&json_field)
|
|
} else {
|
|
editor
|
|
};
|
|
section(
|
|
"SettingsEditor / KeybindingsEditor",
|
|
"Settings as controls by section, each change marked with a way back, or as the JSON a settings file holds; and every command's keys, clashes marked. Double-press a command to record new keys.",
|
|
cx,
|
|
)
|
|
.child(div().w(px(840.)).child(editor))
|
|
.child(
|
|
div().w(px(840.)).child(
|
|
KeybindingsEditor::new("panels-keys", now_bindings)
|
|
.recording(now_recording)
|
|
.on_record(move |command, _, cx| set(&record, Some(command.clone()), cx))
|
|
.on_bind(move |command, stroke, _, cx| {
|
|
let mut next = bind.read(cx).clone();
|
|
if let Some(binding) = next.iter_mut().find(|binding| binding.command == *command) {
|
|
binding.keys = stroke.map(|stroke| stroke.unparse().into());
|
|
binding.source = KeySource::User;
|
|
}
|
|
set(&bind, next, cx);
|
|
set(&done, None, cx)
|
|
}),
|
|
),
|
|
)
|
|
}
|