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
|
# Changelog for rusty-man
|
||||||
|
|
||||||
|
## Unreleased
|
||||||
|
|
||||||
|
- Add `o` command for opening a documentation item to the tui viewer.
|
||||||
|
|
||||||
## v0.4.1 (2020-10-11)
|
## v0.4.1 (2020-10-11)
|
||||||
|
|
||||||
This patch release fixes an issue with the pager configuration.
|
This patch release fixes an issue with the pager configuration.
|
||||||
|
@ -7,12 +7,13 @@ use std::convert;
|
|||||||
|
|
||||||
use anyhow::Context as _;
|
use anyhow::Context as _;
|
||||||
use cursive::view::{Resizable as _, Scrollable 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::{event, theme, utils::markup};
|
||||||
use cursive_markup::MarkupView;
|
use cursive_markup::MarkupView;
|
||||||
|
|
||||||
use crate::args;
|
use crate::args;
|
||||||
use crate::doc;
|
use crate::doc;
|
||||||
|
use crate::index;
|
||||||
use crate::source;
|
use crate::source;
|
||||||
use crate::viewer::{self, utils, utils::ManRenderer as _};
|
use crate::viewer::{self, utils, utils::ManRenderer as _};
|
||||||
|
|
||||||
@ -139,7 +140,6 @@ impl<'s> utils::ManRenderer for TuiManRenderer<'s> {
|
|||||||
) -> Result<(), Self::Error> {
|
) -> Result<(), Self::Error> {
|
||||||
let text = markup::StyledString::styled(text, theme::Effect::Bold);
|
let text = markup::StyledString::styled(text, theme::Effect::Bold);
|
||||||
if let Some(link) = link {
|
if let Some(link) = link {
|
||||||
// TODO: bold
|
|
||||||
let heading = LinkView::new(text, move |s| {
|
let heading = LinkView::new(text, move |s| {
|
||||||
if let Err(err) = open_link(s, link.clone().into()) {
|
if let Err(err) = open_link(s, link.clone().into()) {
|
||||||
report_error(s, err);
|
report_error(s, err);
|
||||||
@ -221,6 +221,7 @@ fn create_cursive(
|
|||||||
screen.pop_layer();
|
screen.pop_layer();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
cursive.add_global_callback('o', open_doc_dialog);
|
||||||
|
|
||||||
let mut theme = theme::Theme::default();
|
let mut theme = theme::Theme::default();
|
||||||
theme.shadow = false;
|
theme.shadow = false;
|
||||||
@ -254,6 +255,76 @@ fn report_error(s: &mut cursive::Cursive, error: anyhow::Error) {
|
|||||||
s.add_layer(dialog);
|
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) {
|
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));
|
let result = resolve_link(doc_name, doc_ty, link).and_then(|link| open_link(s, link));
|
||||||
if let Err(err) = result {
|
if let Err(err) = result {
|
||||||
@ -268,10 +339,7 @@ fn open_link(s: &mut cursive::Cursive, link: ResolvedLink) -> anyhow::Result<()>
|
|||||||
.sources
|
.sources
|
||||||
.find(&name, ty)?
|
.find(&name, ty)?
|
||||||
.with_context(|| format!("Could not find documentation for item: {}", name))?;
|
.with_context(|| format!("Could not find documentation for item: {}", name))?;
|
||||||
let mut renderer = context(s).create_renderer(&doc);
|
open_doc(s, &doc);
|
||||||
renderer.render_doc(&doc).unwrap();
|
|
||||||
let view = renderer.into_view();
|
|
||||||
s.add_fullscreen_layer(view);
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
ResolvedLink::External(link) => webbrowser::open(&link)
|
ResolvedLink::External(link) => webbrowser::open(&link)
|
||||||
|
Loading…
Reference in New Issue
Block a user