зеркало из
https://github.com/glebtv/tui-textarea.git
synced 2026-09-07 16:05:50 +03:00
support hard tab indent by TextArea::set_hard_tab
Этот коммит содержится в:
@@ -18,11 +18,8 @@ use tui::Terminal;
|
|||||||
use tui_textarea::{Input, Key, TextArea};
|
use tui_textarea::{Input, Key, TextArea};
|
||||||
|
|
||||||
macro_rules! error {
|
macro_rules! error {
|
||||||
($fmt: expr, $($args:tt),+) => {{
|
($fmt: expr $(, $args:tt)*) => {{
|
||||||
Err(io::Error::new(io::ErrorKind::Other, format!($fmt, $($args),+)))
|
Err(io::Error::new(io::ErrorKind::Other, format!($fmt $(, $args)*)))
|
||||||
}};
|
|
||||||
($msg: expr) => {{
|
|
||||||
Err(io::Error::new(io::ErrorKind::Other, $msg))
|
|
||||||
}};
|
}};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -36,14 +33,17 @@ impl<'a> Buffer<'a> {
|
|||||||
fn new(path: PathBuf) -> io::Result<Self> {
|
fn new(path: PathBuf) -> io::Result<Self> {
|
||||||
let mut textarea = if let Ok(md) = path.metadata() {
|
let mut textarea = if let Ok(md) = path.metadata() {
|
||||||
if md.is_file() {
|
if md.is_file() {
|
||||||
io::BufReader::new(fs::File::open(&path)?)
|
let mut textarea: TextArea = io::BufReader::new(fs::File::open(&path)?)
|
||||||
.lines()
|
.lines()
|
||||||
.collect::<Result<_, _>>()?
|
.collect::<Result<_, _>>()?;
|
||||||
|
let hard_tab = textarea.lines().iter().any(|l| l.starts_with('\t'));
|
||||||
|
textarea.set_hard_tab(hard_tab);
|
||||||
|
textarea
|
||||||
} else {
|
} else {
|
||||||
return error!("{:?} is not a file", path);
|
return error!("{:?} is not a file", path);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
TextArea::default()
|
TextArea::default() // File does not exist
|
||||||
};
|
};
|
||||||
textarea.set_line_number_style(Style::default().fg(Color::DarkGray));
|
textarea.set_line_number_style(Style::default().fg(Color::DarkGray));
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
|
|||||||
@@ -41,6 +41,7 @@ pub struct TextArea<'a> {
|
|||||||
style: Style,
|
style: Style,
|
||||||
cursor: (usize, usize), // 0-base
|
cursor: (usize, usize), // 0-base
|
||||||
tab_len: u8,
|
tab_len: u8,
|
||||||
|
hard_tab: bool,
|
||||||
history: History,
|
history: History,
|
||||||
cursor_line_style: Style,
|
cursor_line_style: Style,
|
||||||
line_number_style: Option<Style>,
|
line_number_style: Option<Style>,
|
||||||
@@ -134,6 +135,7 @@ impl<'a> TextArea<'a> {
|
|||||||
style: Style::default(),
|
style: Style::default(),
|
||||||
cursor: (0, 0),
|
cursor: (0, 0),
|
||||||
tab_len: 4,
|
tab_len: 4,
|
||||||
|
hard_tab: false,
|
||||||
history: History::new(50),
|
history: History::new(50),
|
||||||
cursor_line_style: Style::default().add_modifier(Modifier::UNDERLINED),
|
cursor_line_style: Style::default().add_modifier(Modifier::UNDERLINED),
|
||||||
line_number_style: None,
|
line_number_style: None,
|
||||||
@@ -619,8 +621,13 @@ impl<'a> TextArea<'a> {
|
|||||||
if self.tab_len == 0 {
|
if self.tab_len == 0 {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
let len = self.tab_len - (self.cursor.1 % self.tab_len as usize) as u8;
|
let tab = if self.hard_tab {
|
||||||
self.insert_str(spaces(len))
|
"\t"
|
||||||
|
} else {
|
||||||
|
let len = self.tab_len - (self.cursor.1 % self.tab_len as usize) as u8;
|
||||||
|
spaces(len)
|
||||||
|
};
|
||||||
|
self.insert_str(tab)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Insert a newline at current cursor position.
|
/// Insert a newline at current cursor position.
|
||||||
@@ -1079,6 +1086,55 @@ impl<'a> TextArea<'a> {
|
|||||||
self.tab_len
|
self.tab_len
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Set if a hard tab is used or not for indent. When `true` is set, typing a tab key inserts a hard tab instead of
|
||||||
|
/// spaces. By default, hard tab is disabled.
|
||||||
|
/// ```
|
||||||
|
/// use tui_textarea::TextArea;
|
||||||
|
///
|
||||||
|
/// let mut textarea = TextArea::default();
|
||||||
|
///
|
||||||
|
/// textarea.set_hard_tab(true);
|
||||||
|
/// textarea.insert_tab();
|
||||||
|
/// assert_eq!(textarea.lines(), ["\t"]);
|
||||||
|
/// ```
|
||||||
|
pub fn set_hard_tab(&mut self, enabled: bool) {
|
||||||
|
self.hard_tab = enabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get if a hard tab is used for indent or not.
|
||||||
|
/// ```
|
||||||
|
/// use tui_textarea::TextArea;
|
||||||
|
///
|
||||||
|
/// let mut textarea = TextArea::default();
|
||||||
|
///
|
||||||
|
/// assert!(!textarea.hard_tab());
|
||||||
|
/// textarea.set_hard_tab(true);
|
||||||
|
/// assert!(textarea.hard_tab());
|
||||||
|
/// ```
|
||||||
|
pub fn hard_tab(&self) -> bool {
|
||||||
|
self.hard_tab
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get a string for indent. It consists of spaces by default. When hard tab is enabled, it is a tab character.
|
||||||
|
/// ```
|
||||||
|
/// use tui_textarea::TextArea;
|
||||||
|
///
|
||||||
|
/// let mut textarea = TextArea::default();
|
||||||
|
///
|
||||||
|
/// assert_eq!(textarea.indent(), " ");
|
||||||
|
/// textarea.set_tab_length(2);
|
||||||
|
/// assert_eq!(textarea.indent(), " ");
|
||||||
|
/// textarea.set_hard_tab(true);
|
||||||
|
/// assert_eq!(textarea.indent(), "\t");
|
||||||
|
/// ```
|
||||||
|
pub fn indent(&self) -> &'static str {
|
||||||
|
if self.hard_tab {
|
||||||
|
"\t"
|
||||||
|
} else {
|
||||||
|
spaces(self.tab_len)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Set how many modifications are remembered for undo/redo. Setting 0 disables undo/redo.
|
/// Set how many modifications are remembered for undo/redo. Setting 0 disables undo/redo.
|
||||||
pub fn set_max_histories(&mut self, max: usize) {
|
pub fn set_max_histories(&mut self, max: usize) {
|
||||||
self.history = History::new(max);
|
self.history = History::new(max);
|
||||||
|
|||||||
Ссылка в новой задаче
Block a user