mirror of https://github.com/helix-editor/helix
Compare commits
2 Commits
27d8bd20bf
...
5ce27b0087
Author | SHA1 | Date |
---|---|---|
|
5ce27b0087 | |
|
70deab1b19 |
|
@ -3215,9 +3215,9 @@ fn buffer_picker(cx: &mut Context) {
|
||||||
spans.push(icon.to_span_with(|icon| format!("{icon} ")));
|
spans.push(icon.to_span_with(|icon| format!("{icon} ")));
|
||||||
}
|
}
|
||||||
|
|
||||||
spans.push(Span::raw(name.to_string()));
|
spans.push(name.to_string().into());
|
||||||
|
|
||||||
Cell::from(Spans::from(spans))
|
Spans::from(spans).into()
|
||||||
}),
|
}),
|
||||||
];
|
];
|
||||||
let picker = Picker::new(columns, 2, items, (), |cx, meta, action| {
|
let picker = Picker::new(columns, 2, items, (), |cx, meta, action| {
|
||||||
|
@ -3281,7 +3281,6 @@ fn jumplist_picker(cx: &mut Context) {
|
||||||
.as_deref()
|
.as_deref()
|
||||||
.and_then(Path::to_str)
|
.and_then(Path::to_str)
|
||||||
.unwrap_or(SCRATCH_BUFFER_NAME);
|
.unwrap_or(SCRATCH_BUFFER_NAME);
|
||||||
|
|
||||||
let icons = ICONS.load();
|
let icons = ICONS.load();
|
||||||
|
|
||||||
let mut spans = Vec::with_capacity(2);
|
let mut spans = Vec::with_capacity(2);
|
||||||
|
@ -3290,9 +3289,9 @@ fn jumplist_picker(cx: &mut Context) {
|
||||||
spans.push(icon.to_span_with(|icon| format!("{icon} ")));
|
spans.push(icon.to_span_with(|icon| format!("{icon} ")));
|
||||||
}
|
}
|
||||||
|
|
||||||
spans.push(Span::raw(name.to_string()));
|
spans.push(name.to_string().into());
|
||||||
|
|
||||||
Cell::from(Spans::from(spans))
|
Spans::from(spans).into()
|
||||||
}),
|
}),
|
||||||
ui::PickerColumn::new("flags", |item: &JumpMeta, _| {
|
ui::PickerColumn::new("flags", |item: &JumpMeta, _| {
|
||||||
let mut flags = Vec::new();
|
let mut flags = Vec::new();
|
||||||
|
|
|
@ -247,7 +247,6 @@ fn diag_picker(
|
||||||
"severity",
|
"severity",
|
||||||
|item: &PickerDiagnostic, styles: &DiagnosticStyles| {
|
|item: &PickerDiagnostic, styles: &DiagnosticStyles| {
|
||||||
let icons = ICONS.load();
|
let icons = ICONS.load();
|
||||||
|
|
||||||
match item.diag.severity {
|
match item.diag.severity {
|
||||||
Some(DiagnosticSeverity::HINT) => {
|
Some(DiagnosticSeverity::HINT) => {
|
||||||
Span::styled(format!("{} HINT", icons.diagnostic().hint()), styles.hint)
|
Span::styled(format!("{} HINT", icons.diagnostic().hint()), styles.hint)
|
||||||
|
@ -416,9 +415,8 @@ pub fn symbol_picker(cx: &mut Context) {
|
||||||
let call = move |_editor: &mut Editor, compositor: &mut Compositor| {
|
let call = move |_editor: &mut Editor, compositor: &mut Compositor| {
|
||||||
let columns = [
|
let columns = [
|
||||||
ui::PickerColumn::new("kind", |item: &SymbolInformationItem, _| {
|
ui::PickerColumn::new("kind", |item: &SymbolInformationItem, _| {
|
||||||
let name = display_symbol_kind(item.symbol.kind);
|
|
||||||
|
|
||||||
let icons = ICONS.load();
|
let icons = ICONS.load();
|
||||||
|
let name = display_symbol_kind(item.symbol.kind);
|
||||||
|
|
||||||
if let Some(icon) = icons.kind().get(name) {
|
if let Some(icon) = icons.kind().get(name) {
|
||||||
icon.to_span_with(|icon| format!("{icon} {name}")).into()
|
icon.to_span_with(|icon| format!("{icon} {name}")).into()
|
||||||
|
|
|
@ -107,8 +107,8 @@ impl menu::Item for CompletionItem {
|
||||||
};
|
};
|
||||||
|
|
||||||
let icons = ICONS.load();
|
let icons = ICONS.load();
|
||||||
|
|
||||||
let name = &kind.0[0].content;
|
let name = &kind.0[0].content;
|
||||||
|
|
||||||
let is_folder = kind.0[0].content == "folder";
|
let is_folder = kind.0[0].content == "folder";
|
||||||
|
|
||||||
if let Some(icon) = icons.kind().get(name) {
|
if let Some(icon) = icons.kind().get(name) {
|
||||||
|
|
|
@ -9,7 +9,6 @@ use helix_core::{visual_offset_from_block, Position, RopeSlice};
|
||||||
use helix_stdx::rope::RopeSliceExt;
|
use helix_stdx::rope::RopeSliceExt;
|
||||||
use helix_view::editor::{WhitespaceConfig, WhitespaceRenderValue};
|
use helix_view::editor::{WhitespaceConfig, WhitespaceRenderValue};
|
||||||
use helix_view::graphics::Rect;
|
use helix_view::graphics::Rect;
|
||||||
use helix_view::icons::ICONS;
|
|
||||||
use helix_view::theme::Style;
|
use helix_view::theme::Style;
|
||||||
use helix_view::view::ViewPosition;
|
use helix_view::view::ViewPosition;
|
||||||
use helix_view::{Document, Theme};
|
use helix_view::{Document, Theme};
|
||||||
|
@ -207,41 +206,38 @@ impl<'a> TextRenderer<'a> {
|
||||||
viewport: Rect,
|
viewport: Rect,
|
||||||
) -> TextRenderer<'a> {
|
) -> TextRenderer<'a> {
|
||||||
let editor_config = doc.config.load();
|
let editor_config = doc.config.load();
|
||||||
|
let WhitespaceConfig {
|
||||||
let WhitespaceConfig { render } = &editor_config.whitespace;
|
render: ws_render,
|
||||||
|
characters: ws_chars,
|
||||||
|
} = &editor_config.whitespace;
|
||||||
|
|
||||||
let tab_width = doc.tab_width();
|
let tab_width = doc.tab_width();
|
||||||
|
let tab = if ws_render.tab() == WhitespaceRenderValue::All {
|
||||||
let icons = ICONS.load();
|
std::iter::once(ws_chars.tab)
|
||||||
|
.chain(std::iter::repeat(ws_chars.tabpad).take(tab_width - 1))
|
||||||
let whitespace = icons.ui().r#virtual();
|
|
||||||
|
|
||||||
let tab = if render.tab() == WhitespaceRenderValue::All {
|
|
||||||
std::iter::once(whitespace.tab())
|
|
||||||
.chain(std::iter::repeat(whitespace.tabpad()).take(tab_width - 1))
|
|
||||||
.collect()
|
.collect()
|
||||||
} else {
|
} else {
|
||||||
" ".repeat(tab_width)
|
" ".repeat(tab_width)
|
||||||
};
|
};
|
||||||
let virtual_tab = " ".repeat(tab_width);
|
let virtual_tab = " ".repeat(tab_width);
|
||||||
let newline = if render.newline() == WhitespaceRenderValue::All {
|
let newline = if ws_render.newline() == WhitespaceRenderValue::All {
|
||||||
whitespace.newline().into()
|
ws_chars.newline.into()
|
||||||
} else {
|
} else {
|
||||||
" ".to_owned()
|
" ".to_owned()
|
||||||
};
|
};
|
||||||
|
|
||||||
let space = if render.space() == WhitespaceRenderValue::All {
|
let space = if ws_render.space() == WhitespaceRenderValue::All {
|
||||||
whitespace.space().into()
|
ws_chars.space.into()
|
||||||
} else {
|
} else {
|
||||||
" ".to_owned()
|
" ".to_owned()
|
||||||
};
|
};
|
||||||
let nbsp = if render.nbsp() == WhitespaceRenderValue::All {
|
let nbsp = if ws_render.nbsp() == WhitespaceRenderValue::All {
|
||||||
whitespace.nbsp().into()
|
ws_chars.nbsp.into()
|
||||||
} else {
|
} else {
|
||||||
" ".to_owned()
|
" ".to_owned()
|
||||||
};
|
};
|
||||||
let nnbsp = if render.nnbsp() == WhitespaceRenderValue::All {
|
let nnbsp = if ws_render.nnbsp() == WhitespaceRenderValue::All {
|
||||||
whitespace.nnbsp().into()
|
ws_chars.nnbsp.into()
|
||||||
} else {
|
} else {
|
||||||
" ".to_owned()
|
" ".to_owned()
|
||||||
};
|
};
|
||||||
|
@ -275,7 +271,6 @@ impl<'a> TextRenderer<'a> {
|
||||||
offset,
|
offset,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Draws a single `grapheme` at the current render position with a specified `style`.
|
/// Draws a single `grapheme` at the current render position with a specified `style`.
|
||||||
pub fn draw_decoration_grapheme(
|
pub fn draw_decoration_grapheme(
|
||||||
&mut self,
|
&mut self,
|
||||||
|
|
|
@ -235,8 +235,7 @@ impl EditorView {
|
||||||
theme: &Theme,
|
theme: &Theme,
|
||||||
) {
|
) {
|
||||||
let editor_rulers = &editor.config().rulers;
|
let editor_rulers = &editor.config().rulers;
|
||||||
|
let ruler_theme = theme
|
||||||
let style = theme
|
|
||||||
.try_get("ui.virtual.ruler")
|
.try_get("ui.virtual.ruler")
|
||||||
.unwrap_or_else(|| Style::default().bg(Color::Red));
|
.unwrap_or_else(|| Style::default().bg(Color::Red));
|
||||||
|
|
||||||
|
@ -254,12 +253,7 @@ impl EditorView {
|
||||||
.filter_map(|ruler| ruler.checked_sub(1 + view_offset.horizontal_offset as u16))
|
.filter_map(|ruler| ruler.checked_sub(1 + view_offset.horizontal_offset as u16))
|
||||||
.filter(|ruler| ruler < &viewport.width)
|
.filter(|ruler| ruler < &viewport.width)
|
||||||
.map(|ruler| viewport.clip_left(ruler).with_width(1))
|
.map(|ruler| viewport.clip_left(ruler).with_width(1))
|
||||||
.for_each(|area| {
|
.for_each(|area| surface.set_style(area, ruler_theme))
|
||||||
let icons = ICONS.load();
|
|
||||||
for y in area.y..area.height {
|
|
||||||
surface.set_string(area.x, y, icons.ui().r#virtual().ruler(), style);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn viewport_byte_range(
|
fn viewport_byte_range(
|
||||||
|
@ -589,7 +583,7 @@ impl EditorView {
|
||||||
let mut x = viewport.x;
|
let mut x = viewport.x;
|
||||||
let current_doc = view!(editor).doc;
|
let current_doc = view!(editor).doc;
|
||||||
|
|
||||||
for doc in editor.documents() {
|
for (idx, doc) in editor.documents().enumerate() {
|
||||||
let fname = doc
|
let fname = doc
|
||||||
.path()
|
.path()
|
||||||
.unwrap_or(&scratch)
|
.unwrap_or(&scratch)
|
||||||
|
@ -604,9 +598,24 @@ impl EditorView {
|
||||||
bufferline_inactive
|
bufferline_inactive
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let lang = doc.language_name().unwrap_or(DEFAULT_LANGUAGE_NAME);
|
||||||
|
|
||||||
let icons = ICONS.load();
|
let icons = ICONS.load();
|
||||||
|
|
||||||
let lang = doc.language_name().unwrap_or(DEFAULT_LANGUAGE_NAME);
|
// Render the separator before the text if the current document is not first.
|
||||||
|
if idx > 0 {
|
||||||
|
let used_width = viewport.x.saturating_sub(x);
|
||||||
|
let rem_width = surface.area.width.saturating_sub(used_width);
|
||||||
|
x = surface
|
||||||
|
.set_stringn(
|
||||||
|
x,
|
||||||
|
viewport.y,
|
||||||
|
icons.ui().bufferline().separator(),
|
||||||
|
rem_width as usize,
|
||||||
|
bufferline_inactive,
|
||||||
|
)
|
||||||
|
.0;
|
||||||
|
}
|
||||||
|
|
||||||
if let Some(icon) = icons
|
if let Some(icon) = icons
|
||||||
.fs()
|
.fs()
|
||||||
|
|
|
@ -32,7 +32,6 @@ pub use text::Text;
|
||||||
|
|
||||||
use helix_view::Editor;
|
use helix_view::Editor;
|
||||||
use tui::text::{Span, Spans, ToSpan};
|
use tui::text::{Span, Spans, ToSpan};
|
||||||
use tui::widgets::Cell;
|
|
||||||
|
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use std::{error::Error, path::PathBuf};
|
use std::{error::Error, path::PathBuf};
|
||||||
|
@ -334,7 +333,7 @@ pub fn file_explorer(root: PathBuf, editor: &Editor) -> Result<FileExplorer, std
|
||||||
spans.push(icon.to_span_with(|icon| format!("{icon} ")));
|
spans.push(icon.to_span_with(|icon| format!("{icon} ")));
|
||||||
spans.push(Span::raw(name));
|
spans.push(Span::raw(name));
|
||||||
|
|
||||||
Cell::from(Spans::from(spans))
|
Spans::from(spans).into()
|
||||||
} else {
|
} else {
|
||||||
name.into()
|
name.into()
|
||||||
}
|
}
|
||||||
|
|
|
@ -236,7 +236,6 @@ where
|
||||||
});
|
});
|
||||||
|
|
||||||
let icons = ICONS.load();
|
let icons = ICONS.load();
|
||||||
|
|
||||||
for sev in &context.editor.config().statusline.diagnostics {
|
for sev in &context.editor.config().statusline.diagnostics {
|
||||||
match sev {
|
match sev {
|
||||||
Severity::Hint if hints > 0 => {
|
Severity::Hint if hints > 0 => {
|
||||||
|
@ -487,10 +486,10 @@ fn render_file_type<'a, F>(context: &mut RenderContext<'a>, write: F)
|
||||||
where
|
where
|
||||||
F: Fn(&mut RenderContext<'a>, Span<'a>) + Copy,
|
F: Fn(&mut RenderContext<'a>, Span<'a>) + Copy,
|
||||||
{
|
{
|
||||||
let icons = ICONS.load();
|
|
||||||
|
|
||||||
let lang = context.doc.language_name().unwrap_or(DEFAULT_LANGUAGE_NAME);
|
let lang = context.doc.language_name().unwrap_or(DEFAULT_LANGUAGE_NAME);
|
||||||
|
|
||||||
|
let icons = ICONS.load();
|
||||||
|
|
||||||
if let Some(icon) = icons
|
if let Some(icon) = icons
|
||||||
.fs()
|
.fs()
|
||||||
.from_optional_path_or_lang(context.doc.path().map(|path| path.as_path()), lang)
|
.from_optional_path_or_lang(context.doc.path().map(|path| path.as_path()), lang)
|
||||||
|
@ -578,13 +577,10 @@ fn render_separator<'a, F>(context: &mut RenderContext<'a>, write: F)
|
||||||
where
|
where
|
||||||
F: Fn(&mut RenderContext<'a>, Span<'a>) + Copy,
|
F: Fn(&mut RenderContext<'a>, Span<'a>) + Copy,
|
||||||
{
|
{
|
||||||
|
let sep = &context.editor.config().statusline.separator;
|
||||||
let style = context.editor.theme.get("ui.statusline.separator");
|
let style = context.editor.theme.get("ui.statusline.separator");
|
||||||
|
|
||||||
let icons = ICONS.load();
|
write(context, Span::styled(sep.to_string(), style));
|
||||||
|
|
||||||
let separator = icons.ui().statusline().separator().to_string();
|
|
||||||
|
|
||||||
write(context, Span::styled(separator, style));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn render_spacer<'a, F>(context: &mut RenderContext<'a>, write: F)
|
fn render_spacer<'a, F>(context: &mut RenderContext<'a>, write: F)
|
||||||
|
|
|
@ -43,7 +43,6 @@ use helix_core::{
|
||||||
ChangeSet, Diagnostic, LineEnding, Range, Rope, RopeBuilder, Selection, Syntax, Transaction,
|
ChangeSet, Diagnostic, LineEnding, Range, Rope, RopeBuilder, Selection, Syntax, Transaction,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::icons::{Icons, ICONS};
|
|
||||||
use crate::{
|
use crate::{
|
||||||
editor::Config,
|
editor::Config,
|
||||||
events::{DocumentDidChange, SelectionDidChange},
|
events::{DocumentDidChange, SelectionDidChange},
|
||||||
|
@ -2244,10 +2243,8 @@ impl Document {
|
||||||
.unwrap_or(40);
|
.unwrap_or(40);
|
||||||
let wrap_indicator = language_soft_wrap
|
let wrap_indicator = language_soft_wrap
|
||||||
.and_then(|soft_wrap| soft_wrap.wrap_indicator.clone())
|
.and_then(|soft_wrap| soft_wrap.wrap_indicator.clone())
|
||||||
.unwrap_or_else(|| {
|
.or_else(|| config.soft_wrap.wrap_indicator.clone())
|
||||||
let icons: arc_swap::access::DynGuard<Icons> = ICONS.load();
|
.unwrap_or_else(|| "↪ ".into());
|
||||||
icons.ui().r#virtual().wrap().to_string()
|
|
||||||
});
|
|
||||||
let tab_width = self.tab_width() as u16;
|
let tab_width = self.tab_width() as u16;
|
||||||
TextFormat {
|
TextFormat {
|
||||||
soft_wrap: enable_soft_wrap && viewport_width > 10,
|
soft_wrap: enable_soft_wrap && viewport_width > 10,
|
||||||
|
|
|
@ -508,6 +508,7 @@ pub struct StatusLineConfig {
|
||||||
pub left: Vec<StatusLineElement>,
|
pub left: Vec<StatusLineElement>,
|
||||||
pub center: Vec<StatusLineElement>,
|
pub center: Vec<StatusLineElement>,
|
||||||
pub right: Vec<StatusLineElement>,
|
pub right: Vec<StatusLineElement>,
|
||||||
|
pub separator: String,
|
||||||
pub mode: ModeConfig,
|
pub mode: ModeConfig,
|
||||||
pub diagnostics: Vec<Severity>,
|
pub diagnostics: Vec<Severity>,
|
||||||
pub workspace_diagnostics: Vec<Severity>,
|
pub workspace_diagnostics: Vec<Severity>,
|
||||||
|
@ -533,6 +534,7 @@ impl Default for StatusLineConfig {
|
||||||
E::Position,
|
E::Position,
|
||||||
E::FileEncoding,
|
E::FileEncoding,
|
||||||
],
|
],
|
||||||
|
separator: String::from("│"),
|
||||||
mode: ModeConfig::default(),
|
mode: ModeConfig::default(),
|
||||||
diagnostics: vec![Severity::Warning, Severity::Error],
|
diagnostics: vec![Severity::Warning, Severity::Error],
|
||||||
workspace_diagnostics: vec![Severity::Warning, Severity::Error],
|
workspace_diagnostics: vec![Severity::Warning, Severity::Error],
|
||||||
|
@ -751,12 +753,14 @@ impl std::str::FromStr for GutterType {
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub struct WhitespaceConfig {
|
pub struct WhitespaceConfig {
|
||||||
pub render: WhitespaceRender,
|
pub render: WhitespaceRender,
|
||||||
|
pub characters: WhitespaceCharacters,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for WhitespaceConfig {
|
impl Default for WhitespaceConfig {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self {
|
Self {
|
||||||
render: WhitespaceRender::Basic(WhitespaceRenderValue::None),
|
render: WhitespaceRender::Basic(WhitespaceRenderValue::None),
|
||||||
|
characters: WhitespaceCharacters::default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -882,6 +886,30 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||||
|
#[serde(default)]
|
||||||
|
pub struct WhitespaceCharacters {
|
||||||
|
pub space: char,
|
||||||
|
pub nbsp: char,
|
||||||
|
pub nnbsp: char,
|
||||||
|
pub tab: char,
|
||||||
|
pub tabpad: char,
|
||||||
|
pub newline: char,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for WhitespaceCharacters {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
space: '·', // U+00B7
|
||||||
|
nbsp: '⍽', // U+237D
|
||||||
|
nnbsp: '␣', // U+2423
|
||||||
|
tab: '→', // U+2192
|
||||||
|
newline: '⏎', // U+23CE
|
||||||
|
tabpad: ' ',
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||||
#[serde(default, rename_all = "kebab-case")]
|
#[serde(default, rename_all = "kebab-case")]
|
||||||
pub struct IndentGuidesConfig {
|
pub struct IndentGuidesConfig {
|
||||||
|
|
|
@ -127,18 +127,17 @@ pub fn diff<'doc>(
|
||||||
let icons = ICONS.load();
|
let icons = ICONS.load();
|
||||||
|
|
||||||
let (icon, style) = if hunk.is_pure_insertion() {
|
let (icon, style) = if hunk.is_pure_insertion() {
|
||||||
(icons.ui().gutter().added(), added)
|
(icons.gutter().added(), added)
|
||||||
} else if hunk.is_pure_removal() {
|
} else if hunk.is_pure_removal() {
|
||||||
if !first_visual_line {
|
if !first_visual_line {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
(icons.ui().gutter().removed(), deleted)
|
(icons.gutter().removed(), deleted)
|
||||||
} else {
|
} else {
|
||||||
(icons.ui().gutter().modified(), modified)
|
(icons.gutter().modified(), modified)
|
||||||
};
|
};
|
||||||
|
|
||||||
write!(out, "{icon}").unwrap();
|
write!(out, "{}", icon).unwrap();
|
||||||
|
|
||||||
Some(style)
|
Some(style)
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
|
@ -20,6 +20,7 @@ pub struct Icons {
|
||||||
diagnostic: Diagnostic,
|
diagnostic: Diagnostic,
|
||||||
vcs: Vcs,
|
vcs: Vcs,
|
||||||
dap: Dap,
|
dap: Dap,
|
||||||
|
gutter: Gutter,
|
||||||
ui: Ui,
|
ui: Ui,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -49,6 +50,11 @@ impl Icons {
|
||||||
&self.dap
|
&self.dap
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn gutter(&self) -> &Gutter {
|
||||||
|
&self.gutter
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn ui(&self) -> &Ui {
|
pub fn ui(&self) -> &Ui {
|
||||||
&self.ui
|
&self.ui
|
||||||
|
@ -107,46 +113,48 @@ impl Kind {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
match kind {
|
let icon = match kind {
|
||||||
"file" => self.file(),
|
"file" => self.file()?,
|
||||||
"folder" => self.folder(),
|
"folder" => self.folder()?,
|
||||||
"module" => self.module(),
|
"module" => self.module()?,
|
||||||
"namespace" => self.namespace(),
|
"namespace" => self.namespace()?,
|
||||||
"package" => self.package(),
|
"package" => self.package()?,
|
||||||
"class" => self.class(),
|
"class" => self.class()?,
|
||||||
"method" => self.method(),
|
"method" => self.method()?,
|
||||||
"property" => self.property(),
|
"property" => self.property()?,
|
||||||
"field" => self.field(),
|
"field" => self.field()?,
|
||||||
"construct" => self.constructor(),
|
"construct" => self.constructor()?,
|
||||||
"enum" => self.r#enum(),
|
"enum" => self.r#enum()?,
|
||||||
"interface" => self.interface(),
|
"interface" => self.interface()?,
|
||||||
"function" => self.function(),
|
"function" => self.function()?,
|
||||||
"variable" => self.variable(),
|
"variable" => self.variable()?,
|
||||||
"constant" => self.constant(),
|
"constant" => self.constant()?,
|
||||||
"string" => self.string(),
|
"string" => self.string()?,
|
||||||
"number" => self.number(),
|
"number" => self.number()?,
|
||||||
"boolean" => self.boolean(),
|
"boolean" => self.boolean()?,
|
||||||
"array" => self.array(),
|
"array" => self.array()?,
|
||||||
"object" => self.object(),
|
"object" => self.object()?,
|
||||||
"key" => self.key(),
|
"key" => self.key()?,
|
||||||
"null" => self.null(),
|
"null" => self.null()?,
|
||||||
"enum_member" => self.enum_member(),
|
"enum_member" => self.enum_member()?,
|
||||||
"struct" => self.r#struct(),
|
"struct" => self.r#struct()?,
|
||||||
"event" => self.event(),
|
"event" => self.event()?,
|
||||||
"operator" => self.operator(),
|
"operator" => self.operator()?,
|
||||||
"typeparam" => self.type_parameter(),
|
"typeparam" => self.type_parameter()?,
|
||||||
"color" => Some(self.color()),
|
"color" => self.color(),
|
||||||
"keyword" => self.keyword(),
|
"keyword" => self.keyword()?,
|
||||||
"value" => self.value(),
|
"value" => self.value()?,
|
||||||
"snippet" => self.snippet(),
|
"snippet" => self.snippet()?,
|
||||||
"reference" => self.reference(),
|
"reference" => self.reference()?,
|
||||||
"text" => self.text(),
|
"text" => self.text()?,
|
||||||
"unit" => self.unit(),
|
"unit" => self.unit()?,
|
||||||
"word" => self.word(),
|
"word" => self.word()?,
|
||||||
"spellcheck" => self.spellcheck(),
|
"spellcheck" => self.spellcheck()?,
|
||||||
|
|
||||||
_ => None,
|
_ => return None,
|
||||||
}
|
};
|
||||||
|
|
||||||
|
Some(icon)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -548,23 +556,21 @@ pub struct Fs {
|
||||||
mime: HashMap<String, Icon>,
|
mime: HashMap<String, Icon>,
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! iconmap {
|
macro_rules! mimes {
|
||||||
( $( $key:literal => { glyph: $glyph:expr $(, color: $color:expr)? } ),* $(,)? ) => {{
|
( $( $key:literal => { glyph: $glyph:expr $(, color: $color:expr)? } ),* $(,)? ) => {{
|
||||||
HashMap::from(
|
let mut map = HashMap::new();
|
||||||
[
|
$(
|
||||||
$(
|
map.insert(String::from($key), Icon {
|
||||||
(String::from($key), Icon {
|
glyph: String::from($glyph),
|
||||||
glyph: String::from($glyph),
|
color: None $(.or( Some(Color::from_hex($color).unwrap())) )?,
|
||||||
color: None $(.or( Some(Color::from_hex($color).unwrap())) )?,
|
});
|
||||||
}),
|
)*
|
||||||
)*
|
map
|
||||||
]
|
|
||||||
)
|
|
||||||
}};
|
}};
|
||||||
}
|
}
|
||||||
|
|
||||||
static MIMES: once_cell::sync::Lazy<HashMap<String, Icon>> = once_cell::sync::Lazy::new(|| {
|
static MIMES: once_cell::sync::Lazy<HashMap<String, Icon>> = once_cell::sync::Lazy::new(|| {
|
||||||
iconmap! {
|
mimes! {
|
||||||
// Language name
|
// Language name
|
||||||
"git-commit" => {glyph: "", color: "#f15233" },
|
"git-commit" => {glyph: "", color: "#f15233" },
|
||||||
"git-rebase" => {glyph: "", color: "#f15233" },
|
"git-rebase" => {glyph: "", color: "#f15233" },
|
||||||
|
@ -689,11 +695,13 @@ impl Fs {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
if is_open {
|
let dir = if is_open {
|
||||||
self.directory_open.as_deref().or(Some(""))
|
self.directory_open.as_deref().unwrap_or("")
|
||||||
} else {
|
} else {
|
||||||
self.directory.as_deref().or(Some(""))
|
self.directory.as_deref().unwrap_or("")
|
||||||
}
|
};
|
||||||
|
|
||||||
|
Some(dir)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -800,41 +808,6 @@ impl Dap {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Deserialize, PartialEq, Eq, Clone, Default)]
|
|
||||||
#[serde(default, deny_unknown_fields)]
|
|
||||||
pub struct Ui {
|
|
||||||
workspace: Option<Icon>,
|
|
||||||
gutter: Gutter,
|
|
||||||
#[serde(rename = "virtual")]
|
|
||||||
r#virtual: Virtual,
|
|
||||||
statusline: Statusline,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Ui {
|
|
||||||
/// Returns a workspace diagnostic icon.
|
|
||||||
///
|
|
||||||
/// If no icon is set in the config, it will return `W` by default.
|
|
||||||
#[inline]
|
|
||||||
pub fn workspace(&self) -> Icon {
|
|
||||||
self.workspace.clone().unwrap_or_else(|| Icon::from("W"))
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub fn gutter(&self) -> &Gutter {
|
|
||||||
&self.gutter
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub fn r#virtual(&self) -> &Virtual {
|
|
||||||
&self.r#virtual
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub fn statusline(&self) -> &Statusline {
|
|
||||||
&self.statusline
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize, PartialEq, Eq, Clone, Default)]
|
#[derive(Debug, Serialize, Deserialize, PartialEq, Eq, Clone, Default)]
|
||||||
pub struct Gutter {
|
pub struct Gutter {
|
||||||
added: Option<String>,
|
added: Option<String>,
|
||||||
|
@ -859,100 +832,46 @@ impl Gutter {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize, PartialEq, Eq, Clone, Default)]
|
|
||||||
pub struct Virtual {
|
|
||||||
// Whitespace
|
|
||||||
space: Option<String>,
|
|
||||||
nbsp: Option<String>,
|
|
||||||
nnbsp: Option<String>,
|
|
||||||
tab: Option<String>,
|
|
||||||
newline: Option<String>,
|
|
||||||
tabpad: Option<String>,
|
|
||||||
|
|
||||||
// Soft-wrap
|
|
||||||
wrap: Option<String>,
|
|
||||||
|
|
||||||
// Indentation guide
|
|
||||||
indentation: Option<String>,
|
|
||||||
|
|
||||||
// Ruler
|
|
||||||
ruler: Option<String>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Virtual {
|
|
||||||
#[inline]
|
|
||||||
pub fn space(&self) -> &str {
|
|
||||||
// Default: U+00B7
|
|
||||||
self.space.as_deref().unwrap_or("·")
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub fn nbsp(&self) -> &str {
|
|
||||||
// Default: U+237D
|
|
||||||
self.nbsp.as_deref().unwrap_or("⍽")
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub fn nnbsp(&self) -> &str {
|
|
||||||
// Default: U+2423
|
|
||||||
self.nnbsp.as_deref().unwrap_or("␣")
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub fn tab(&self) -> &str {
|
|
||||||
// Default: U+2192
|
|
||||||
self.tab.as_deref().unwrap_or("→")
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub fn newline(&self) -> &str {
|
|
||||||
// Default: U+23CE
|
|
||||||
self.newline.as_deref().unwrap_or("⏎")
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub fn tabpad(&self) -> &str {
|
|
||||||
// Default: U+23CE
|
|
||||||
self.tabpad.as_deref().unwrap_or(" ")
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub fn wrap(&self) -> &str {
|
|
||||||
// Default: U+21AA
|
|
||||||
self.wrap.as_deref().unwrap_or("↪")
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub fn indentation(&self) -> &str {
|
|
||||||
// Default: U+254E
|
|
||||||
self.indentation.as_deref().unwrap_or("╎")
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub fn ruler(&self) -> &str {
|
|
||||||
// TODO: Default: U+00A6: ¦
|
|
||||||
self.ruler.as_deref().unwrap_or(" ")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Deserialize, PartialEq, Eq, Clone, Default)]
|
|
||||||
pub struct Statusline {
|
|
||||||
separator: Option<String>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Statusline {
|
|
||||||
#[inline]
|
|
||||||
pub fn separator(&self) -> &str {
|
|
||||||
self.separator.as_deref().unwrap_or("│")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Default, PartialEq, Eq, Clone)]
|
#[derive(Debug, Default, PartialEq, Eq, Clone)]
|
||||||
pub struct Icon {
|
pub struct Icon {
|
||||||
glyph: String,
|
glyph: String,
|
||||||
color: Option<Color>,
|
color: Option<Color>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize, PartialEq, Eq, Clone, Default)]
|
||||||
|
#[serde(default, deny_unknown_fields)]
|
||||||
|
pub struct Ui {
|
||||||
|
workspace: Option<Icon>,
|
||||||
|
bufferline: BufferLine,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Ui {
|
||||||
|
/// Returns a workspace diagnostic icon.
|
||||||
|
///
|
||||||
|
/// If no icon is set in the config, it will return `W` by default.
|
||||||
|
#[inline]
|
||||||
|
pub fn workspace(&self) -> Icon {
|
||||||
|
self.workspace.clone().unwrap_or_else(|| Icon::from("W"))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn bufferline(&self) -> &BufferLine {
|
||||||
|
&self.bufferline
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize, PartialEq, Eq, Clone, Default)]
|
||||||
|
pub struct BufferLine {
|
||||||
|
separator: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl BufferLine {
|
||||||
|
#[inline]
|
||||||
|
pub fn separator(&self) -> &str {
|
||||||
|
self.separator.as_deref().unwrap_or("│")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Icon {
|
impl Icon {
|
||||||
pub fn glyph(&self) -> &str {
|
pub fn glyph(&self) -> &str {
|
||||||
self.glyph.as_str()
|
self.glyph.as_str()
|
||||||
|
|
Loading…
Reference in New Issue