Add o command for opening items to tui viewer
This patch adds the o command to the tui viewer that can be used to open items. The command uses the same lookup logic as the rusty-man program: First, it tries to find a direct match. If none is found, it uses the search index to find partial matches.
This commit is contained in:
parent
44b1405595
commit
6232585d36
@ -5,6 +5,10 @@ SPDX-License-Identifier: MIT
|
||||
|
||||
# Changelog for rusty-man
|
||||
|
||||
## Unreleased
|
||||
|
||||
- Add `o` command for opening a documentation item to the tui viewer.
|
||||
|
||||
## v0.4.1 (2020-10-11)
|
||||
|
||||
This patch release fixes an issue with the pager configuration.
|
||||
|
@ -7,12 +7,13 @@ use std::convert;
|
||||
|
||||
use anyhow::Context as _;
|
||||
use cursive::view::{Resizable as _, Scrollable as _};
|
||||
use cursive::views::{Dialog, LinearLayout, PaddedView, Panel, TextView};
|
||||
use cursive::views::{Dialog, EditView, LinearLayout, PaddedView, Panel, SelectView, TextView};
|
||||
use cursive::{event, theme, utils::markup};
|
||||
use cursive_markup::MarkupView;
|
||||
|
||||
use crate::args;
|
||||
use crate::doc;
|
||||
use crate::index;
|
||||
use crate::source;
|
||||
use crate::viewer::{self, utils, utils::ManRenderer as _};
|
||||
|
||||
@ -139,7 +140,6 @@ impl<'s> utils::ManRenderer for TuiManRenderer<'s> {
|
||||
) -> Result<(), Self::Error> {
|
||||
let text = markup::StyledString::styled(text, theme::Effect::Bold);
|
||||
if let Some(link) = link {
|
||||
// TODO: bold
|
||||
let heading = LinkView::new(text, move |s| {
|
||||
if let Err(err) = open_link(s, link.clone().into()) {
|
||||
report_error(s, err);
|
||||
@ -221,6 +221,7 @@ fn create_cursive(
|
||||
screen.pop_layer();
|
||||
}
|
||||
});
|
||||
cursive.add_global_callback('o', open_doc_dialog);
|
||||
|
||||
let mut theme = theme::Theme::default();
|
||||
theme.shadow = false;
|
||||
@ -254,6 +255,76 @@ fn report_error(s: &mut cursive::Cursive, error: anyhow::Error) {
|
||||
s.add_layer(dialog);
|
||||
}
|
||||
|
||||
fn with_report_error<F>(s: &mut cursive::Cursive, f: F)
|
||||
where
|
||||
F: Fn(&mut cursive::Cursive) -> anyhow::Result<()>,
|
||||
{
|
||||
if let Err(err) = f(s) {
|
||||
report_error(s, err);
|
||||
}
|
||||
}
|
||||
|
||||
fn open_doc_dialog(s: &mut cursive::Cursive) {
|
||||
let mut edit_view = EditView::new();
|
||||
edit_view.set_on_submit(|s, val| {
|
||||
with_report_error(s, |s| {
|
||||
s.pop_layer();
|
||||
let sources = &context(s).sources;
|
||||
let name = doc::Name::from(val.to_owned());
|
||||
let mut doc = sources.find(&name, None)?;
|
||||
if doc.is_none() {
|
||||
let items = sources.search(&name)?;
|
||||
if items.len() > 1 {
|
||||
select_doc_dialog(s, items);
|
||||
return Ok(());
|
||||
} else if !items.is_empty() {
|
||||
doc = sources.find(&items[0].name, Some(items[0].ty))?;
|
||||
}
|
||||
}
|
||||
if let Some(doc) = doc {
|
||||
open_doc(s, &doc);
|
||||
Ok(())
|
||||
} else {
|
||||
Err(anyhow::anyhow!("Could not find documentation for {}", name))
|
||||
}
|
||||
});
|
||||
});
|
||||
let dialog = Dialog::around(edit_view.min_width(40)).title("Open documentation");
|
||||
s.add_layer(dialog);
|
||||
}
|
||||
|
||||
fn select_doc_dialog(s: &mut cursive::Cursive, items: Vec<index::IndexItem>) {
|
||||
let mut select_view = SelectView::new();
|
||||
select_view.add_all(
|
||||
items
|
||||
.into_iter()
|
||||
.map(|item| (item.name.as_ref().to_owned(), item)),
|
||||
);
|
||||
select_view.set_on_submit(|s, item| {
|
||||
with_report_error(s, |s| {
|
||||
let doc = context(s).sources.find(&item.name, Some(item.ty))?;
|
||||
if let Some(doc) = doc {
|
||||
open_doc(s, &doc);
|
||||
Ok(())
|
||||
} else {
|
||||
Err(anyhow::anyhow!(
|
||||
"Could not find documentation for {}",
|
||||
item.name
|
||||
))
|
||||
}
|
||||
});
|
||||
});
|
||||
let dialog = Dialog::around(select_view.scrollable()).title("Select documentation item");
|
||||
s.add_layer(dialog);
|
||||
}
|
||||
|
||||
fn open_doc(s: &mut cursive::Cursive, doc: &doc::Doc) {
|
||||
let mut renderer = context(s).create_renderer(&doc);
|
||||
renderer.render_doc(&doc).unwrap();
|
||||
let view = renderer.into_view();
|
||||
s.add_fullscreen_layer(view);
|
||||
}
|
||||
|
||||
fn handle_link(s: &mut cursive::Cursive, doc_name: &doc::Fqn, doc_ty: doc::ItemType, link: &str) {
|
||||
let result = resolve_link(doc_name, doc_ty, link).and_then(|link| open_link(s, link));
|
||||
if let Err(err) = result {
|
||||
@ -268,10 +339,7 @@ fn open_link(s: &mut cursive::Cursive, link: ResolvedLink) -> anyhow::Result<()>
|
||||
.sources
|
||||
.find(&name, ty)?
|
||||
.with_context(|| format!("Could not find documentation for item: {}", name))?;
|
||||
let mut renderer = context(s).create_renderer(&doc);
|
||||
renderer.render_doc(&doc).unwrap();
|
||||
let view = renderer.into_view();
|
||||
s.add_fullscreen_layer(view);
|
||||
open_doc(s, &doc);
|
||||
Ok(())
|
||||
}
|
||||
ResolvedLink::External(link) => webbrowser::open(&link)
|
||||
|
Loading…
Reference in New Issue
Block a user