mirror of
https://github.com/denisidoro/navi.git
synced 2026-01-23 02:14:19 +00:00
Merge 2030a5c7d7 into b01291e040
This commit is contained in:
commit
f9c4122d72
7 changed files with 88 additions and 17 deletions
|
|
@ -13,8 +13,8 @@ pub struct Input {
|
|||
pub line: String,
|
||||
}
|
||||
|
||||
fn extract_elements(argstr: &str) -> Result<(&str, &str, &str)> {
|
||||
let mut parts = argstr.split(deser::terminal::DELIMITER).skip(3);
|
||||
fn extract_elements(argstr: &str, skip_columns: usize) -> Result<(&str, &str, &str)> {
|
||||
let mut parts = argstr.split(deser::terminal::DELIMITER).skip(skip_columns);
|
||||
let tags = parts.next().context("No `tags` element provided.")?;
|
||||
let comment = parts.next().context("No `comment` element provided.")?;
|
||||
let snippet = parts.next().context("No `snippet` element provided.")?;
|
||||
|
|
@ -25,7 +25,10 @@ impl Runnable for Input {
|
|||
fn run(&self) -> Result<()> {
|
||||
let line = &self.line;
|
||||
|
||||
let (tags, comment, snippet) = extract_elements(line)?;
|
||||
// In multiline mode, only 1 column is used for rendering tags, comment an snippet with zfs.
|
||||
// In legacy mode, using 3 columns for tags, comment and snippet allow permuting their order with --with-nth of fzf.
|
||||
let skip_columns = if CONFIG.multiline() { 1 } else { 3 };
|
||||
let (tags, comment, snippet) = extract_elements(line, skip_columns)?;
|
||||
|
||||
println!(
|
||||
"{comment} {tags} \n{snippet}",
|
||||
|
|
|
|||
|
|
@ -36,7 +36,8 @@ use clap::{crate_version, Parser, Subcommand};
|
|||
navi --fzf-overrides-var '--no-select-1' # same, but for variable selection
|
||||
navi --fzf-overrides '--nth 1,2' # only consider the first two columns for search
|
||||
navi --fzf-overrides '--no-exact' # use looser search algorithm
|
||||
navi --tag-rules='git,!checkout' # show non-checkout git snippets only")]
|
||||
navi --tag-rules='git,!checkout' # show non-checkout git snippets only
|
||||
navi --multiline # show multiline snippets (adds support for newlines in snippet/comment)")]
|
||||
#[clap(version = crate_version!())]
|
||||
pub(super) struct ClapConfig {
|
||||
/// Colon-separated list of paths containing .cheat files
|
||||
|
|
@ -80,6 +81,10 @@ pub(super) struct ClapConfig {
|
|||
#[arg(long, allow_hyphen_values = true)]
|
||||
pub fzf_overrides_var: Option<String>,
|
||||
|
||||
/// When set, show multiline snippets in the terminal listing (split snippet/comment across lines)
|
||||
#[arg(long)]
|
||||
pub multiline: bool,
|
||||
|
||||
/// Finder application to use
|
||||
#[arg(long, ignore_case = true)]
|
||||
pub finder: Option<FinderChoice>,
|
||||
|
|
|
|||
|
|
@ -169,6 +169,10 @@ impl Config {
|
|||
self.yaml.style.tag.width_percentage
|
||||
}
|
||||
|
||||
pub fn multiline(&self) -> bool {
|
||||
self.clap.multiline || self.yaml.style.multiline
|
||||
}
|
||||
|
||||
pub fn comment_width_percentage(&self) -> u16 {
|
||||
self.yaml.style.comment.width_percentage
|
||||
}
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@ pub struct Style {
|
|||
pub tag: ColorWidth,
|
||||
pub comment: ColorWidth,
|
||||
pub snippet: ColorWidth,
|
||||
pub multiline: bool,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Debug)]
|
||||
|
|
@ -167,6 +168,7 @@ impl Default for Style {
|
|||
min_width: 45,
|
||||
},
|
||||
snippet: Default::default(),
|
||||
multiline: false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -33,21 +33,66 @@ lazy_static! {
|
|||
|
||||
pub fn write(item: &Item) -> String {
|
||||
let (tag_width_percentage, comment_width_percentage, snippet_width_percentage) = *COLUMN_WIDTHS;
|
||||
format!(
|
||||
"{tags_short}{delimiter}{comment_short}{delimiter}{snippet_short}{delimiter}{tags}{delimiter}{comment}{delimiter}{snippet}{delimiter}{file_index}{delimiter}\n",
|
||||
let snippet = &item.snippet.trim_end_matches(LINE_SEPARATOR);
|
||||
|
||||
let printer_item = if CONFIG.multiline() {
|
||||
let separator_count = max(
|
||||
snippet.matches(LINE_SEPARATOR).count(),
|
||||
item.comment.matches(LINE_SEPARATOR).count(),
|
||||
);
|
||||
|
||||
let splitted_comment = item.comment.split(LINE_SEPARATOR).collect::<Vec<&str>>();
|
||||
let splitted_snippet = snippet.split(LINE_SEPARATOR).collect::<Vec<&str>>();
|
||||
|
||||
(0..=separator_count)
|
||||
.map(|i| {
|
||||
format!(
|
||||
"{tags_short}{delimiter}{comment_line_i}{delimiter}{snippet_line_i}",
|
||||
tags_short = style(limit_str(
|
||||
if i == 0 { &item.tags } else { "" },
|
||||
tag_width_percentage
|
||||
))
|
||||
.with(CONFIG.tag_color()),
|
||||
comment_line_i = style(limit_str(
|
||||
splitted_comment.get(i).unwrap_or(&""),
|
||||
comment_width_percentage
|
||||
))
|
||||
.with(CONFIG.comment_color()),
|
||||
snippet_line_i = style(limit_str(
|
||||
splitted_snippet.get(i).unwrap_or(&""),
|
||||
snippet_width_percentage
|
||||
))
|
||||
.with(CONFIG.snippet_color()),
|
||||
delimiter = " ",
|
||||
)
|
||||
})
|
||||
.collect::<Vec<String>>()
|
||||
.join("\n")
|
||||
} else {
|
||||
format!(
|
||||
"{tags_short}{delimiter}{comment_short}{delimiter}{snippet_short}",
|
||||
tags_short = style(limit_str(&item.tags, tag_width_percentage)).with(CONFIG.tag_color()),
|
||||
comment_short = style(limit_str(&item.comment, comment_width_percentage)).with(CONFIG.comment_color()),
|
||||
snippet_short = style(limit_str(&fix_newlines(&item.snippet), snippet_width_percentage)).with(CONFIG.snippet_color()),
|
||||
comment_short = style(limit_str(&fix_newlines(&item.comment), comment_width_percentage))
|
||||
.with(CONFIG.comment_color()),
|
||||
snippet_short = style(limit_str(&fix_newlines(&item.snippet), snippet_width_percentage))
|
||||
.with(CONFIG.snippet_color()),
|
||||
delimiter = DELIMITER,
|
||||
)
|
||||
};
|
||||
|
||||
format!(
|
||||
"{printer_item}{delimiter}{tags}{delimiter}{comment}{delimiter}{snippet}{delimiter}{file_index}{delimiter}\0",
|
||||
printer_item = printer_item,
|
||||
tags = item.tags,
|
||||
comment = item.comment,
|
||||
delimiter = DELIMITER,
|
||||
snippet = &item.snippet.trim_end_matches(LINE_SEPARATOR),
|
||||
snippet = snippet,
|
||||
file_index = item.file_index.unwrap_or(0),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn read(raw_snippet: &str, is_single: bool) -> Result<(&str, Item)> {
|
||||
let mut lines = raw_snippet.split('\n');
|
||||
let mut lines = raw_snippet.split('\0');
|
||||
let key = if is_single {
|
||||
"enter"
|
||||
} else {
|
||||
|
|
@ -56,11 +101,12 @@ pub fn read(raw_snippet: &str, is_single: bool) -> Result<(&str, Item)> {
|
|||
.context("Key was promised but not present in `selections`")?
|
||||
};
|
||||
|
||||
let skip_columns = if CONFIG.multiline() { 1 } else { 3 };
|
||||
let mut parts = lines
|
||||
.next()
|
||||
.context("No more parts in `selections`")?
|
||||
.split(DELIMITER)
|
||||
.skip(3);
|
||||
.skip(skip_columns);
|
||||
|
||||
let tags = parts.next().unwrap_or("").into();
|
||||
let comment = parts.next().unwrap_or("").into();
|
||||
|
|
|
|||
|
|
@ -119,7 +119,8 @@ impl FinderChoice {
|
|||
]);
|
||||
|
||||
if !opts.show_all_columns {
|
||||
command.args(["--with-nth", "1,2,3"]);
|
||||
let with_nth = if CONFIG.multiline() { "1" } else { "1,2,3" };
|
||||
command.args(["--read0", "--print0", "--with-nth", with_nth]);
|
||||
}
|
||||
|
||||
if !opts.prevent_select1 {
|
||||
|
|
|
|||
|
|
@ -225,9 +225,10 @@ impl<'a> Parser<'a> {
|
|||
|
||||
let write_fn = self.write_fn;
|
||||
|
||||
self.writer
|
||||
return self
|
||||
.writer
|
||||
.write_all(write_fn(item).as_bytes())
|
||||
.context("Failed to write command to finder's stdin")
|
||||
.context("Failed to write command to finder's stdin");
|
||||
}
|
||||
|
||||
pub fn read_lines(
|
||||
|
|
@ -265,6 +266,7 @@ impl<'a> Parser<'a> {
|
|||
else if line.starts_with('%') {
|
||||
should_break = self.write_cmd(&item).is_err();
|
||||
item.snippet = String::from("");
|
||||
item.comment = String::from("");
|
||||
item.tags = without_prefix(&line);
|
||||
}
|
||||
// dependency
|
||||
|
|
@ -281,9 +283,17 @@ impl<'a> Parser<'a> {
|
|||
}
|
||||
// comment
|
||||
else if line.starts_with('#') {
|
||||
should_break = self.write_cmd(&item).is_err();
|
||||
item.snippet = String::from("");
|
||||
item.comment = without_prefix(&line);
|
||||
// if current item has a snippet, write it to the finder and start a new item
|
||||
if !item.snippet.is_empty() {
|
||||
should_break = self.write_cmd(&item).is_err();
|
||||
item.snippet = String::from("");
|
||||
item.comment = without_prefix(&line);
|
||||
} else {
|
||||
if !item.comment.is_empty() {
|
||||
item.comment.push_str(deser::LINE_SEPARATOR);
|
||||
}
|
||||
item.comment.push_str(&without_prefix(&line));
|
||||
}
|
||||
}
|
||||
// variable
|
||||
else if !variable_cmd.is_empty()
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue