T17 Editor: CodeEditor with gutter, folds, minimap, rulers, guides, brackets, whitespace, cursors, multi-cursor, sticky scroll, inlay hints, lenses, decorations, ghost text, inline chat and diff (T17a); completions, signatures, hover, code actions, rename, references, outline, go to symbol, call and type hierarchy (T17b); find and replace, search panel and filters (T17c); problems, output, debug console, extensions, settings with JSON, keybindings, theme previews, welcome, recent projects, switcher, task runner (T17d); status items (T17e)
Shared: generic undo History, OverflowMenu icon and tooltip, StatusBarItem leading, six Lucide icons. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
c229a096ca
commit
d05754ac19
59 files changed
+10820
-71
No files matched your search
@@ -0,0 +1,208 @@
|
||||
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)
|
||||
}),
|
||||
),
|
||||
)
|
||||
}
|
||||
Reference in new issue
Block a user