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.
This commit is contained in:
1 parent
a894e5f973
commit
5545ce6458
59 files changed
+10820
-71
No files matched your search
@@ -0,0 +1,241 @@
|
||||
use ely_gpui_component::{
|
||||
buttons::Button,
|
||||
editor::{
|
||||
ActionKind, Call, CallHierarchy, CodeAction, CodeActionMenu, CompletionItem,
|
||||
CompletionMenu, FileHits, GoToSymbol, Hit, HoverInfo, ReferencesPanel, RenameInput,
|
||||
Signature, SignatureHelp, Symbol, SymbolKind, SymbolOutline, completions,
|
||||
},
|
||||
forms::TextInput,
|
||||
primitives::Severity,
|
||||
typography::Caption,
|
||||
};
|
||||
use gpui::{App, IntoElement, ParentElement, SharedString, Styled, Window, div, px};
|
||||
|
||||
use crate::ui::{keep, row, section, set};
|
||||
|
||||
fn items() -> Vec<CompletionItem> {
|
||||
vec![
|
||||
CompletionItem::new("lookup", SymbolKind::Method)
|
||||
.detail("fn(&self, &str, f32) -> Color")
|
||||
.docs("The color for a name, blended toward white by lift."),
|
||||
CompletionItem::new("insert", SymbolKind::Method).detail("fn(&mut self, &str, Color)"),
|
||||
CompletionItem::new("colors", SymbolKind::Field).detail("HashMap<String, Color>"),
|
||||
CompletionItem::new("fallback", SymbolKind::Field).detail("Color"),
|
||||
CompletionItem::new("len", SymbolKind::Method).detail("fn(&self) -> usize"),
|
||||
CompletionItem::new("Palette", SymbolKind::Struct).detail("struct Palette"),
|
||||
CompletionItem::new("loop", SymbolKind::Keyword),
|
||||
]
|
||||
}
|
||||
|
||||
pub fn hints(window: &mut Window, cx: &mut App) -> impl IntoElement + use<> {
|
||||
let overload = keep("intel-overload", || 0usize, window, cx);
|
||||
let told = keep("intel-told", || None::<SharedString>, window, cx);
|
||||
let (over, said) = (*overload.read(cx), told.read(cx).clone());
|
||||
let chosen = completions(&items(), "lo")
|
||||
.iter()
|
||||
.position(|(item, _)| item.label.as_ref() == "lookup")
|
||||
.expect("lookup fits lo");
|
||||
let param = |label: &str, text: &str| {
|
||||
let start = label.find(text).expect("the parameter is in the label");
|
||||
start..start + text.len()
|
||||
};
|
||||
let (long, short) = (
|
||||
"fn lookup(&self, name: &str, lift: f32) -> Color",
|
||||
"fn lookup(&self, name: &str) -> Color",
|
||||
);
|
||||
let (pick, step, tell) = (told.clone(), overload.clone(), told.clone());
|
||||
let signatures = [
|
||||
Signature {
|
||||
label: long.into(),
|
||||
params: vec![param(long, "name: &str"), param(long, "lift: f32")],
|
||||
docs: Some("The color for a name, blended toward white by lift.".into()),
|
||||
},
|
||||
Signature {
|
||||
label: short.into(),
|
||||
params: vec![param(short, "name: &str")],
|
||||
docs: Some("The color for a name as it is.".into()),
|
||||
},
|
||||
];
|
||||
section(
|
||||
"CompletionMenu / SignatureHelp / HoverInfo",
|
||||
"Completions as you type, the typed letters marked and the chosen one's documentation beside; the call's signature with the parameter at the cursor; and what a hover over a symbol reads.",
|
||||
cx,
|
||||
)
|
||||
.child(
|
||||
row()
|
||||
.items_start()
|
||||
.gap_8()
|
||||
.child(
|
||||
CompletionMenu::new("intel-menu", items())
|
||||
.typed("lo")
|
||||
.selected(chosen)
|
||||
.on_pick(move |item, _, cx| set(&pick, Some(format!("Picked {}.", item.label).into()), cx)),
|
||||
)
|
||||
.child(
|
||||
div()
|
||||
.flex()
|
||||
.flex_col()
|
||||
.gap_4()
|
||||
.child(
|
||||
SignatureHelp::new("intel-signature", signatures)
|
||||
.at(over, 1)
|
||||
.on_step(move |next, _, cx| set(&step, next, cx)),
|
||||
)
|
||||
.child(
|
||||
HoverInfo::new("intel-hover", "pub fn lookup(&self, name: &str, lift: f32) -> Color")
|
||||
.problem(Severity::Warning, "`lift` outside 0..=1 is clamped")
|
||||
.docs("The color for `name`, blended toward white by `lift`.")
|
||||
.docs("Unknown names read as the fallback color.")
|
||||
.link("Go to definition", move |_, cx| set(&tell, Some("Went to palette.rs:23.".into()), cx))
|
||||
.link("Find references", |_, _| {}),
|
||||
),
|
||||
),
|
||||
)
|
||||
.children(said.map(Caption::new))
|
||||
}
|
||||
|
||||
fn symbols() -> Vec<Symbol> {
|
||||
vec![
|
||||
Symbol::new("Palette", SymbolKind::Struct, 3).children([
|
||||
Symbol::new("colors", SymbolKind::Field, 4).detail("HashMap<String, Color>"),
|
||||
Symbol::new("fallback", SymbolKind::Field, 5).detail("Color"),
|
||||
]),
|
||||
Symbol::new("Color", SymbolKind::Struct, 9),
|
||||
Symbol::new("impl Palette", SymbolKind::Module, 15).children([
|
||||
Symbol::new("new", SymbolKind::Method, 16).detail("fn(Color) -> Self"),
|
||||
Symbol::new("insert", SymbolKind::Method, 23),
|
||||
Symbol::new("lookup", SymbolKind::Method, 28).detail("fn(&self, &str, f32) -> Color"),
|
||||
]),
|
||||
Symbol::new("main", SymbolKind::Function, 42),
|
||||
]
|
||||
}
|
||||
|
||||
pub fn navigate(window: &mut Window, cx: &mut App) -> impl IntoElement + use<> {
|
||||
let cursor = keep("intel-cursor", || 30usize, window, cx);
|
||||
let palette = keep("intel-goto", || false, window, cx);
|
||||
let incoming = keep("intel-incoming", || true, window, cx);
|
||||
let rename_open = keep("intel-rename", || false, window, cx);
|
||||
let field = window.use_keyed_state("intel-rename-field", cx, |window, cx| {
|
||||
let mut field = TextInput::new(window, cx);
|
||||
field.set_text("lookup", cx);
|
||||
field
|
||||
});
|
||||
let (line, open, inbound, renaming) = (
|
||||
*cursor.read(cx),
|
||||
*palette.read(cx),
|
||||
*incoming.read(cx),
|
||||
*rename_open.read(cx),
|
||||
);
|
||||
let (pick, go, close, flip) = (
|
||||
cursor.clone(),
|
||||
cursor.clone(),
|
||||
palette.clone(),
|
||||
incoming.clone(),
|
||||
);
|
||||
let opener = palette.clone();
|
||||
let (renamer, done, cancel) = (
|
||||
rename_open.clone(),
|
||||
rename_open.clone(),
|
||||
rename_open.clone(),
|
||||
);
|
||||
let hit = |line: usize, text: &str| {
|
||||
let start = text.find("lookup").expect("the line names lookup");
|
||||
let name = start..start + "lookup".len();
|
||||
Hit {
|
||||
line,
|
||||
text: text.to_string().into(),
|
||||
ranges: vec![name],
|
||||
}
|
||||
};
|
||||
let references = [
|
||||
FileHits {
|
||||
path: "src/palette.rs".into(),
|
||||
hits: vec![hit(
|
||||
27,
|
||||
" pub fn lookup(&self, name: &str, lift: f32) -> Color {",
|
||||
)],
|
||||
},
|
||||
FileHits {
|
||||
path: "src/main.rs".into(),
|
||||
hits: vec![
|
||||
hit(
|
||||
44,
|
||||
" let tints: Vec<Color> = (0..5u8).map(|step| palette.lookup(\"accent\", step as f32 / 4.0)).collect();",
|
||||
),
|
||||
hit(51, " let text = palette.lookup(\"fg\", 0.0);"),
|
||||
],
|
||||
},
|
||||
];
|
||||
let callers = Call {
|
||||
name: "lookup".into(),
|
||||
kind: SymbolKind::Method,
|
||||
place: "palette.rs:28".into(),
|
||||
calls: vec![
|
||||
Call {
|
||||
name: "main".into(),
|
||||
kind: SymbolKind::Function,
|
||||
place: "main.rs:44".into(),
|
||||
calls: Vec::new(),
|
||||
},
|
||||
Call {
|
||||
name: "paint_theme".into(),
|
||||
kind: SymbolKind::Function,
|
||||
place: "theme.rs:12".into(),
|
||||
calls: vec![Call {
|
||||
name: "render".into(),
|
||||
kind: SymbolKind::Method,
|
||||
place: "app.rs:88".into(),
|
||||
calls: Vec::new(),
|
||||
}],
|
||||
},
|
||||
],
|
||||
};
|
||||
let fixes = [
|
||||
CodeAction::new("Change type of `count` to `usize`", ActionKind::QuickFix).preferred(),
|
||||
CodeAction::new("Convert with `u32::try_from`", ActionKind::QuickFix),
|
||||
CodeAction::new("Extract into function", ActionKind::Refactor),
|
||||
CodeAction::new("Inline variable", ActionKind::Refactor),
|
||||
CodeAction::new("Organize imports", ActionKind::Source),
|
||||
];
|
||||
section(
|
||||
"CodeActionMenu / RenameInput / PeekView / ReferencesPanel / SymbolOutline / GoToSymbol / CallHierarchy / TypeHierarchy",
|
||||
"Fixes and refactors behind a lightbulb; renaming in place; where a symbol is used; a file's symbols as a tree that follows the cursor, or as a palette to jump by name; and who calls a function.",
|
||||
cx,
|
||||
)
|
||||
.child(
|
||||
row()
|
||||
.gap_4()
|
||||
.child(CodeActionMenu::new("intel-actions", fixes))
|
||||
.child(Button::new("intel-goto-open", "Go to symbol…").on_click(move |_, _, cx| set(&opener, true, cx)))
|
||||
.child(Button::new("intel-rename-open", "Rename lookup").on_click(move |_, _, cx| set(&renamer, true, cx)))
|
||||
.child(Caption::new(format!("Cursor on line {}.", line + 1))),
|
||||
)
|
||||
.children(renaming.then(|| {
|
||||
RenameInput::new("intel-rename-box", &field)
|
||||
.on_rename(move |_, _, cx| set(&done, false, cx))
|
||||
.on_cancel(move |_, cx| set(&cancel, false, cx))
|
||||
}))
|
||||
.child(
|
||||
row()
|
||||
.items_start()
|
||||
.gap_8()
|
||||
.child(
|
||||
div().w(px(300.)).h(px(240.)).child(
|
||||
SymbolOutline::new("intel-outline", symbols())
|
||||
.cursor(line)
|
||||
.on_pick(move |line, _, cx| set(&pick, line, cx)),
|
||||
),
|
||||
)
|
||||
.child(
|
||||
div().w(px(300.)).h(px(240.)).child(
|
||||
CallHierarchy::new("intel-calls", callers, inbound)
|
||||
.on_flip(move |incoming, _, cx| set(&flip, incoming, cx)),
|
||||
),
|
||||
),
|
||||
)
|
||||
.child(div().w(px(840.)).child(ReferencesPanel::new("intel-references", "lookup", references)))
|
||||
.children(open.then(|| {
|
||||
GoToSymbol::new("intel-goto-palette", symbols(), move |_, cx| set(&close, false, cx))
|
||||
.on_pick(move |line, _, cx| set(&go, line, cx))
|
||||
}))
|
||||
}
|
||||
Reference in new issue
Block a user