Skip to content

Commit

Permalink
Add on_move_async property (#481)
Browse files Browse the repository at this point in the history
* Add `on_move_async` property

* Impl async preview for bcommits and commits

* Update CHANGELOG.md
  • Loading branch information
liuchengxu committed Jul 13, 2020
1 parent fe6797a commit 1c56d8a
Show file tree
Hide file tree
Showing 12 changed files with 117 additions and 17 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ CHANGELOG
- Python dynamic module now can be compiled using stable Rust. ([#471](https://github.com/liuchengxu/vim-clap/pull/471))
- Add `windows` preview support. ([#473](https://github.com/liuchengxu/vim-clap/pull/473))
- Impl `commits` and `bcommits` provider. ([#477](https://github.com/liuchengxu/vim-clap/pull/477)) @ray-x
- Add new provider property `on_move_async`. ([#481](https://github.com/liuchengxu/vim-clap/pull/481))

### Fixed

Expand Down
3 changes: 3 additions & 0 deletions PROVIDER.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ Field | Type | Required | Has default implem
`filter` | Funcref | **mandatory** | **Yes**
`on_typed` | Funcref | **mandatory** | **Yes**
`on_move` | Funcref | optional | No
`on_move_async` | Funcref | optional | No
`on_enter` | Funcref | optional | No
`on_exit` | Funcref | optional | No
`support_open_action` | Bool | optional | **Yes** if the `sink` is `e`/`edit`/`edit!`
Expand Down Expand Up @@ -100,6 +101,8 @@ Field | Type | Required | Has default implem

- `on_move`: when navigating the result list, can be used for the preview purpose, see [clap/provider/colors](autoload/clap/provider/colors.vim).

- `on_move_async`: async preview implementation, normally done by the Rust binary maple, see [autoload/clap/provider/filer.vim](autoload/clap/provider/filer.vim).

- `on_enter`: when entering the clap window, can be used for recording the current state.

- `on_exit`: can be used for restoring the state on start.
Expand Down
9 changes: 4 additions & 5 deletions autoload/clap/impl/on_move.vim
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,7 @@ if clap#maple#is_available()
endfunction

function! s:dispatch_on_move_impl() abort
if g:clap.provider.id ==# 'filer'
call g:clap.provider._().on_move()
return
elseif index(s:async_preview_implemented, g:clap.provider.id) > -1
if index(s:async_preview_implemented, g:clap.provider.id) > -1
return clap#client#call_on_move('on_move', function('s:handle_on_move_result'))
endif
call s:sync_run_with_delay()
Expand All @@ -55,7 +52,9 @@ function! clap#impl#on_move#invoke() abort
if get(g:, '__clap_has_no_matches', v:false)
return
endif
if has_key(g:clap.provider._(), 'on_move')
if has_key(g:clap.provider._(), 'on_move_async')
call g:clap.provider._().on_move_async()
elseif has_key(g:clap.provider._(), 'on_move')
call s:dispatch_on_move_impl()
endif
endfunction
Expand Down
4 changes: 4 additions & 0 deletions autoload/clap/provider/bcommits.vim
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@ function! s:bcommits.on_move() abort
call clap#provider#commits#on_move_common(s:into_git_diff_cmd(cur_line))
endfunction

function! s:bcommits.on_move_async() abort
call clap#client#call_on_move('on_move', function('clap#provider#commits#on_move_callback'))
endfunction

function! s:bcommits.sink(line) abort
call clap#provider#commits#sink_inner('!'.s:into_git_diff_cmd(a:line))
endfunction
Expand Down
10 changes: 10 additions & 0 deletions autoload/clap/provider/commits.vim
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,16 @@ function! s:commits.on_move() abort
call clap#provider#commits#on_move_common('git show '.rev)
endfunction

function! clap#provider#commits#on_move_callback(result) abort
let lines = a:result.lines
call clap#preview#show_lines(lines, 'diff', -1)
call clap#preview#highlight_header()
endfunction

function! s:commits.on_move_async() abort
call clap#client#call_on_move('on_move', function('clap#provider#commits#on_move_callback'))
endfunction

function! clap#provider#commits#sink_inner(bang_cmd) abort
vertical botright new
setlocal buftype=nofile bufhidden=wipe noswapfile nomodeline
Expand Down
3 changes: 1 addition & 2 deletions autoload/clap/provider/filer.vim
Original file line number Diff line number Diff line change
Expand Up @@ -230,7 +230,7 @@ function! s:filer_handle_on_move_result(result) abort
endif
endfunction

function! s:filer_on_move() abort
function! s:filer.on_move_async() abort
call clap#client#call_on_move('filer/on_move', function('s:filer_handle_on_move_result'), {'cwd': s:current_dir})
endfunction

Expand Down Expand Up @@ -261,7 +261,6 @@ endfunction
let s:filer.init = function('s:start_rpc_service')
let s:filer.sink = function('s:filer_sink')
let s:filer.syntax = 'clap_filer'
let s:filer.on_move = function('s:filer_on_move')
let s:filer.on_typed = function('s:filer_on_typed')
let s:filer.bs_action = function('s:bs_action')
let s:filer.tab_action = function('s:tab_action')
Expand Down
22 changes: 20 additions & 2 deletions crates/pattern/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ lazy_static! {
static ref BUFFER_TAGS: Regex = Regex::new(r"^.*:(\d+)").unwrap();

static ref PROJ_TAGS: Regex = Regex::new(r"^(.*):(\d+).*\[(.*)@(.*)\]").unwrap();

static ref COMMIT_RE: Regex = Regex::new(r"^.*\d{4}-\d{2}-\d{2}\s+([0-9a-z]+)\s+").unwrap();
}

/// Extract tag name from the line in tags provider.
Expand Down Expand Up @@ -83,6 +85,11 @@ fn parse_lnum(lnum: &str) -> Option<usize> {
}
}

pub fn parse_rev(line: &str) -> Option<&str> {
let cap = COMMIT_RE.captures(line)?;
cap.get(1).map(|x| x.as_str())
}

pub fn extract_proj_tags(line: &str) -> Option<(usize, &str)> {
let cap = PROJ_TAGS.captures(line)?;
let lnum = cap.get(2).map(|x| x.as_str()).and_then(parse_lnum)?;
Expand Down Expand Up @@ -138,12 +145,23 @@ mod tests {
#[test]
fn test_buffer_tags_regexp() {
let line = r#" extract_fpath_from_grep_line:58 [function] pub fn extract_fpath_from_grep_line(line: &str) -> Option<&str> {"#;
println!("{:?}", extract_buf_tags_lnum(line));
assert_eq!(Some(58), extract_buf_tags_lnum(line));
}

#[test]
fn test_blines_lnum() {
let line = r#" 103 call clap#helper#echo_error('Provider without source must specify on_moved, but only has: '.keys(provider_info))"#;
println!("{:?}", extract_blines_lnum(line));
assert_eq!(Some(103), extract_blines_lnum(line));
}

#[test]
fn test_parse_rev() {
let line =
"* 2019-10-18 8ed4391 Rename sign and rooter related options (#65) (Liu-Cheng Xu)";
assert_eq!(parse_rev(line), Some("8ed4391"));
let line = "2019-10-18 8ed4391 Rename sign and rooter related options (#65) (Liu-Cheng Xu)";
assert_eq!(parse_rev(line), Some("8ed4391"));
let line = "2019-12-29 3f0d00c Add forerunner job status sign and a delay timer for running maple (#184) (Liu-Cheng Xu)";
assert_eq!(parse_rev(line), Some("3f0d00c"));
}
}
1 change: 1 addition & 0 deletions crates/stdio_server/src/filer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ impl HandleMessage for FilerMessageHandler {
msg_id: msg.id,
size: provider_id.get_preview_size(),
provider_id,
context,
inner: OnMove::Filer(path),
};
on_move_handler.handle().unwrap();
Expand Down
8 changes: 8 additions & 0 deletions crates/stdio_server/src/session/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,14 @@ pub struct SessionContext {
pub source_list: Arc<Mutex<Option<Vec<String>>>>,
}

impl SessionContext {
// Executes the command `cmd` and returns the raw bytes of stdout.
pub fn execute(&self, cmd: &str) -> Result<Vec<u8>> {
let out = utility::execute_at(cmd, Some(&self.cwd))?;
Ok(out.stdout)
}
}

impl From<Message> for SessionContext {
fn from(msg: Message) -> Self {
log::debug!("recv msg for SessionContext: {:?}", msg);
Expand Down
38 changes: 31 additions & 7 deletions crates/stdio_server/src/session/handler/on_move.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ pub fn as_absolute_path<P: AsRef<Path>>(path: P) -> Result<String> {
#[derive(Debug, Clone)]
#[allow(dead_code)]
pub enum OnMove {
Commit(String),
Files(PathBuf),
Filer(PathBuf),
History(PathBuf),
Expand Down Expand Up @@ -55,8 +56,7 @@ impl OnMove {
}
"filer" => unreachable!("filer has been handled ahead"),
"proj_tags" => {
let (lnum, p) =
extract_proj_tags(&curline).context("Couldn't extract proj tags")?;
let (lnum, p) = extract_proj_tags(&curline).context("can not extract proj tags")?;
let mut path: PathBuf = context.cwd.clone().into();
path.push(&p);
Self::ProjTags { path, lnum }
Expand All @@ -69,16 +69,20 @@ impl OnMove {
Self::Grep { path, lnum }
}
"blines" => {
let lnum = extract_blines_lnum(&curline).context("Couldn't extract buffer lnum")?;
let lnum = extract_blines_lnum(&curline).context("can not extract buffer lnum")?;
let path = context.start_buffer_path.clone().into();
Self::BLines { path, lnum }
}
"tags" => {
let lnum =
extract_buf_tags_lnum(&curline).context("Couldn't extract buffer tags")?;
extract_buf_tags_lnum(&curline).context("can not extract buffer tags")?;
let path = context.start_buffer_path.clone().into();
Self::BufferTags { path, lnum }
}
"commits" | "bcommits" => {
let rev = parse_rev(&curline).context("can not extract rev")?;
Self::Commit(rev.into())
}
_ => {
return Err(anyhow!(
"Couldn't constructs a OnMove instance, context: {:?}",
Expand All @@ -91,15 +95,16 @@ impl OnMove {
}
}

pub struct OnMoveHandler {
pub struct OnMoveHandler<'a> {
pub msg_id: u64,
pub provider_id: ProviderId,
pub size: usize,
pub inner: OnMove,
pub context: &'a SessionContext,
}

impl OnMoveHandler {
pub fn try_new(msg: Message, context: &SessionContext) -> anyhow::Result<Self> {
impl<'a> OnMoveHandler<'a> {
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 All @@ -109,13 +114,15 @@ impl OnMoveHandler {
msg_id,
size: provider_id.get_preview_size(),
provider_id,
context,
inner: OnMove::Filer(path),
});
}
Ok(Self {
msg_id,
size: provider_id.get_preview_size(),
provider_id,
context,
inner: OnMove::new(curline, context)?,
})
}
Expand All @@ -136,6 +143,9 @@ impl OnMoveHandler {
Files(path) | Filer(path) | History(path) => {
self.preview_file(&path)?;
}
Commit(rev) => {
self.show_commit(rev)?;
}
}

Ok(())
Expand All @@ -150,6 +160,20 @@ impl OnMoveHandler {
}));
}

fn show_commit(&self, rev: &str) -> Result<()> {
let stdout = self.context.execute(&format!("git show {}", rev))?;
let stdout_str = String::from_utf8_lossy(&stdout);
let lines = stdout_str
.split('\n')
.take(self.provider_id.get_preview_size() * 2)
.collect::<Vec<_>>();
self.send_response(json!({
"event": "on_move",
"lines": lines,
}));
Ok(())
}

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
4 changes: 3 additions & 1 deletion crates/stdio_server/src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,8 @@ impl Message {
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub struct ProviderId(String);

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

impl ProviderId {
pub fn as_str(&self) -> &str {
&self.0
Expand All @@ -118,7 +120,7 @@ impl ProviderId {
/// Returns true if the provider can have icon.
#[inline]
pub fn has_icon_support(&self) -> bool {
&self.0 != "blines"
!NO_ICON_PROVIDERS.contains(&self.as_str())
}
}

Expand Down
31 changes: 31 additions & 0 deletions crates/utility/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,12 @@

use anyhow::{anyhow, Result};
use std::collections::hash_map::DefaultHasher;
use std::ffi::OsStr;
use std::fs::{read_dir, remove_dir_all, remove_file, DirEntry, File};
use std::hash::{Hash, Hasher};
use std::io::{self, BufRead};
use std::path::{Path, PathBuf};
use std::process::{Command, Output};

pub const CLAP_CACHE: &str = "vim.clap";

Expand Down Expand Up @@ -124,6 +126,35 @@ pub fn read_preview_lines<P: AsRef<Path>>(
))
}

/// Converts `shell_cmd` to `Command` with optional working directory.
pub fn as_std_command<P: AsRef<Path>>(shell_cmd: impl AsRef<OsStr>, dir: Option<P>) -> Command {
let mut cmd = if cfg!(target_os = "windows") {
let mut cmd = Command::new("cmd");
cmd.arg("/C").arg(shell_cmd.as_ref());
cmd
} else {
let mut cmd = Command::new("bash");
cmd.arg("-c").arg(shell_cmd.as_ref());
cmd
};

if let Some(d) = dir {
cmd.current_dir(d);
}

cmd
}

/// Executes the `shell_cmd` and returns the output.
pub fn execute_at<S, P>(shell_cmd: S, dir: Option<P>) -> Result<Output>
where
S: AsRef<OsStr>,
P: AsRef<Path>,
{
let mut cmd = as_std_command(shell_cmd, dir);
Ok(cmd.output()?)
}

/// Combine json and println macro.
#[macro_export]
macro_rules! println_json {
Expand Down

0 comments on commit 1c56d8a

Please sign in to comment.