mirror of
https://github.com/helix-editor/helix.git
synced 2025-04-04 19:37:54 +03:00
Merge a51334f00b
into 7ebf650029
This commit is contained in:
commit
5214d74fdf
5 changed files with 133 additions and 3 deletions
|
@ -61,6 +61,7 @@
|
|||
| `end-of-line-diagnostics` | Minimum severity of diagnostics to render at the end of the line. Set to `disable` to disable entirely. Refer to the setting about `inline-diagnostics` for more details | "disable"
|
||||
| `clipboard-provider` | Which API to use for clipboard interaction. One of `pasteboard` (MacOS), `wayland`, `x-clip`, `x-sel`, `win-32-yank`, `termux`, `tmux`, `windows`, `termcode`, `none`, or a custom command set. | Platform and environment specific. |
|
||||
| `editor-config` | Whether to read settings from [EditorConfig](https://editorconfig.org) files | `true` |
|
||||
| `welcome-screen` | Whether to enable the welcome screen | `true` |
|
||||
|
||||
### `[editor.clipboard-provider]` Section
|
||||
|
||||
|
|
|
@ -215,11 +215,11 @@ impl Application {
|
|||
editor.new_file(Action::VerticalSplit);
|
||||
}
|
||||
} else if stdin().is_tty() || cfg!(feature = "integration") {
|
||||
editor.new_file(Action::VerticalSplit);
|
||||
editor.new_file_welcome(Action::VerticalSplit);
|
||||
} else {
|
||||
editor
|
||||
.new_file_from_stdin(Action::VerticalSplit)
|
||||
.unwrap_or_else(|_| editor.new_file(Action::VerticalSplit));
|
||||
.unwrap_or_else(|_| editor.new_file_welcome(Action::VerticalSplit));
|
||||
}
|
||||
|
||||
#[cfg(windows)]
|
||||
|
|
|
@ -22,6 +22,7 @@ use helix_core::{
|
|||
unicode::width::UnicodeWidthStr,
|
||||
visual_offset_from_block, Change, Position, Range, Selection, Transaction,
|
||||
};
|
||||
use helix_loader::VERSION_AND_GIT_HASH;
|
||||
use helix_view::{
|
||||
annotations::diagnostics::DiagnosticFilter,
|
||||
document::{Mode, SCRATCH_BUFFER_NAME},
|
||||
|
@ -33,7 +34,10 @@ use helix_view::{
|
|||
};
|
||||
use std::{mem::take, num::NonZeroUsize, path::PathBuf, rc::Rc};
|
||||
|
||||
use tui::{buffer::Buffer as Surface, text::Span};
|
||||
use tui::{
|
||||
buffer::Buffer as Surface,
|
||||
text::{Span, Spans},
|
||||
};
|
||||
|
||||
pub struct EditorView {
|
||||
pub keymaps: Keymaps,
|
||||
|
@ -74,6 +78,107 @@ impl EditorView {
|
|||
&mut self.spinners
|
||||
}
|
||||
|
||||
pub fn render_welcome(theme: &Theme, view: &View, surface: &mut Surface) {
|
||||
#[derive(PartialEq, PartialOrd, Eq, Ord)]
|
||||
enum Align {
|
||||
Left,
|
||||
Center,
|
||||
}
|
||||
|
||||
macro_rules! welcome {
|
||||
(
|
||||
$([$align:ident] $line:expr, $(if $cond:expr;)?)* $(,)?
|
||||
) => {{
|
||||
let mut lines = vec![];
|
||||
let mut longest_left = 0;
|
||||
let mut longest_center = 0;
|
||||
$(
|
||||
let line = Spans::from($line);
|
||||
let width = line.width();
|
||||
lines.push((line, Align::$align));
|
||||
match Align::$align {
|
||||
Align::Left => longest_left = longest_left.max(width),
|
||||
Align::Center => longest_center = longest_center.max(width),
|
||||
}
|
||||
)*
|
||||
(lines, longest_left, longest_center)
|
||||
}};
|
||||
}
|
||||
|
||||
let (lines, longest_left, longest_center) = welcome! {
|
||||
[Center] vec!["helix ".into(), Span::styled(VERSION_AND_GIT_HASH, theme.get("comment"))],
|
||||
[Left] "",
|
||||
[Center] Span::styled(
|
||||
"A post-modern modal text editor",
|
||||
theme.get("ui.text").add_modifier(Modifier::ITALIC),
|
||||
),
|
||||
[Left] "",
|
||||
[Left] vec![
|
||||
Span::styled(":tutor", theme.get("markup.raw")),
|
||||
Span::styled("<enter>", theme.get("comment")),
|
||||
" learn helix".into(),
|
||||
],
|
||||
[Left] vec![
|
||||
Span::styled(":theme", theme.get("markup.raw")),
|
||||
Span::styled("<tab>", theme.get("comment")),
|
||||
" choose a theme".into(),
|
||||
],
|
||||
[Left] vec![
|
||||
Span::styled("<space>e", theme.get("markup.raw")),
|
||||
" file explorer".into(),
|
||||
],
|
||||
[Left] vec![
|
||||
Span::styled("<space>?", theme.get("markup.raw")),
|
||||
" see all commands".into(),
|
||||
],
|
||||
[Left] vec![
|
||||
Span::styled(":config-open", theme.get("markup.raw")),
|
||||
Span::styled("<enter>", theme.get("comment")),
|
||||
" configure helix".into(),
|
||||
],
|
||||
[Left] vec![
|
||||
Span::styled(":quit", theme.get("markup.raw")),
|
||||
Span::styled("<enter>", theme.get("comment")),
|
||||
" quit helix".into(),
|
||||
],
|
||||
[Left] "",
|
||||
[Center] vec![
|
||||
Span::styled("docs: ", theme.get("ui.text")),
|
||||
Span::styled("docs.helix-editor.com", theme.get("markup.link.url")),
|
||||
],
|
||||
};
|
||||
|
||||
// how many total lines there are in the welcome screen
|
||||
let lines_count = lines.len();
|
||||
|
||||
// the y-coordinate where we start drawing the welcome screen
|
||||
let y_start = view.area.y + (view.area.height / 2).saturating_sub(lines_count as u16 / 2);
|
||||
let y_center = view.area.x + view.area.width / 2;
|
||||
|
||||
let x_start_left =
|
||||
view.area.x + (view.area.width / 2).saturating_sub(longest_left as u16 / 2) + 2;
|
||||
|
||||
let has_x_left_overflow = (x_start_left + longest_left as u16) > view.area.width;
|
||||
let has_x_center_overflow = longest_center as u16 > view.area.width;
|
||||
let has_x_overflow = has_x_left_overflow || has_x_center_overflow;
|
||||
|
||||
// we want lines_count < view.area.height so it does not get drawn
|
||||
// over the status line
|
||||
let has_y_overflow = lines_count as u16 >= view.area.height;
|
||||
|
||||
if has_x_overflow || has_y_overflow {
|
||||
return;
|
||||
}
|
||||
|
||||
for (lines_drawn, (line, align)) in lines.iter().enumerate() {
|
||||
let x = match align {
|
||||
Align::Left => x_start_left,
|
||||
Align::Center => y_center - line.width() as u16 / 2,
|
||||
};
|
||||
surface.set_spans(x, y_start + lines_drawn as u16, line, line.width() as u16);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn render_view(
|
||||
&self,
|
||||
editor: &Editor,
|
||||
|
@ -178,6 +283,10 @@ impl EditorView {
|
|||
|
||||
Self::render_rulers(editor, doc, view, inner, surface, theme);
|
||||
|
||||
if config.welcome_screen && doc.version() == 0 && doc.is_welcome {
|
||||
Self::render_welcome(theme, view, surface);
|
||||
}
|
||||
|
||||
let primary_cursor = doc
|
||||
.selection(view.id)
|
||||
.primary()
|
||||
|
|
|
@ -207,6 +207,9 @@ pub struct Document {
|
|||
// NOTE: ideally this would live on the handler for color swatches. This is blocked on a
|
||||
// large refactor that would make `&mut Editor` available on the `DocumentDidChange` event.
|
||||
pub color_swatch_controller: TaskController,
|
||||
|
||||
/// Whether to render the welcome screen when opening the document
|
||||
pub is_welcome: bool,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Default)]
|
||||
|
@ -719,6 +722,7 @@ impl Document {
|
|||
jump_labels: HashMap::new(),
|
||||
color_swatches: None,
|
||||
color_swatch_controller: TaskController::new(),
|
||||
is_welcome: false,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -728,6 +732,11 @@ impl Document {
|
|||
Self::from(text, None, config)
|
||||
}
|
||||
|
||||
pub fn with_welcome(mut self) -> Self {
|
||||
self.is_welcome = true;
|
||||
self
|
||||
}
|
||||
|
||||
// TODO: async fn?
|
||||
/// Create a new document from `path`. Encoding is auto-detected, but it can be manually
|
||||
/// overwritten with the `encoding` parameter.
|
||||
|
|
|
@ -247,6 +247,8 @@ where
|
|||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "kebab-case", default, deny_unknown_fields)]
|
||||
pub struct Config {
|
||||
/// Whether to enable the welcome screen
|
||||
pub welcome_screen: bool,
|
||||
/// Padding to keep between the edge of the screen and the cursor when scrolling. Defaults to 5.
|
||||
pub scrolloff: usize,
|
||||
/// Number of lines to scroll at once. Defaults to 3
|
||||
|
@ -960,6 +962,7 @@ pub enum PopupBorderConfig {
|
|||
impl Default for Config {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
welcome_screen: true,
|
||||
scrolloff: 5,
|
||||
scroll_lines: 3,
|
||||
mouse: true,
|
||||
|
@ -1736,6 +1739,14 @@ impl Editor {
|
|||
self.new_file_from_document(action, Document::default(self.config.clone()))
|
||||
}
|
||||
|
||||
/// Use when Helix is opened with no arguments passed
|
||||
pub fn new_file_welcome(&mut self, action: Action) -> DocumentId {
|
||||
self.new_file_from_document(
|
||||
action,
|
||||
Document::default(self.config.clone()).with_welcome(),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn new_file_from_stdin(&mut self, action: Action) -> Result<DocumentId, Error> {
|
||||
let (stdin, encoding, has_bom) = crate::document::read_to_string(&mut stdin(), None)?;
|
||||
let doc = Document::from(
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue