Open links via number shortcuts
This commit is contained in:
parent
7932c2f20b
commit
37b04c7eba
1 changed files with 51 additions and 14 deletions
|
|
@ -3,6 +3,7 @@ use std::io;
|
||||||
use crossterm::event::KeyCode;
|
use crossterm::event::KeyCode;
|
||||||
use crossterm::style::{ContentStyle, Stylize};
|
use crossterm::style::{ContentStyle, Stylize};
|
||||||
use linkify::{LinkFinder, LinkKind};
|
use linkify::{LinkFinder, LinkKind};
|
||||||
|
use toss::styled::Styled;
|
||||||
|
|
||||||
use crate::ui::input::{key, InputEvent, KeyBindingsList, KeyEvent};
|
use crate::ui::input::{key, InputEvent, KeyBindingsList, KeyEvent};
|
||||||
use crate::ui::widgets::list::ListState;
|
use crate::ui::widgets::list::ListState;
|
||||||
|
|
@ -22,6 +23,8 @@ pub enum EventResult {
|
||||||
ErrorOpeningLink { link: String, error: io::Error },
|
ErrorOpeningLink { link: String, error: io::Error },
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const NUMBER_KEYS: [char; 10] = ['1', '2', '3', '4', '5', '6', '7', '8', '9', '0'];
|
||||||
|
|
||||||
impl LinksState {
|
impl LinksState {
|
||||||
pub fn new(content: &str) -> Self {
|
pub fn new(content: &str) -> Self {
|
||||||
let links = LinkFinder::new()
|
let links = LinkFinder::new()
|
||||||
|
|
@ -37,6 +40,8 @@ impl LinksState {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn widget(&self) -> BoxedWidget {
|
pub fn widget(&self) -> BoxedWidget {
|
||||||
|
let style_selected = ContentStyle::default().black().on_white();
|
||||||
|
|
||||||
let mut list = self.list.widget().focus(true);
|
let mut list = self.list.widget().focus(true);
|
||||||
if self.links.is_empty() {
|
if self.links.is_empty() {
|
||||||
list.add_unsel(Text::new((
|
list.add_unsel(Text::new((
|
||||||
|
|
@ -45,30 +50,51 @@ impl LinksState {
|
||||||
)))
|
)))
|
||||||
}
|
}
|
||||||
for (id, link) in self.links.iter().enumerate() {
|
for (id, link) in self.links.iter().enumerate() {
|
||||||
list.add_sel(
|
let (line_normal, line_selected) = if let Some(number_key) = NUMBER_KEYS.get(id) {
|
||||||
id,
|
(
|
||||||
Text::new((link,)),
|
Styled::new(
|
||||||
Text::new((link, ContentStyle::default().black().on_white())),
|
format!("[{number_key}]"),
|
||||||
);
|
ContentStyle::default().dark_grey().bold(),
|
||||||
|
)
|
||||||
|
.then_plain(" ")
|
||||||
|
.then_plain(link),
|
||||||
|
Styled::new(format!("[{number_key}]"), style_selected.bold())
|
||||||
|
.then(" ", style_selected)
|
||||||
|
.then(link, style_selected),
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
(
|
||||||
|
Styled::new_plain(format!(" {link}")),
|
||||||
|
Styled::new(format!(" {link}"), style_selected),
|
||||||
|
)
|
||||||
|
};
|
||||||
|
|
||||||
|
list.add_sel(id, Text::new(line_normal), Text::new(line_selected));
|
||||||
}
|
}
|
||||||
|
|
||||||
Popup::new(list).title("Links").build()
|
Popup::new(list).title("Links").build()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn open_link(&self) -> EventResult {
|
fn open_link_by_id(&self, id: usize) -> EventResult {
|
||||||
if let Some(id) = self.list.cursor() {
|
if let Some(link) = self.links.get(id) {
|
||||||
if let Some(link) = self.links.get(id) {
|
if let Err(error) = open::that(link) {
|
||||||
if let Err(error) = open::that(link) {
|
return EventResult::ErrorOpeningLink {
|
||||||
return EventResult::ErrorOpeningLink {
|
link: link.to_string(),
|
||||||
link: link.to_string(),
|
error,
|
||||||
error,
|
};
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
EventResult::Handled
|
EventResult::Handled
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn open_link(&self) -> EventResult {
|
||||||
|
if let Some(id) = self.list.cursor() {
|
||||||
|
self.open_link_by_id(id)
|
||||||
|
} else {
|
||||||
|
EventResult::Handled
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn list_key_bindings(&self, bindings: &mut KeyBindingsList) {
|
pub fn list_key_bindings(&self, bindings: &mut KeyBindingsList) {
|
||||||
bindings.binding("esc", "close links popup");
|
bindings.binding("esc", "close links popup");
|
||||||
bindings.binding("j/k, ↓/↑", "move cursor up/down");
|
bindings.binding("j/k, ↓/↑", "move cursor up/down");
|
||||||
|
|
@ -77,6 +103,7 @@ impl LinksState {
|
||||||
bindings.binding("ctrl+y/e", "scroll up/down");
|
bindings.binding("ctrl+y/e", "scroll up/down");
|
||||||
bindings.empty();
|
bindings.empty();
|
||||||
bindings.binding("enter", "open selected link");
|
bindings.binding("enter", "open selected link");
|
||||||
|
bindings.binding("1,2,...", "open link by position");
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn handle_input_event(&mut self, event: &InputEvent) -> EventResult {
|
pub fn handle_input_event(&mut self, event: &InputEvent) -> EventResult {
|
||||||
|
|
@ -89,6 +116,16 @@ impl LinksState {
|
||||||
key!(Ctrl + 'y') => self.list.scroll_up(1),
|
key!(Ctrl + 'y') => self.list.scroll_up(1),
|
||||||
key!(Ctrl + 'e') => self.list.scroll_down(1),
|
key!(Ctrl + 'e') => self.list.scroll_down(1),
|
||||||
key!(Enter) => return self.open_link(),
|
key!(Enter) => return self.open_link(),
|
||||||
|
key!('1') => return self.open_link_by_id(0),
|
||||||
|
key!('2') => return self.open_link_by_id(1),
|
||||||
|
key!('3') => return self.open_link_by_id(2),
|
||||||
|
key!('4') => return self.open_link_by_id(3),
|
||||||
|
key!('5') => return self.open_link_by_id(4),
|
||||||
|
key!('6') => return self.open_link_by_id(5),
|
||||||
|
key!('7') => return self.open_link_by_id(6),
|
||||||
|
key!('8') => return self.open_link_by_id(7),
|
||||||
|
key!('9') => return self.open_link_by_id(8),
|
||||||
|
key!('0') => return self.open_link_by_id(9),
|
||||||
_ => return EventResult::NotHandled,
|
_ => return EventResult::NotHandled,
|
||||||
}
|
}
|
||||||
EventResult::Handled
|
EventResult::Handled
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue