mirror of
https://github.com/lotabout/skim.git
synced 2026-09-10 07:16:23 -04:00
* feat: add more info variants (closes #1042) * chore: generate completions & manpage * docs: update info docs --------- Co-authored-by: Skim bot <skim-bot@skim-rs.github.io>
This commit is contained in:
parent
4997e2d253
commit
7375d30bf1
|
|
@ -377,21 +377,12 @@ Number of spaces that make up a tab
|
|||
\fB\-\-info\fR \fI<INFO>\fR [default: default]
|
||||
Set matching result count display position
|
||||
|
||||
\- hidden: do not display info
|
||||
\- inline: display info in the same row as the input
|
||||
\- default: display info in a dedicated row above the input
|
||||
.br
|
||||
|
||||
.br
|
||||
\fIPossible values:\fR
|
||||
.RS 14
|
||||
.IP \(bu 2
|
||||
default
|
||||
.IP \(bu 2
|
||||
inline
|
||||
.IP \(bu 2
|
||||
hidden
|
||||
.RE
|
||||
\- hidden do not display info
|
||||
\- inline[:SEP] display info in the same row as the input with an optional non\-default
|
||||
separator
|
||||
\- default display info in a dedicated row above the input
|
||||
\- inline\-right[:SEP] display info in the same row as the input with an optional
|
||||
non\-default separator
|
||||
.TP
|
||||
\fB\-\-no\-info\fR
|
||||
Alias for \-\-info=hidden
|
||||
|
|
|
|||
|
|
@ -154,7 +154,7 @@ _sk() {
|
|||
return 0
|
||||
;;
|
||||
--info)
|
||||
COMPREPLY=($(compgen -W "default inline hidden" -- "${cur}"))
|
||||
COMPREPLY=($(compgen -f "${cur}"))
|
||||
return 0
|
||||
;;
|
||||
--header)
|
||||
|
|
|
|||
|
|
@ -44,9 +44,7 @@ complete -c sk -l selector -d 'Set selected item icon' -r
|
|||
complete -c sk -l multi-selector -d 'Set selected item icon' -r
|
||||
complete -c sk -l tabstop -d 'Number of spaces that make up a tab' -r
|
||||
complete -c sk -l ellipsis -d 'The characters used to display truncated lines' -r
|
||||
complete -c sk -l info -d 'Set matching result count display position' -r -f -a "default\t''
|
||||
inline\t''
|
||||
hidden\t''"
|
||||
complete -c sk -l info -d 'Set matching result count display position' -r
|
||||
complete -c sk -l header -d 'Set header, displayed next to the info' -r
|
||||
complete -c sk -l header-lines -d 'Number of lines of the input treated as header' -r
|
||||
complete -c sk -l border -d 'Draw borders around the UI components' -r -f -a "force-off\t'ForceOff disables borders around popups too set with no_border'
|
||||
|
|
|
|||
|
|
@ -20,10 +20,6 @@ module completions {
|
|||
[ "default" "reverse" "reverse-list" ]
|
||||
}
|
||||
|
||||
def "nu-complete sk info" [] {
|
||||
[ "default" "inline" "hidden" ]
|
||||
}
|
||||
|
||||
def "nu-complete sk border" [] {
|
||||
[ "force-off" "none" "plain" "rounded" "double" "thick" "light-double-dashed" "heavy-double-dashed" "light-triple-dashed" "heavy-triple-dashed" "light-quadruple-dashed" "heavy-quadruple-dashed" "quadrant-inside" "quadrant-outside" ]
|
||||
}
|
||||
|
|
@ -86,7 +82,7 @@ module completions {
|
|||
--ansi # Parse ANSI color codes in input strings
|
||||
--tabstop: string # Number of spaces that make up a tab
|
||||
--ellipsis: string # The characters used to display truncated lines
|
||||
--info: string@"nu-complete sk info" # Set matching result count display position
|
||||
--info: string # Set matching result count display position
|
||||
--no-info # Alias for --info=hidden
|
||||
--inline-info # Alias for --info=inline
|
||||
--header: string # Set header, displayed next to the info
|
||||
|
|
|
|||
|
|
@ -56,7 +56,7 @@ reverse-list\:"Display from the top of the screen, prompt at the bottom"))' \
|
|||
'--multi-selector=[Set selected item icon]:MULTI_SELECT_ICON:_default' \
|
||||
'--tabstop=[Number of spaces that make up a tab]:TABSTOP:_default' \
|
||||
'--ellipsis=[The characters used to display truncated lines]:ELLIPSIS:_default' \
|
||||
'--info=[Set matching result count display position]:INFO:(default inline hidden)' \
|
||||
'--info=[Set matching result count display position]:INFO:_default' \
|
||||
'--header=[Set header, displayed next to the info]:HEADER:_default' \
|
||||
'--header-lines=[Number of lines of the input treated as header]:HEADER_LINES:_default' \
|
||||
'--border=[Draw borders around the UI components]::BORDER:((force-off\:"ForceOff disables borders around popups too set with no_border"
|
||||
|
|
|
|||
|
|
@ -501,18 +501,15 @@ pub struct SkimOptions {
|
|||
|
||||
/// Set matching result count display position
|
||||
///
|
||||
/// - hidden: do not display info
|
||||
/// - inline: display info in the same row as the input
|
||||
/// - default: display info in a dedicated row above the input
|
||||
/// - hidden do not display info
|
||||
/// - inline[:SEP] display info in the same row as the input with an optional non-default
|
||||
/// separator
|
||||
/// - default display info in a dedicated row above the input
|
||||
/// - inline-right[:SEP] display info in the same row as the input with an optional
|
||||
/// non-default separator
|
||||
#[cfg_attr(
|
||||
feature = "cli",
|
||||
arg(
|
||||
long,
|
||||
help_heading = "Display",
|
||||
value_enum,
|
||||
default_value = "default",
|
||||
verbatim_doc_comment
|
||||
)
|
||||
arg(long, help_heading = "Display", default_value = "default", verbatim_doc_comment)
|
||||
)]
|
||||
pub info: InfoDisplay,
|
||||
|
||||
|
|
@ -1215,7 +1212,7 @@ impl SkimOptions {
|
|||
self.scrollbar = String::new();
|
||||
}
|
||||
if self.inline_info {
|
||||
self.info = InfoDisplay::Inline;
|
||||
self.info = InfoDisplay::Inline(crate::tui::statusline::DEFAULT_SEPARATOR.to_string());
|
||||
}
|
||||
if self.no_info {
|
||||
self.info = InfoDisplay::Hidden;
|
||||
|
|
|
|||
|
|
@ -174,6 +174,11 @@ impl Widget for &mut App {
|
|||
current_item_idx: self.item_list.current,
|
||||
hscroll_offset: i64::from(self.item_list.manual_hscroll),
|
||||
start: Some(self.spinner_start),
|
||||
inline_separator: self
|
||||
.options
|
||||
.info
|
||||
.separator()
|
||||
.unwrap_or(super::statusline::DEFAULT_SEPARATOR.to_string()),
|
||||
})
|
||||
};
|
||||
res |= self.input.render(self.layout.input_area, buf);
|
||||
|
|
|
|||
|
|
@ -41,6 +41,8 @@ pub struct StatusInfo {
|
|||
pub hscroll_offset: i64,
|
||||
/// Start time for calculating spinner animation
|
||||
pub start: Option<Instant>,
|
||||
/// Inline prefix/separator (when the spinner is hidden)
|
||||
pub inline_separator: String,
|
||||
}
|
||||
|
||||
impl StatusInfo {
|
||||
|
|
@ -86,16 +88,20 @@ impl StatusInfo {
|
|||
|
||||
/// Get the inline separator character: spinner when active, '<' otherwise
|
||||
/// Used for Inline info display mode
|
||||
pub fn inline_separator(&self) -> char {
|
||||
pub fn inline_separator_or_spinner(&self) -> String {
|
||||
if self.show_spinner
|
||||
&& let Some(start) = self.start
|
||||
{
|
||||
let spinner_elapsed_ms = start.elapsed().as_millis();
|
||||
let index =
|
||||
((spinner_elapsed_ms / u128::from(SPINNER_DURATION)) % (SPINNERS_UNICODE.len() as u128)) as usize;
|
||||
SPINNERS_UNICODE[index]
|
||||
format!(
|
||||
"{}{}",
|
||||
SPINNERS_UNICODE[index],
|
||||
" ".repeat(display_width(&self.inline_separator).try_into().unwrap())
|
||||
)
|
||||
} else {
|
||||
'<'
|
||||
self.inline_separator.clone()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -459,12 +465,12 @@ impl SkimWidget for Input {
|
|||
|
||||
// Handle different info display modes
|
||||
match self.info_display {
|
||||
InfoDisplay::Inline => {
|
||||
InfoDisplay::Inline(_) | InfoDisplay::InlineRight(_) => {
|
||||
// Inline mode: render status on the same line as input
|
||||
// Format: prompt + value + " " + separator_char + " " + status + padding + right_status
|
||||
// separator_char is spinner when active, '<' otherwise
|
||||
if let Some(ref status) = self.status_info {
|
||||
let separator = status.inline_separator();
|
||||
let separator = status.inline_separator_or_spinner();
|
||||
let inline_status = status.inline_status();
|
||||
let right_status = status.right_title();
|
||||
|
||||
|
|
@ -472,7 +478,7 @@ impl SkimWidget for Input {
|
|||
// Format: " X " where X is separator (3 chars total)
|
||||
let prompt_width = display_width(&self.prompt);
|
||||
let value_width = display_width(&self.value);
|
||||
let separator_width = 4; // " X " (2xspace + separator + space)
|
||||
let separator_width = display_width(&separator); // " X " (2xspace + separator + space)
|
||||
let inline_status_width = display_width(&inline_status);
|
||||
let right_status_width = display_width(&right_status);
|
||||
|
||||
|
|
@ -481,9 +487,16 @@ impl SkimWidget for Input {
|
|||
let available_width = u64::from(area.width);
|
||||
let padding_width = available_width.saturating_sub(used_width);
|
||||
|
||||
line.push_span(Span::styled(format!(" {separator} "), self.theme.info));
|
||||
if let InfoDisplay::InlineRight(_) = self.info_display {
|
||||
line.push_span(Span::raw(" ".repeat(usize::try_from(padding_width).unwrap() - 2)));
|
||||
}
|
||||
line.push_span(Span::styled(separator, self.theme.info));
|
||||
line.push_span(Span::styled(inline_status, self.theme.info));
|
||||
if let InfoDisplay::Inline(_) = self.info_display {
|
||||
line.push_span(Span::raw(" ".repeat(padding_width.try_into().unwrap())));
|
||||
} else {
|
||||
line.push_span(Span::raw(" ".repeat(2)));
|
||||
}
|
||||
line.push_span(Span::styled(right_status, self.theme.info));
|
||||
|
||||
Paragraph::new(line)
|
||||
|
|
|
|||
|
|
@ -1,7 +1,5 @@
|
|||
#[cfg(feature = "cli")]
|
||||
use clap::ValueEnum;
|
||||
#[cfg(feature = "cli")]
|
||||
use clap::builder::PossibleValue;
|
||||
/// Default inline info separator
|
||||
pub const DEFAULT_SEPARATOR: &str = " < ";
|
||||
|
||||
/// Display mode for the info/status line
|
||||
#[derive(Debug, Clone, Default, Eq, PartialEq)]
|
||||
|
|
@ -10,24 +8,38 @@ pub enum InfoDisplay {
|
|||
#[default]
|
||||
Default,
|
||||
/// Display info inline with the input
|
||||
Inline,
|
||||
Inline(String),
|
||||
/// Hide the info display
|
||||
Hidden,
|
||||
/// Inline and right-aligned
|
||||
InlineRight(String),
|
||||
}
|
||||
|
||||
#[cfg(feature = "cli")]
|
||||
impl ValueEnum for InfoDisplay {
|
||||
fn value_variants<'a>() -> &'a [Self] {
|
||||
use InfoDisplay::{Default, Hidden, Inline};
|
||||
&[Default, Inline, Hidden]
|
||||
}
|
||||
|
||||
fn to_possible_value(&self) -> Option<clap::builder::PossibleValue> {
|
||||
use InfoDisplay::{Default, Hidden, Inline};
|
||||
match self {
|
||||
Default => Some(PossibleValue::new("default")),
|
||||
Inline => Some(PossibleValue::new("inline")),
|
||||
Hidden => Some(PossibleValue::new("hidden")),
|
||||
impl InfoDisplay {
|
||||
pub(crate) fn separator(&self) -> Option<String> {
|
||||
if let InfoDisplay::Inline(s) = self {
|
||||
Some(s.clone())
|
||||
} else if let InfoDisplay::InlineRight(s) = self {
|
||||
Some(s.clone())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&str> for InfoDisplay {
|
||||
fn from(s: &str) -> Self {
|
||||
use InfoDisplay::{Default, Hidden, Inline, InlineRight};
|
||||
let (variant, separator) = s.split_once(':').unwrap_or((s, DEFAULT_SEPARATOR));
|
||||
|
||||
match variant {
|
||||
"default" => Default,
|
||||
"inline" => Inline(separator.to_string()),
|
||||
"inline-right" => InlineRight(separator.to_string()),
|
||||
"hidden" => Hidden,
|
||||
x => panic!(
|
||||
"Failed to parse {x} as an InfoDisplay. Possible options are `default`, `inline[:separator]`, `inline-right:[separator]` or `hidden`"
|
||||
),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -255,6 +255,24 @@ insta_test!(opt_info_inline, ["a", "b", "c"], &["--info", "inline"], {
|
|||
@snap;
|
||||
});
|
||||
|
||||
insta_test!(opt_info_inline_right, ["a", "b", "c"], &["--info", "inline-right"], {
|
||||
@snap;
|
||||
@char 'a';
|
||||
@snap;
|
||||
});
|
||||
|
||||
insta_test!(opt_info_inline_custom, ["a", "b", "c"], &["--info", "inline:SEP"], {
|
||||
@snap;
|
||||
@char 'a';
|
||||
@snap;
|
||||
});
|
||||
|
||||
insta_test!(opt_info_inline_right_custom, ["a", "b", "c"], &["--info", "inline-right:SEP"], {
|
||||
@snap;
|
||||
@char 'a';
|
||||
@snap;
|
||||
});
|
||||
|
||||
insta_test!(opt_inline_info, ["a", "b", "c"], &["--inline-info"], {
|
||||
@snap;
|
||||
@char 'a';
|
||||
|
|
|
|||
29
tests/snapshots/options__opt_info_inline_custom@001.snap
Normal file
29
tests/snapshots/options__opt_info_inline_custom@001.snap
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
---
|
||||
source: tests/options.rs
|
||||
description: "input: items [\"a\", \"b\", \"c\"]\noptions: --info inline:SEP"
|
||||
---
|
||||
" "
|
||||
" "
|
||||
" "
|
||||
" "
|
||||
" "
|
||||
" "
|
||||
" "
|
||||
" "
|
||||
" "
|
||||
" "
|
||||
" "
|
||||
" "
|
||||
" "
|
||||
" "
|
||||
" "
|
||||
" "
|
||||
" "
|
||||
" "
|
||||
" "
|
||||
" "
|
||||
" c "
|
||||
" b "
|
||||
"> a "
|
||||
"> SEP3/3 0/0"
|
||||
cursor: (25, 3)
|
||||
29
tests/snapshots/options__opt_info_inline_custom@002.snap
Normal file
29
tests/snapshots/options__opt_info_inline_custom@002.snap
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
---
|
||||
source: tests/options.rs
|
||||
description: "input: items [\"a\", \"b\", \"c\"]\noptions: --info inline:SEP\nafter:\n @char 'a'"
|
||||
---
|
||||
" "
|
||||
" "
|
||||
" "
|
||||
" "
|
||||
" "
|
||||
" "
|
||||
" "
|
||||
" "
|
||||
" "
|
||||
" "
|
||||
" "
|
||||
" "
|
||||
" "
|
||||
" "
|
||||
" "
|
||||
" "
|
||||
" "
|
||||
" "
|
||||
" "
|
||||
" "
|
||||
" "
|
||||
" "
|
||||
"> a "
|
||||
"> aSEP1/3 0/0"
|
||||
cursor: (25, 4)
|
||||
29
tests/snapshots/options__opt_info_inline_right@001.snap
Normal file
29
tests/snapshots/options__opt_info_inline_right@001.snap
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
---
|
||||
source: tests/options.rs
|
||||
description: "input: items [\"a\", \"b\", \"c\"]\noptions: --info inline-right"
|
||||
---
|
||||
" "
|
||||
" "
|
||||
" "
|
||||
" "
|
||||
" "
|
||||
" "
|
||||
" "
|
||||
" "
|
||||
" "
|
||||
" "
|
||||
" "
|
||||
" "
|
||||
" "
|
||||
" "
|
||||
" "
|
||||
" "
|
||||
" "
|
||||
" "
|
||||
" "
|
||||
" "
|
||||
" c "
|
||||
" b "
|
||||
"> a "
|
||||
"> < 3/3 0/0"
|
||||
cursor: (25, 3)
|
||||
29
tests/snapshots/options__opt_info_inline_right@002.snap
Normal file
29
tests/snapshots/options__opt_info_inline_right@002.snap
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
---
|
||||
source: tests/options.rs
|
||||
description: "input: items [\"a\", \"b\", \"c\"]\noptions: --info inline-right\nafter:\n @char 'a'"
|
||||
---
|
||||
" "
|
||||
" "
|
||||
" "
|
||||
" "
|
||||
" "
|
||||
" "
|
||||
" "
|
||||
" "
|
||||
" "
|
||||
" "
|
||||
" "
|
||||
" "
|
||||
" "
|
||||
" "
|
||||
" "
|
||||
" "
|
||||
" "
|
||||
" "
|
||||
" "
|
||||
" "
|
||||
" "
|
||||
" "
|
||||
"> a "
|
||||
"> a < 1/3 0/0"
|
||||
cursor: (25, 4)
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
---
|
||||
source: tests/options.rs
|
||||
description: "input: items [\"a\", \"b\", \"c\"]\noptions: --info inline-right:SEP"
|
||||
---
|
||||
" "
|
||||
" "
|
||||
" "
|
||||
" "
|
||||
" "
|
||||
" "
|
||||
" "
|
||||
" "
|
||||
" "
|
||||
" "
|
||||
" "
|
||||
" "
|
||||
" "
|
||||
" "
|
||||
" "
|
||||
" "
|
||||
" "
|
||||
" "
|
||||
" "
|
||||
" "
|
||||
" c "
|
||||
" b "
|
||||
"> a "
|
||||
"> SEP3/3 0/0"
|
||||
cursor: (25, 3)
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
---
|
||||
source: tests/options.rs
|
||||
description: "input: items [\"a\", \"b\", \"c\"]\noptions: --info inline-right:SEP\nafter:\n @char 'a'"
|
||||
---
|
||||
" "
|
||||
" "
|
||||
" "
|
||||
" "
|
||||
" "
|
||||
" "
|
||||
" "
|
||||
" "
|
||||
" "
|
||||
" "
|
||||
" "
|
||||
" "
|
||||
" "
|
||||
" "
|
||||
" "
|
||||
" "
|
||||
" "
|
||||
" "
|
||||
" "
|
||||
" "
|
||||
" "
|
||||
" "
|
||||
"> a "
|
||||
"> a SEP1/3 0/0"
|
||||
cursor: (25, 4)
|
||||
Loading…
Reference in a new issue