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,259 @@
|
||||
use ely_gpui_component::{
|
||||
editor::{
|
||||
ConsoleEntry, DebugConsole, Extension, ExtensionAction, ExtensionState, ExtensionsPanel,
|
||||
OutputPanel, Problem, ProblemsPanel,
|
||||
},
|
||||
forms::TextInput,
|
||||
primitives::Severity,
|
||||
typography::Caption,
|
||||
};
|
||||
use gpui::{App, IntoElement, ParentElement, SharedString, Styled, Window, div, px};
|
||||
|
||||
use crate::ui::{keep, section, set};
|
||||
|
||||
fn problems() -> Vec<Problem> {
|
||||
let problem = |path: &str, line, column, severity, message: &str, source: &str| Problem {
|
||||
path: path.to_string().into(),
|
||||
line,
|
||||
column,
|
||||
severity,
|
||||
message: message.to_string().into(),
|
||||
source: Some(source.to_string().into()),
|
||||
};
|
||||
vec![
|
||||
problem(
|
||||
"src/main.rs",
|
||||
45,
|
||||
21,
|
||||
Severity::Danger,
|
||||
"mismatched types: expected `u32`, found `usize`",
|
||||
"rustc",
|
||||
),
|
||||
problem(
|
||||
"src/main.rs",
|
||||
46,
|
||||
8,
|
||||
Severity::Warning,
|
||||
"unused variable: `spare`",
|
||||
"rustc",
|
||||
),
|
||||
problem(
|
||||
"src/palette.rs",
|
||||
0,
|
||||
23,
|
||||
Severity::Info,
|
||||
"a BTreeMap keeps a steady order",
|
||||
"clippy",
|
||||
),
|
||||
problem(
|
||||
"src/theme/tokens.rs",
|
||||
112,
|
||||
4,
|
||||
Severity::Warning,
|
||||
"this function has too many arguments (8/7)",
|
||||
"clippy",
|
||||
),
|
||||
]
|
||||
}
|
||||
|
||||
pub fn problems_and_output(window: &mut Window, cx: &mut App) -> impl IntoElement + use<> {
|
||||
let shown = keep(
|
||||
"panels-shown",
|
||||
|| vec![Severity::Danger, Severity::Warning, Severity::Info],
|
||||
window,
|
||||
cx,
|
||||
);
|
||||
let channel = keep("panels-channel", || SharedString::from("Build"), window, cx);
|
||||
let follow = keep("panels-follow", || true, window, cx);
|
||||
let cleared = keep("panels-cleared", || false, window, cx);
|
||||
let opened = keep("panels-problem", || None::<SharedString>, window, cx);
|
||||
let (now_shown, now_channel, now_follow, now_cleared, said) = (
|
||||
shown.read(cx).clone(),
|
||||
channel.read(cx).clone(),
|
||||
*follow.read(cx),
|
||||
*cleared.read(cx),
|
||||
opened.read(cx).clone(),
|
||||
);
|
||||
let lines: Vec<&str> = if now_cleared {
|
||||
Vec::new()
|
||||
} else if now_channel.as_ref() == "Build" {
|
||||
vec![
|
||||
" Compiling ely-gpui-component v0.1.0",
|
||||
"warning: unused variable: `spare`",
|
||||
"error[E0308]: mismatched types",
|
||||
" --> src/main.rs:46:22",
|
||||
"error: could not compile `palette` due to 1 previous error",
|
||||
]
|
||||
} else {
|
||||
vec![
|
||||
"[info] rust-analyzer started",
|
||||
"[debug] indexing 214 files",
|
||||
"[info] indexed in 1.2 s",
|
||||
]
|
||||
};
|
||||
let (show, pick, keep_up, clear, open) = (
|
||||
shown.clone(),
|
||||
channel.clone(),
|
||||
follow.clone(),
|
||||
cleared.clone(),
|
||||
opened.clone(),
|
||||
);
|
||||
let reset = cleared.clone();
|
||||
section(
|
||||
"ProblemsPanel / DiagnosticsList / OutputPanel",
|
||||
"Every problem by file, worst first, with toggles by severity; and a tool's log by channel, levels tinted, following the newest line.",
|
||||
cx,
|
||||
)
|
||||
.child(
|
||||
div()
|
||||
.flex()
|
||||
.gap_8()
|
||||
.child(
|
||||
div().flex_1().child(
|
||||
ProblemsPanel::new("panels-problems", problems())
|
||||
.shown(now_shown)
|
||||
.on_shown(move |next, _, cx| set(&show, next, cx))
|
||||
.on_open(move |problem, _, cx| {
|
||||
set(&open, Some(format!("Opened {}:{}.", problem.path, problem.line + 1).into()), cx)
|
||||
}),
|
||||
),
|
||||
)
|
||||
.child(
|
||||
div().w(px(400.)).h(px(220.)).child(
|
||||
OutputPanel::new("panels-output", ["Build", "Language server"], now_channel, lines)
|
||||
.follow(now_follow)
|
||||
.on_channel(move |name, _, cx| {
|
||||
set(&pick, name.clone(), cx);
|
||||
set(&reset, false, cx);
|
||||
})
|
||||
.on_follow(move |on, _, cx| set(&keep_up, on, cx))
|
||||
.on_clear(move |_, cx| set(&clear, true, cx)),
|
||||
),
|
||||
),
|
||||
)
|
||||
.children(said.map(Caption::new))
|
||||
}
|
||||
|
||||
pub fn console_and_extensions(window: &mut Window, cx: &mut App) -> impl IntoElement + use<> {
|
||||
let field = window.use_keyed_state("panels-console-field", cx, TextInput::new);
|
||||
let entries = keep(
|
||||
"panels-console",
|
||||
|| {
|
||||
vec![
|
||||
ConsoleEntry::Input("tints.len()".into()),
|
||||
ConsoleEntry::Value("5".into(), "usize".into()),
|
||||
ConsoleEntry::Input("palette.lookup(\"accent\", 0.5).red".into()),
|
||||
ConsoleEntry::Value("0.605".into(), "f32".into()),
|
||||
ConsoleEntry::Input("spare + missing".into()),
|
||||
ConsoleEntry::Error("cannot find value `missing` in this scope".into()),
|
||||
]
|
||||
},
|
||||
window,
|
||||
cx,
|
||||
);
|
||||
let states = keep(
|
||||
"panels-extensions",
|
||||
|| {
|
||||
vec![
|
||||
ExtensionState::Installed,
|
||||
ExtensionState::Available,
|
||||
ExtensionState::Outdated,
|
||||
ExtensionState::Disabled,
|
||||
]
|
||||
},
|
||||
window,
|
||||
cx,
|
||||
);
|
||||
let now_entries = entries.read(cx).clone();
|
||||
let now_states = states.read(cx).clone();
|
||||
let extension = |ix: usize,
|
||||
id: &str,
|
||||
name: &str,
|
||||
publisher: &str,
|
||||
description: &str,
|
||||
version: &str,
|
||||
installs: u64,
|
||||
rating: f32| Extension {
|
||||
id: id.to_string().into(),
|
||||
name: name.to_string().into(),
|
||||
publisher: publisher.to_string().into(),
|
||||
description: description.to_string().into(),
|
||||
version: version.to_string().into(),
|
||||
installs,
|
||||
rating,
|
||||
state: now_states[ix],
|
||||
};
|
||||
let extensions = vec![
|
||||
extension(
|
||||
0,
|
||||
"rust",
|
||||
"Rust",
|
||||
"Ely Tools",
|
||||
"Syntax, completions and checks for Rust.",
|
||||
"1.4.2",
|
||||
2_410_000,
|
||||
4.8,
|
||||
),
|
||||
extension(
|
||||
1,
|
||||
"toml",
|
||||
"Even Better TOML",
|
||||
"Tamasfe",
|
||||
"TOML with schemas and formatting.",
|
||||
"0.19.2",
|
||||
830_000,
|
||||
4.6,
|
||||
),
|
||||
extension(
|
||||
2,
|
||||
"lens",
|
||||
"Git Lens",
|
||||
"Line Labs",
|
||||
"Who changed each line, and when.",
|
||||
"14.1.0",
|
||||
5_900_000,
|
||||
4.4,
|
||||
),
|
||||
extension(
|
||||
3,
|
||||
"vim",
|
||||
"Vim",
|
||||
"Modal Folk",
|
||||
"Modal editing with the keys you know.",
|
||||
"1.27.3",
|
||||
1_200_000,
|
||||
4.2,
|
||||
),
|
||||
];
|
||||
let (eval, act) = (entries.clone(), states.clone());
|
||||
section(
|
||||
"DebugConsole / ExtensionsPanel / PluginList",
|
||||
"An expression prompt beside a paused program; and extensions with their reach, rating, and the one action each needs next.",
|
||||
cx,
|
||||
)
|
||||
.child(
|
||||
div()
|
||||
.flex()
|
||||
.gap_8()
|
||||
.child(
|
||||
div().w(px(380.)).child(DebugConsole::new("panels-console", &field, now_entries).on_eval(move |text, _, cx| {
|
||||
let mut next = eval.read(cx).clone();
|
||||
next.push(ConsoleEntry::Input(text.clone()));
|
||||
next.push(match text.trim().parse::<i64>() {
|
||||
Ok(value) => ConsoleEntry::Value(value.to_string().into(), "i64".into()),
|
||||
Err(_) => ConsoleEntry::Error(format!("cannot find value `{}` in this scope", text.trim()).into()),
|
||||
});
|
||||
set(&eval, next, cx)
|
||||
})),
|
||||
)
|
||||
.child(div().flex_1().child(ExtensionsPanel::new("panels-extensions", extensions).on_action(move |id, action, _, cx| {
|
||||
let ix = ["rust", "toml", "lens", "vim"].iter().position(|known| *known == id.as_ref()).expect("a listed extension");
|
||||
let mut next = act.read(cx).clone();
|
||||
next[ix] = match action {
|
||||
ExtensionAction::Install | ExtensionAction::Enable | ExtensionAction::Update => ExtensionState::Installed,
|
||||
ExtensionAction::Uninstall => ExtensionState::Available,
|
||||
};
|
||||
set(&act, next, cx)
|
||||
}))),
|
||||
)
|
||||
}
|
||||
Reference in new issue
Block a user