Skip to content

Commit

Permalink
Add preview support for help_tags (#630)
Browse files Browse the repository at this point in the history
* Add preview for helptags

* Add clap#impl#on_move#async()

* Add fname and highlight the subject line

* Set the preview syntax to help

* Update CHANGELOG.md

* Fix clippy warnings

* .
  • Loading branch information
liuchengxu authored Feb 12, 2021
1 parent 1607538 commit ba6f546
Show file tree
Hide file tree
Showing 16 changed files with 170 additions and 27 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
- Add `g:ClapProviderHistoryCustomFilter` for customizing the source of `history` provider. #615
- Add a bonus for the match in the filename when the source item is a path, but you can only have this when you are using Python dynamic module or the Rust backend. #614.
- Add a bonus for the files you opened since you enter vim. #622
- Add async preview support for `help_tags` provider, the Rust binary is required. #630

### Fixed

Expand Down
3 changes: 3 additions & 0 deletions autoload/clap/client.vim
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,9 @@ function! clap#client#notify_on_init(method, ...) abort
\ 'provider_id': g:clap.provider.id,
\ 'source_fpath': expand('#'.g:clap.start.bufnr.':p'),
\ }
if g:clap.provider.id ==# 'help_tags'
let params['runtimepath'] = &runtimepath
endif
if a:0 > 0
call extend(params, a:1)
endif
Expand Down
11 changes: 10 additions & 1 deletion autoload/clap/impl/on_move.vim
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,9 @@ if clap#maple#is_available()
catch
return
endtry
if has_key(a:result, 'fname')
if has_key(a:result, 'syntax')
call g:clap.preview.set_syntax(a:result.syntax)
elseif has_key(a:result, 'fname')
call g:clap.preview.set_syntax(clap#ext#into_filetype(a:result.fname))
endif
call clap#preview#highlight_header()
Expand All @@ -45,10 +47,17 @@ if clap#maple#is_available()
endif
call s:sync_run_with_delay()
endfunction

function! clap#impl#on_move#async() abort
return clap#client#call_on_move('on_move', function('s:handle_on_move_result'))
endfunction
else
function! s:dispatch_on_move_impl() abort
call s:sync_run_with_delay()
endfunction

function! clap#impl#on_move#async() abort
endfunction
endif

function! clap#impl#on_move#invoke() abort
Expand Down
4 changes: 3 additions & 1 deletion autoload/clap/provider/help_tags.vim
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
let s:save_cpo = &cpoptions
set cpoptions&vim

let s:help_tags = {}

function! s:get_doc_tags() abort
return ['/doc/tags'] + map(filter(split(&helplang, ','), 'v:val !=? "en"'), '"/doc/tags-".v:val')
endfunction
Expand All @@ -27,6 +29,7 @@ if clap#maple#is_available() && clap#filter#sync#python#has_dynamic_module()
endif
endfunction

let s:help_tags.on_move_async = function('clap#impl#on_move#async')
else

let s:help_tags_memory_cache = []
Expand Down Expand Up @@ -78,7 +81,6 @@ else
endfunction
endif

let s:help_tags = {}
let s:help_tags.sink = function('s:help_tags_sink')
let s:help_tags.source = function('s:help_tags_source')

Expand Down
3 changes: 2 additions & 1 deletion build.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
fn main() {
built::write_built_file().expect("Failed to acquire build-time information");
built::write_built_file()
.unwrap_or_else(|e| panic!("Failed to acquire build-time information: {:?}", e));
}
10 changes: 5 additions & 5 deletions crates/maple_cli/src/cmd/cache.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ impl Cache {
.file_name()
.and_then(std::ffi::OsStr::to_str)
.map(Into::into)
.expect("Couldn't get file name")
.unwrap_or_else(|| panic!("Couldn't get file name"))
})
})
.collect::<Result<Vec<String>, std::io::Error>>()?;
Expand All @@ -73,11 +73,11 @@ pub struct CacheEntry;
impl CacheEntry {
/// Construct the cache entry given command arguments and its working directory, the `total`
/// info is cached in the file name.
pub fn new(cmd_args: &[&str], cmd_dir: Option<PathBuf>, total: usize) -> Result<PathBuf> {
pub fn try_new(cmd_args: &[&str], cmd_dir: Option<PathBuf>, total: usize) -> Result<PathBuf> {
let mut dir = clap_cache_dir();
dir.push(cmd_args.join("_"));
if let Some(mut cmd_dir) = cmd_dir {
dir.push(format!("{}", calculate_hash(&mut cmd_dir)));
if let Some(cmd_dir) = cmd_dir {
dir.push(format!("{}", calculate_hash(&cmd_dir)));
} else {
dir.push("no_cmd_dir");
}
Expand Down Expand Up @@ -117,7 +117,7 @@ impl CacheEntry {
total: usize,
contents: T,
) -> Result<PathBuf> {
let entry = Self::new(cmd_args, cmd_dir, total)?;
let entry = Self::try_new(cmd_args, cmd_dir, total)?;
Self::write(&entry, contents)?;
Ok(entry)
}
Expand Down
2 changes: 1 addition & 1 deletion crates/maple_cli/src/light_command.rs
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ impl CommandEnv {
if let Some(ref output) = self.output {
Ok(output.into())
} else {
CacheEntry::new(args, self.dir.clone(), self.total)
CacheEntry::try_new(args, self.dir.clone(), self.total)
}
}

Expand Down
8 changes: 5 additions & 3 deletions crates/printer/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,9 @@ pub fn truncate_long_matched_lines<T>(
let line = item.display_text.unwrap_or(item.raw);
lnum += 1;
if !indices.is_empty() {
let last_idx = indices.last().expect("indices are non-empty; qed");
let last_idx = indices
.last()
.unwrap_or_else(|| panic!("indices are non-empty; qed"));
if *last_idx > winwidth {
let mut start = *last_idx - winwidth;
if start >= indices[0] || (indices.len() > 1 && *last_idx - start > winwidth) {
Expand Down Expand Up @@ -98,10 +100,10 @@ pub fn truncate_long_matched_lines<T>(
truncated_map.insert(lnum, line);
(truncated, score, truncated_indices)
} else {
(line.into(), score, indices)
(line, score, indices)
}
} else {
(line.into(), score, indices)
(line, score, indices)
}
})
.collect::<Vec<_>>();
Expand Down
2 changes: 1 addition & 1 deletion crates/stdio_server/src/env.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ pub fn initialize_global(msg: Message) {
let preview_size = msg
.params
.get("clap_preview_size")
.expect("Missing clap_preview_size on initialize_global_env");
.unwrap_or_else(|| panic!("Missing clap_preview_size on initialize_global_env"));

let global_env = GlobalEnv::new(is_nvim, enable_icon, preview_size.clone());

Expand Down
2 changes: 1 addition & 1 deletion crates/stdio_server/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,6 @@ where
.spawn(move || {
loop_read_rpc_message(reader, &tx);
})
.expect("Failed to spawn rpc reader thread");
.unwrap_or_else(|_| panic!("Failed to spawn rpc reader thread"));
loop_handle_rpc_message(&rx);
}
9 changes: 8 additions & 1 deletion crates/stdio_server/src/session/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ pub struct SessionContext {
pub source_cmd: Option<String>,
pub winwidth: Option<u64>,
pub provider_id: ProviderId,
pub runtimepath: Option<String>,
pub start_buffer_path: String,
pub is_running: Arc<Mutex<AtomicBool>>,
pub source_list: Arc<Mutex<Option<Vec<String>>>>,
Expand All @@ -29,6 +30,11 @@ impl From<Message> for SessionContext {

let cwd = msg.get_cwd();

let runtimepath = msg
.params
.get("runtimepath")
.and_then(|x| x.as_str().map(Into::into));

let source_cmd = msg
.params
.get("source_cmd")
Expand All @@ -40,13 +46,14 @@ impl From<Message> for SessionContext {
msg.params
.get("source_fpath")
.and_then(|x| x.as_str())
.expect("Missing source_fpath"),
.unwrap_or_else(|| panic!("Missing source_fpath")),
);

Self {
provider_id,
cwd,
source_cmd,
runtimepath,
winwidth,
start_buffer_path,
is_running: Arc::new(Mutex::new(true.into())),
Expand Down
5 changes: 3 additions & 2 deletions crates/stdio_server/src/session/handler/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,9 @@ impl HandleMessage for MessageHandler {
match msg {
RpcMessage::OnMove(msg) => {
let msg_id = msg.id;
if let Err(e) = on_move::OnMoveHandler::try_new(msg, context).map(|x| x.handle()) {
write_response(json!({ "error": format!("{}",e), "id": msg_id }));
if let Err(e) = on_move::OnMoveHandler::try_new(&msg, context).map(|x| x.handle()) {
log::debug!("Handle RpcMessage::OnMove {:?}, error: {:?}", msg, e);
write_response(json!({"error": format!("{}",e), "id": msg_id }));
}
}
RpcMessage::OnTyped(msg) => on_typed::handle_on_typed(msg, context),
Expand Down
114 changes: 108 additions & 6 deletions crates/stdio_server/src/session/handler/on_move.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,51 @@ pub fn as_absolute_path<P: AsRef<Path>>(path: P) -> Result<String> {
.map_err(|e| anyhow!("{:?}, path:{}", e, path.as_ref().display()))
}

#[derive(Debug, Clone)]
struct PreviewTag {
subject: String,
doc_filename: String,
runtimepath: String,
}

fn find_tag_line(p: &PathBuf, subject: &str) -> Option<usize> {
if let Ok(doc_lines) = utility::read_lines(p) {
for (idx, doc_line) in doc_lines.enumerate() {
if let Ok(d_line) = doc_line {
if d_line.trim().contains(&format!("*{}*", subject)) {
return Some(idx);
}
}
}
}
None
}

impl PreviewTag {
pub fn new(subject: String, doc_filename: String, runtimepath: String) -> Self {
Self {
subject,
doc_filename,
runtimepath,
}
}

pub fn get_help_lines(&self, size: usize) -> Option<(String, Vec<String>)> {
for r in self.runtimepath.split(',') {
let p = Path::new(r).join("doc").join(&self.doc_filename);
if p.exists() {
if let Some(line_number) = find_tag_line(&p, &self.subject) {
if let Ok(lines_iter) = utility::read_lines_from(&p, line_number, size) {
return Some((format!("{}", p.display()), lines_iter.collect()));
}
}
}
}

None
}
}

/// Preview environment on Vim CursorMoved event.
#[derive(Debug, Clone)]
#[allow(dead_code)]
Expand All @@ -27,10 +72,27 @@ pub enum OnMove {
Files(PathBuf),
Filer(PathBuf),
History(PathBuf),
Grep { path: PathBuf, lnum: usize },
BLines { path: PathBuf, lnum: usize },
ProjTags { path: PathBuf, lnum: usize },
BufferTags { path: PathBuf, lnum: usize },
Grep {
path: PathBuf,
lnum: usize,
},
BLines {
path: PathBuf,
lnum: usize,
},
ProjTags {
path: PathBuf,
lnum: usize,
},
BufferTags {
path: PathBuf,
lnum: usize,
},
HelpTags {
subject: String,
doc_filename: String,
runtimepath: String,
},
}

/// Build the absolute path using cwd and relative path.
Expand Down Expand Up @@ -82,6 +144,23 @@ impl OnMove {
let path = context.start_buffer_path.clone().into();
Self::BufferTags { path, lnum }
}
"help_tags" => {
let runtimepath = context
.runtimepath
.clone()
.context("no runtimepath in the context")?;
let items = curline.split('\t').collect::<Vec<_>>();
if items.len() < 2 {
return Err(anyhow!(
"Can not extract subject and doc_filename from the line"
));
}
Self::HelpTags {
subject: items[0].trim().to_string(),
doc_filename: items[1].trim().to_string(),
runtimepath,
}
}
"commits" | "bcommits" => {
let rev = parse_rev(&curline).context("can not extract rev")?;
Self::Commit(rev.into())
Expand All @@ -107,7 +186,7 @@ pub struct OnMoveHandler<'a> {
}

impl<'a> OnMoveHandler<'a> {
pub fn try_new(msg: Message, context: &'a SessionContext) -> anyhow::Result<Self> {
pub fn try_new(msg: &Message, context: &'a SessionContext) -> anyhow::Result<Self> {
let msg_id = msg.id;
let provider_id = context.provider_id.clone();
let curline = msg.get_curline(&provider_id)?;
Expand Down Expand Up @@ -140,6 +219,11 @@ impl<'a> OnMoveHandler<'a> {
debug!("path:{}, lnum:{}", path.display(), lnum);
self.preview_file_at(&path, *lnum);
}
HelpTags {
subject,
doc_filename,
runtimepath,
} => self.preview_help_subject(subject, doc_filename, runtimepath),
Filer(path) if path.is_dir() => {
self.preview_directory(&path)?;
}
Expand All @@ -155,7 +239,7 @@ impl<'a> OnMoveHandler<'a> {
}

fn send_response(&self, result: serde_json::value::Value) {
let provider_id: crate::types::ProviderId = self.provider_id.clone().into();
let provider_id: crate::types::ProviderId = self.provider_id.clone();
write_response(json!({
"id": self.msg_id,
"provider_id": provider_id,
Expand All @@ -177,6 +261,24 @@ impl<'a> OnMoveHandler<'a> {
Ok(())
}

fn preview_help_subject(&self, subject: &str, doc_filename: &str, runtimepath: &str) {
let preview_tag = PreviewTag::new(subject.into(), doc_filename.into(), runtimepath.into());
if let Some((fname, lines)) = preview_tag.get_help_lines(self.size * 2) {
let lines = std::iter::once(fname.clone())
.chain(lines.into_iter())
.collect::<Vec<_>>();
self.send_response(json!({
"event": "on_move",
"syntax": "help",
"lines": lines,
"hi_lnum": 1,
"fname": fname
}));
} else {
debug!("Can not find the preview help lines for {:?}", preview_tag);
}
}

fn preview_file_at<P: AsRef<Path>>(&self, path: P, lnum: usize) {
match utility::read_preview_lines(path.as_ref(), lnum, self.size) {
Ok((lines_iter, hi_lnum)) => {
Expand Down
6 changes: 3 additions & 3 deletions crates/stdio_server/src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,22 +81,22 @@ impl Message {
.get(key)
.and_then(|x| x.as_str())
.map(Into::into)
.expect(&format!("Missing {} in msg.params", key))
.unwrap_or_else(|| panic!("Missing {} in msg.params", key))
}

fn _get_string(&self, key: &str) -> anyhow::Result<String> {
self.params
.get(key)
.and_then(|x| x.as_str())
.map(Into::into)
.ok_or(anyhow::anyhow!("Missing {} in msg.params", key))
.ok_or_else(|| anyhow::anyhow!("Missing {} in msg.params", key))
}
}

#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub struct ProviderId(String);

const NO_ICON_PROVIDERS: [&str; 3] = ["blines", "commits", "bcommits"];
const NO_ICON_PROVIDERS: [&str; 4] = ["blines", "commits", "bcommits", "help_tags"];

impl ProviderId {
pub fn as_str(&self) -> &str {
Expand Down
Loading

0 comments on commit ba6f546

Please sign in to comment.