mirror of https://github.com/helix-editor/helix
Merge f252e179a2
into 1315b7e2b1
commit
43853e96a6
|
@ -1,3 +1,4 @@
|
||||||
|
//! Functions for working with the host environment.
|
||||||
use std::{
|
use std::{
|
||||||
borrow::Cow,
|
borrow::Cow,
|
||||||
ffi::{OsStr, OsString},
|
ffi::{OsStr, OsString},
|
||||||
|
@ -10,9 +11,9 @@ use once_cell::sync::Lazy;
|
||||||
// We keep the CWD as a static so that we can access it in places where we don't have access to the Editor
|
// We keep the CWD as a static so that we can access it in places where we don't have access to the Editor
|
||||||
static CWD: RwLock<Option<PathBuf>> = RwLock::new(None);
|
static CWD: RwLock<Option<PathBuf>> = RwLock::new(None);
|
||||||
|
|
||||||
// Get the current working directory.
|
/// Get the current working directory.
|
||||||
// This information is managed internally as the call to std::env::current_dir
|
/// This information is managed internally as the call to std::env::current_dir
|
||||||
// might fail if the cwd has been deleted.
|
/// might fail if the cwd has been deleted.
|
||||||
pub fn current_working_dir() -> PathBuf {
|
pub fn current_working_dir() -> PathBuf {
|
||||||
if let Some(path) = &*CWD.read().unwrap() {
|
if let Some(path) = &*CWD.read().unwrap() {
|
||||||
return path.clone();
|
return path.clone();
|
||||||
|
@ -37,6 +38,7 @@ pub fn current_working_dir() -> PathBuf {
|
||||||
cwd
|
cwd
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Update the current working directory.
|
||||||
pub fn set_current_working_dir(path: impl AsRef<Path>) -> std::io::Result<Option<PathBuf>> {
|
pub fn set_current_working_dir(path: impl AsRef<Path>) -> std::io::Result<Option<PathBuf>> {
|
||||||
let path = crate::path::canonicalize(path);
|
let path = crate::path::canonicalize(path);
|
||||||
std::env::set_current_dir(&path)?;
|
std::env::set_current_dir(&path)?;
|
||||||
|
@ -45,14 +47,17 @@ pub fn set_current_working_dir(path: impl AsRef<Path>) -> std::io::Result<Option
|
||||||
Ok(cwd.replace(path))
|
Ok(cwd.replace(path))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Checks if the given environment variable is set.
|
||||||
pub fn env_var_is_set(env_var_name: &str) -> bool {
|
pub fn env_var_is_set(env_var_name: &str) -> bool {
|
||||||
std::env::var_os(env_var_name).is_some()
|
std::env::var_os(env_var_name).is_some()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Checks if a binary with the given name exists.
|
||||||
pub fn binary_exists<T: AsRef<OsStr>>(binary_name: T) -> bool {
|
pub fn binary_exists<T: AsRef<OsStr>>(binary_name: T) -> bool {
|
||||||
which::which(binary_name).is_ok()
|
which::which(binary_name).is_ok()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Attempts to find a binary of the given name. See [which](https://linux.die.net/man/1/which).
|
||||||
pub fn which<T: AsRef<OsStr>>(
|
pub fn which<T: AsRef<OsStr>>(
|
||||||
binary_name: T,
|
binary_name: T,
|
||||||
) -> Result<std::path::PathBuf, ExecutableNotFoundError> {
|
) -> Result<std::path::PathBuf, ExecutableNotFoundError> {
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
//! Functions for managine file metadata.
|
||||||
//! From <https://github.com/Freaky/faccess>
|
//! From <https://github.com/Freaky/faccess>
|
||||||
|
|
||||||
use std::io;
|
use std::io;
|
||||||
|
|
|
@ -1,3 +1,6 @@
|
||||||
|
//! Extensions to the standard library. A collection of helper functions
|
||||||
|
//! used throughout helix.
|
||||||
|
|
||||||
pub mod env;
|
pub mod env;
|
||||||
pub mod faccess;
|
pub mod faccess;
|
||||||
pub mod path;
|
pub mod path;
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
//! Functions for working with [Path].
|
||||||
|
|
||||||
pub use etcetera::home_dir;
|
pub use etcetera::home_dir;
|
||||||
use once_cell::sync::Lazy;
|
use once_cell::sync::Lazy;
|
||||||
use regex_cursor::{engines::meta::Regex, Input};
|
use regex_cursor::{engines::meta::Regex, Input};
|
||||||
|
@ -140,6 +142,7 @@ pub fn canonicalize(path: impl AsRef<Path>) -> PathBuf {
|
||||||
normalize(path)
|
normalize(path)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Convert path into a relative path
|
||||||
pub fn get_relative_path<'a, P>(path: P) -> Cow<'a, Path>
|
pub fn get_relative_path<'a, P>(path: P) -> Cow<'a, Path>
|
||||||
where
|
where
|
||||||
P: Into<Cow<'a, Path>>,
|
P: Into<Cow<'a, Path>>,
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
//! Provides [Range] type expanding on [RangeBounds].
|
||||||
|
|
||||||
use std::ops::{self, RangeBounds};
|
use std::ops::{self, RangeBounds};
|
||||||
|
|
||||||
/// A range of `char`s within the text.
|
/// A range of `char`s within the text.
|
||||||
|
@ -66,6 +68,7 @@ pub fn is_subset<const ALLOW_EMPTY: bool>(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Similar to is_subset but requires each element of `super_set` to be matched
|
||||||
pub fn is_exact_subset(
|
pub fn is_exact_subset(
|
||||||
mut super_set: impl Iterator<Item = Range>,
|
mut super_set: impl Iterator<Item = Range>,
|
||||||
mut sub_set: impl Iterator<Item = Range>,
|
mut sub_set: impl Iterator<Item = Range>,
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
//! Functions and types for working with [RopeSlice]
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::ops::{Bound, RangeBounds};
|
use std::ops::{Bound, RangeBounds};
|
||||||
|
|
||||||
|
@ -8,6 +9,7 @@ use ropey::iter::Chunks;
|
||||||
use ropey::RopeSlice;
|
use ropey::RopeSlice;
|
||||||
use unicode_segmentation::{GraphemeCursor, GraphemeIncomplete};
|
use unicode_segmentation::{GraphemeCursor, GraphemeIncomplete};
|
||||||
|
|
||||||
|
/// Additional utility functions for [RopeSlice]
|
||||||
pub trait RopeSliceExt<'a>: Sized {
|
pub trait RopeSliceExt<'a>: Sized {
|
||||||
fn ends_with(self, text: &str) -> bool;
|
fn ends_with(self, text: &str) -> bool;
|
||||||
fn starts_with(self, text: &str) -> bool;
|
fn starts_with(self, text: &str) -> bool;
|
||||||
|
|
|
@ -95,6 +95,7 @@ impl Capabilities {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Terminal backend supporting a wide variety of terminals
|
||||||
pub struct CrosstermBackend<W: Write> {
|
pub struct CrosstermBackend<W: Write> {
|
||||||
buffer: W,
|
buffer: W,
|
||||||
capabilities: Capabilities,
|
capabilities: Capabilities,
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
//! Provides interface for controlling the terminal
|
||||||
|
|
||||||
use std::io;
|
use std::io;
|
||||||
|
|
||||||
use crate::{buffer::Cell, terminal::Config};
|
use crate::{buffer::Cell, terminal::Config};
|
||||||
|
@ -12,19 +14,32 @@ pub use self::crossterm::CrosstermBackend;
|
||||||
mod test;
|
mod test;
|
||||||
pub use self::test::TestBackend;
|
pub use self::test::TestBackend;
|
||||||
|
|
||||||
|
/// Representation of a terminal backend.
|
||||||
pub trait Backend {
|
pub trait Backend {
|
||||||
|
/// Claims the terminal for TUI use.
|
||||||
fn claim(&mut self, config: Config) -> Result<(), io::Error>;
|
fn claim(&mut self, config: Config) -> Result<(), io::Error>;
|
||||||
|
/// Update terminal configuration.
|
||||||
fn reconfigure(&mut self, config: Config) -> Result<(), io::Error>;
|
fn reconfigure(&mut self, config: Config) -> Result<(), io::Error>;
|
||||||
|
/// Restores the terminal to a normal state, undoes `claim`
|
||||||
fn restore(&mut self, config: Config) -> Result<(), io::Error>;
|
fn restore(&mut self, config: Config) -> Result<(), io::Error>;
|
||||||
|
/// Forcibly resets the terminal, ignoring errors and configuration
|
||||||
fn force_restore() -> Result<(), io::Error>;
|
fn force_restore() -> Result<(), io::Error>;
|
||||||
|
/// Draws styled text to the terminal
|
||||||
fn draw<'a, I>(&mut self, content: I) -> Result<(), io::Error>
|
fn draw<'a, I>(&mut self, content: I) -> Result<(), io::Error>
|
||||||
where
|
where
|
||||||
I: Iterator<Item = (u16, u16, &'a Cell)>;
|
I: Iterator<Item = (u16, u16, &'a Cell)>;
|
||||||
|
/// Hides the cursor
|
||||||
fn hide_cursor(&mut self) -> Result<(), io::Error>;
|
fn hide_cursor(&mut self) -> Result<(), io::Error>;
|
||||||
|
/// Sets the cursor to the given shape
|
||||||
fn show_cursor(&mut self, kind: CursorKind) -> Result<(), io::Error>;
|
fn show_cursor(&mut self, kind: CursorKind) -> Result<(), io::Error>;
|
||||||
|
/// Gets the current position of the cursor
|
||||||
fn get_cursor(&mut self) -> Result<(u16, u16), io::Error>;
|
fn get_cursor(&mut self) -> Result<(u16, u16), io::Error>;
|
||||||
|
/// Sets the cursor to the given position
|
||||||
fn set_cursor(&mut self, x: u16, y: u16) -> Result<(), io::Error>;
|
fn set_cursor(&mut self, x: u16, y: u16) -> Result<(), io::Error>;
|
||||||
|
/// Clears the terminal
|
||||||
fn clear(&mut self) -> Result<(), io::Error>;
|
fn clear(&mut self) -> Result<(), io::Error>;
|
||||||
|
/// Gets the size of the terminal in cells
|
||||||
fn size(&self) -> Result<Rect, io::Error>;
|
fn size(&self) -> Result<Rect, io::Error>;
|
||||||
|
/// Flushes the terminal buffer
|
||||||
fn flush(&mut self) -> Result<(), io::Error>;
|
fn flush(&mut self) -> Result<(), io::Error>;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
//! Contents of a terminal screen. A [Buffer] is made up of [Cell]s.
|
||||||
use crate::text::{Span, Spans};
|
use crate::text::{Span, Spans};
|
||||||
use helix_core::unicode::width::UnicodeWidthStr;
|
use helix_core::unicode::width::UnicodeWidthStr;
|
||||||
use std::cmp::min;
|
use std::cmp::min;
|
||||||
|
@ -5,7 +6,7 @@ use unicode_segmentation::UnicodeSegmentation;
|
||||||
|
|
||||||
use helix_view::graphics::{Color, Modifier, Rect, Style, UnderlineStyle};
|
use helix_view::graphics::{Color, Modifier, Rect, Style, UnderlineStyle};
|
||||||
|
|
||||||
/// A buffer cell
|
/// One cell of the terminal. Contains one stylized grapheme.
|
||||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
pub struct Cell {
|
pub struct Cell {
|
||||||
pub symbol: String,
|
pub symbol: String,
|
||||||
|
@ -17,28 +18,33 @@ pub struct Cell {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Cell {
|
impl Cell {
|
||||||
|
/// Set the cell's grapheme
|
||||||
pub fn set_symbol(&mut self, symbol: &str) -> &mut Cell {
|
pub fn set_symbol(&mut self, symbol: &str) -> &mut Cell {
|
||||||
self.symbol.clear();
|
self.symbol.clear();
|
||||||
self.symbol.push_str(symbol);
|
self.symbol.push_str(symbol);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Set the cell's grapheme to a [char]
|
||||||
pub fn set_char(&mut self, ch: char) -> &mut Cell {
|
pub fn set_char(&mut self, ch: char) -> &mut Cell {
|
||||||
self.symbol.clear();
|
self.symbol.clear();
|
||||||
self.symbol.push(ch);
|
self.symbol.push(ch);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Set the foreground [Color]
|
||||||
pub fn set_fg(&mut self, color: Color) -> &mut Cell {
|
pub fn set_fg(&mut self, color: Color) -> &mut Cell {
|
||||||
self.fg = color;
|
self.fg = color;
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Set the background [Color]
|
||||||
pub fn set_bg(&mut self, color: Color) -> &mut Cell {
|
pub fn set_bg(&mut self, color: Color) -> &mut Cell {
|
||||||
self.bg = color;
|
self.bg = color;
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Set the [Style] of the cell
|
||||||
pub fn set_style(&mut self, style: Style) -> &mut Cell {
|
pub fn set_style(&mut self, style: Style) -> &mut Cell {
|
||||||
if let Some(c) = style.fg {
|
if let Some(c) = style.fg {
|
||||||
self.fg = c;
|
self.fg = c;
|
||||||
|
@ -58,6 +64,7 @@ impl Cell {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns the current style of the cell
|
||||||
pub fn style(&self) -> Style {
|
pub fn style(&self) -> Style {
|
||||||
Style::default()
|
Style::default()
|
||||||
.fg(self.fg)
|
.fg(self.fg)
|
||||||
|
@ -67,6 +74,7 @@ impl Cell {
|
||||||
.add_modifier(self.modifier)
|
.add_modifier(self.modifier)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Resets the cell to a default blank state
|
||||||
pub fn reset(&mut self) {
|
pub fn reset(&mut self) {
|
||||||
self.symbol.clear();
|
self.symbol.clear();
|
||||||
self.symbol.push(' ');
|
self.symbol.push(' ');
|
||||||
|
@ -494,6 +502,8 @@ impl Buffer {
|
||||||
(x_offset as u16, y)
|
(x_offset as u16, y)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Print at most the first `width` characters of a [Spans] if enough space is available
|
||||||
|
/// until the end of the line. Appends a `…` at the end of truncated lines.
|
||||||
pub fn set_spans_truncated(&mut self, x: u16, y: u16, spans: &Spans, width: u16) -> (u16, u16) {
|
pub fn set_spans_truncated(&mut self, x: u16, y: u16, spans: &Spans, width: u16) -> (u16, u16) {
|
||||||
// prevent panic if out of range
|
// prevent panic if out of range
|
||||||
if !self.in_bounds(x, y) || width == 0 {
|
if !self.in_bounds(x, y) || width == 0 {
|
||||||
|
@ -535,6 +545,8 @@ impl Buffer {
|
||||||
(x_offset as u16, y)
|
(x_offset as u16, y)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Print at most the first `width` characters of a [Spans] if enough space is available
|
||||||
|
/// until the end of the line
|
||||||
pub fn set_spans(&mut self, x: u16, y: u16, spans: &Spans, width: u16) -> (u16, u16) {
|
pub fn set_spans(&mut self, x: u16, y: u16, spans: &Spans, width: u16) -> (u16, u16) {
|
||||||
let mut remaining_width = width;
|
let mut remaining_width = width;
|
||||||
let mut x = x;
|
let mut x = x;
|
||||||
|
@ -556,6 +568,8 @@ impl Buffer {
|
||||||
(x, y)
|
(x, y)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Print at most the first `width` characters of a [Span] if enough space is available
|
||||||
|
/// until the end of the line
|
||||||
pub fn set_span(&mut self, x: u16, y: u16, span: &Span, width: u16) -> (u16, u16) {
|
pub fn set_span(&mut self, x: u16, y: u16, span: &Span, width: u16) -> (u16, u16) {
|
||||||
self.set_stringn(x, y, span.content.as_ref(), width as usize, span.style)
|
self.set_stringn(x, y, span.content.as_ref(), width as usize, span.style)
|
||||||
}
|
}
|
||||||
|
@ -572,6 +586,7 @@ impl Buffer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Set all cells in the [area](Rect) to the given [Style]
|
||||||
pub fn set_style(&mut self, area: Rect, style: Style) {
|
pub fn set_style(&mut self, area: Rect, style: Style) {
|
||||||
for y in area.top()..area.bottom() {
|
for y in area.top()..area.bottom() {
|
||||||
for x in area.left()..area.right() {
|
for x in area.left()..area.right() {
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
//! Layout engine for terminal
|
||||||
|
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
@ -7,6 +9,7 @@ use cassowary::{Constraint as CassowaryConstraint, Expression, Solver, Variable}
|
||||||
|
|
||||||
use helix_view::graphics::{Margin, Rect};
|
use helix_view::graphics::{Margin, Rect};
|
||||||
|
|
||||||
|
/// Enum of all corners
|
||||||
#[derive(Debug, Hash, Clone, Copy, PartialEq, Eq)]
|
#[derive(Debug, Hash, Clone, Copy, PartialEq, Eq)]
|
||||||
pub enum Corner {
|
pub enum Corner {
|
||||||
TopLeft,
|
TopLeft,
|
||||||
|
@ -15,12 +18,14 @@ pub enum Corner {
|
||||||
BottomLeft,
|
BottomLeft,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Direction a [Rect] should be split
|
||||||
#[derive(Debug, Hash, Clone, PartialEq, Eq)]
|
#[derive(Debug, Hash, Clone, PartialEq, Eq)]
|
||||||
pub enum Direction {
|
pub enum Direction {
|
||||||
Horizontal,
|
Horizontal,
|
||||||
Vertical,
|
Vertical,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Describes requirements of a [Rect] to be split
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||||
pub enum Constraint {
|
pub enum Constraint {
|
||||||
// TODO: enforce range 0 - 100
|
// TODO: enforce range 0 - 100
|
||||||
|
@ -46,6 +51,7 @@ impl Constraint {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// How content should be aligned
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
pub enum Alignment {
|
pub enum Alignment {
|
||||||
Left,
|
Left,
|
||||||
|
@ -53,6 +59,7 @@ pub enum Alignment {
|
||||||
Right,
|
Right,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Description of a how a [Rect] should be split
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||||
pub struct Layout {
|
pub struct Layout {
|
||||||
direction: Direction,
|
direction: Direction,
|
||||||
|
@ -75,6 +82,7 @@ impl Default for Layout {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Layout {
|
impl Layout {
|
||||||
|
/// Returns a layout with the given [Constraint]s.
|
||||||
pub fn constraints<C>(mut self, constraints: C) -> Layout
|
pub fn constraints<C>(mut self, constraints: C) -> Layout
|
||||||
where
|
where
|
||||||
C: Into<Vec<Constraint>>,
|
C: Into<Vec<Constraint>>,
|
||||||
|
@ -83,21 +91,25 @@ impl Layout {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns a layout wit the given margins on all sides.
|
||||||
pub const fn margin(mut self, margin: u16) -> Layout {
|
pub const fn margin(mut self, margin: u16) -> Layout {
|
||||||
self.margin = Margin::all(margin);
|
self.margin = Margin::all(margin);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns a layout with the given horizontal margins.
|
||||||
pub const fn horizontal_margin(mut self, horizontal: u16) -> Layout {
|
pub const fn horizontal_margin(mut self, horizontal: u16) -> Layout {
|
||||||
self.margin.horizontal = horizontal;
|
self.margin.horizontal = horizontal;
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns a layout with the given vertical margins.
|
||||||
pub const fn vertical_margin(mut self, vertical: u16) -> Layout {
|
pub const fn vertical_margin(mut self, vertical: u16) -> Layout {
|
||||||
self.margin.vertical = vertical;
|
self.margin.vertical = vertical;
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns a layout with the given [Direction].
|
||||||
pub const fn direction(mut self, direction: Direction) -> Layout {
|
pub const fn direction(mut self, direction: Direction) -> Layout {
|
||||||
self.direction = direction;
|
self.direction = direction;
|
||||||
self
|
self
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
//! Common TUI symbols including blocks, bars, braille, lines
|
||||||
|
|
||||||
pub mod block {
|
pub mod block {
|
||||||
pub const FULL: &str = "█";
|
pub const FULL: &str = "█";
|
||||||
pub const SEVEN_EIGHTHS: &str = "▉";
|
pub const SEVEN_EIGHTHS: &str = "▉";
|
||||||
|
|
|
@ -1,3 +1,6 @@
|
||||||
|
//! Terminal interface provided through the [Terminal] type.
|
||||||
|
//! Frontend for [Backend]
|
||||||
|
|
||||||
use crate::{backend::Backend, buffer::Buffer};
|
use crate::{backend::Backend, buffer::Buffer};
|
||||||
use helix_view::editor::Config as EditorConfig;
|
use helix_view::editor::Config as EditorConfig;
|
||||||
use helix_view::graphics::{CursorKind, Rect};
|
use helix_view::graphics::{CursorKind, Rect};
|
||||||
|
@ -17,6 +20,7 @@ pub struct Viewport {
|
||||||
resize_behavior: ResizeBehavior,
|
resize_behavior: ResizeBehavior,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Terminal configuration
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Config {
|
pub struct Config {
|
||||||
pub enable_mouse_capture: bool,
|
pub enable_mouse_capture: bool,
|
||||||
|
@ -47,7 +51,7 @@ pub struct TerminalOptions {
|
||||||
pub viewport: Viewport,
|
pub viewport: Viewport,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Interface to the terminal backed by Termion
|
/// Interface to the terminal backed by crossterm
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Terminal<B>
|
pub struct Terminal<B>
|
||||||
where
|
where
|
||||||
|
|
|
@ -331,6 +331,7 @@ impl<'a> Table<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Track [Table] scroll offset and selection
|
||||||
#[derive(Debug, Default, Clone)]
|
#[derive(Debug, Default, Clone)]
|
||||||
pub struct TableState {
|
pub struct TableState {
|
||||||
pub offset: usize,
|
pub offset: usize,
|
||||||
|
|
|
@ -9,8 +9,6 @@ categories.workspace = true
|
||||||
repository.workspace = true
|
repository.workspace = true
|
||||||
homepage.workspace = true
|
homepage.workspace = true
|
||||||
|
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
helix-core = { path = "../helix-core" }
|
helix-core = { path = "../helix-core" }
|
||||||
helix-event = { path = "../helix-event" }
|
helix-event = { path = "../helix-event" }
|
||||||
|
|
|
@ -34,6 +34,7 @@ struct DiffInner {
|
||||||
hunks: Vec<Hunk>,
|
hunks: Vec<Hunk>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Representation of a diff that can be updated.
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct DiffHandle {
|
pub struct DiffHandle {
|
||||||
channel: UnboundedSender<Event>,
|
channel: UnboundedSender<Event>,
|
||||||
|
@ -64,10 +65,12 @@ impl DiffHandle {
|
||||||
(differ, handle)
|
(differ, handle)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Switch base and modified texts' roles
|
||||||
pub fn invert(&mut self) {
|
pub fn invert(&mut self) {
|
||||||
self.inverted = !self.inverted;
|
self.inverted = !self.inverted;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Load the actual diff
|
||||||
pub fn load(&self) -> Diff {
|
pub fn load(&self) -> Diff {
|
||||||
Diff {
|
Diff {
|
||||||
diff: self.diff.read(),
|
diff: self.diff.read(),
|
||||||
|
@ -88,6 +91,7 @@ impl DiffHandle {
|
||||||
self.update_document_impl(doc, self.inverted, Some(RenderLock { lock, timeout }))
|
self.update_document_impl(doc, self.inverted, Some(RenderLock { lock, timeout }))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Updates the base text of the diff. Returns if the update was successful.
|
||||||
pub fn update_diff_base(&self, diff_base: Rope) -> bool {
|
pub fn update_diff_base(&self, diff_base: Rope) -> bool {
|
||||||
self.update_document_impl(diff_base, !self.inverted, None)
|
self.update_document_impl(diff_base, !self.inverted, None)
|
||||||
}
|
}
|
||||||
|
@ -143,7 +147,7 @@ impl Hunk {
|
||||||
after: u32::MAX..u32::MAX,
|
after: u32::MAX..u32::MAX,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Inverts a change so that `before`
|
/// Inverts a change so that `before` and `after` are swapped.
|
||||||
pub fn invert(&self) -> Hunk {
|
pub fn invert(&self) -> Hunk {
|
||||||
Hunk {
|
Hunk {
|
||||||
before: self.after.clone(),
|
before: self.after.clone(),
|
||||||
|
@ -151,10 +155,12 @@ impl Hunk {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Is this hunk only adding to the document
|
||||||
pub fn is_pure_insertion(&self) -> bool {
|
pub fn is_pure_insertion(&self) -> bool {
|
||||||
self.before.is_empty()
|
self.before.is_empty()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Is this hunk only removing from the document
|
||||||
pub fn is_pure_removal(&self) -> bool {
|
pub fn is_pure_removal(&self) -> bool {
|
||||||
self.after.is_empty()
|
self.after.is_empty()
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,7 @@
|
||||||
|
//! `helix_vcs` provides types for working with diffs from a Version Control System (VCS).
|
||||||
|
//! Currently `git` is the only supported provider for diffs, but this architecture allows
|
||||||
|
//! for other providers to be added in the future.
|
||||||
|
|
||||||
use anyhow::{anyhow, bail, Result};
|
use anyhow::{anyhow, bail, Result};
|
||||||
use arc_swap::ArcSwap;
|
use arc_swap::ArcSwap;
|
||||||
use std::{
|
use std::{
|
||||||
|
@ -16,12 +20,16 @@ mod status;
|
||||||
|
|
||||||
pub use status::FileChange;
|
pub use status::FileChange;
|
||||||
|
|
||||||
|
/// Contains all active diff providers. Diff providers are compiled in via features. Currently
|
||||||
|
/// only `git` is supported.
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct DiffProviderRegistry {
|
pub struct DiffProviderRegistry {
|
||||||
providers: Vec<DiffProvider>,
|
providers: Vec<DiffProvider>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DiffProviderRegistry {
|
impl DiffProviderRegistry {
|
||||||
|
/// Get the given file from the VCS. This provides the unedited document as a "base"
|
||||||
|
/// for a diff to be created.
|
||||||
pub fn get_diff_base(&self, file: &Path) -> Option<Vec<u8>> {
|
pub fn get_diff_base(&self, file: &Path) -> Option<Vec<u8>> {
|
||||||
self.providers
|
self.providers
|
||||||
.iter()
|
.iter()
|
||||||
|
@ -35,6 +43,7 @@ impl DiffProviderRegistry {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get the current name of the current [HEAD](https://stackoverflow.com/questions/2304087/what-is-head-in-git).
|
||||||
pub fn get_current_head_name(&self, file: &Path) -> Option<Arc<ArcSwap<Box<str>>>> {
|
pub fn get_current_head_name(&self, file: &Path) -> Option<Arc<ArcSwap<Box<str>>>> {
|
||||||
self.providers
|
self.providers
|
||||||
.iter()
|
.iter()
|
||||||
|
@ -75,6 +84,7 @@ impl Default for DiffProviderRegistry {
|
||||||
let providers = vec![
|
let providers = vec![
|
||||||
#[cfg(feature = "git")]
|
#[cfg(feature = "git")]
|
||||||
DiffProvider::Git,
|
DiffProvider::Git,
|
||||||
|
DiffProvider::None,
|
||||||
];
|
];
|
||||||
DiffProviderRegistry { providers }
|
DiffProviderRegistry { providers }
|
||||||
}
|
}
|
||||||
|
@ -85,7 +95,7 @@ impl Default for DiffProviderRegistry {
|
||||||
///
|
///
|
||||||
/// `Copy` is simply to ensure the `clone()` call is the simplest it can be.
|
/// `Copy` is simply to ensure the `clone()` call is the simplest it can be.
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone)]
|
||||||
pub enum DiffProvider {
|
enum DiffProvider {
|
||||||
#[cfg(feature = "git")]
|
#[cfg(feature = "git")]
|
||||||
Git,
|
Git,
|
||||||
None,
|
None,
|
||||||
|
|
|
@ -1,18 +1,16 @@
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
|
|
||||||
|
/// States for a file having been changed.
|
||||||
pub enum FileChange {
|
pub enum FileChange {
|
||||||
Untracked {
|
/// Not tracked by the VCS.
|
||||||
path: PathBuf,
|
Untracked { path: PathBuf },
|
||||||
},
|
/// File has been modified.
|
||||||
Modified {
|
Modified { path: PathBuf },
|
||||||
path: PathBuf,
|
/// File modification is in conflict with a different update.
|
||||||
},
|
Conflict { path: PathBuf },
|
||||||
Conflict {
|
/// File has been deleted.
|
||||||
path: PathBuf,
|
Deleted { path: PathBuf },
|
||||||
},
|
/// File has been renamed.
|
||||||
Deleted {
|
|
||||||
path: PathBuf,
|
|
||||||
},
|
|
||||||
Renamed {
|
Renamed {
|
||||||
from_path: PathBuf,
|
from_path: PathBuf,
|
||||||
to_path: PathBuf,
|
to_path: PathBuf,
|
||||||
|
|
Loading…
Reference in New Issue