Skip to content

Commit

Permalink
Add icon support for proj_tags (#461)
Browse files Browse the repository at this point in the history
* Add icon support for proj_tags

* Fix forerunner tags icon painter

* Update CHANGELOG.md

* Evaluate clap#builtin_providers lazily

* Skip sending on_move request if curline is empty

* .

* Fix test

* .

* Avoid triggering on_typed hook when relaunching provider

* .
  • Loading branch information
liuchengxu committed Jun 8, 2020
1 parent b6f3723 commit 387eff6
Show file tree
Hide file tree
Showing 18 changed files with 179 additions and 24 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 @@ CHANGELOG
### Added

- Implement async preview for `blines`, `tags` and `proj_tags` provider. ([#457](https://github.com/liuchengxu/vim-clap/pull/457))
- Add icon support for `proj_tags` provider. ([#461](https://github.com/liuchengxu/vim-clap/pull/461))
- Add `g:clap_preview_size` for configuring the number of preview lines. ([#444](https://github.com/liuchengxu/vim-clap/pull/444))
- Add `g:clap_provider_buffers_cur_tab_only`. ([#439](https://github.com/liuchengxu/vim-clap/pull/439))

Expand Down
25 changes: 20 additions & 5 deletions autoload/clap.vim
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,8 @@ if !s:has_features
endif

let s:cur_dir = fnamemodify(resolve(expand('<sfile>:p')), ':h')
let s:builtin_providers = map(
\ split(globpath(s:cur_dir.'/clap/provider', '*'), '\n'),
\ 'fnamemodify(v:val, '':t:r'')'
\ )

let g:clap#autoload_dir = s:cur_dir
let g:clap#builtin_providers = s:builtin_providers

let g:__t_func = 0
let g:__t_string = 1
Expand Down Expand Up @@ -87,6 +82,16 @@ let g:clap_multi_selection_warning_silent = get(g:, 'clap_multi_selection_warnin

let g:clap_popup_border = get(g:, 'clap_popup_border', 'rounded')

function! clap#builtin_providers() abort
if !exists('s:builtin_providers')
let s:builtin_providers = map(
\ split(globpath(s:cur_dir.'/clap/provider', '*'), '\n'),
\ 'fnamemodify(v:val, '':t:r'')'
\ )
endif
return s:builtin_providers
endfunction

function! s:inject_default_impl_is_ok(provider_info) abort
let provider_info = a:provider_info

Expand Down Expand Up @@ -280,7 +285,17 @@ function! clap#for(provider_id_or_alias) abort

call clap#selection#init()

" This flag is used to slience the autocmd events for NeoVim, e.g., on_typed.
" Vim doesn't have these issues as it uses noautocmd in most cases.
"
" Without this flag, the on_typed hook can be triggered when relaunching
" some provider. To reproduce:
" 1. :Clap
" 2. Choose proj_tags
" 3. proj_tags ontyped hook will be triggered.
let g:__clap_open_win_pre = v:true
call g:clap.open_win()
let g:__clap_open_win_pre = v:false
endfunction

if !exists('g:clap')
Expand Down
5 changes: 4 additions & 1 deletion autoload/clap/api.vim
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ function! clap#api#has_externalfilter() abort
\ || has_key(g:clap.context, 'externalfilter')
endfunction

let s:has_no_icons = ['blines', 'proj_tags']
let s:has_no_icons = ['blines']

" Returns the original full line with icon if g:clap_enable_icon is on given
" the lnum of display buffer.
Expand Down Expand Up @@ -341,6 +341,9 @@ function! s:init_provider() abort

" After you have typed something
function! provider.on_typed() abort
if get(g:, '__clap_open_win_pre', v:false)
return
endif
try
call self._().on_typed()
catch
Expand Down
3 changes: 3 additions & 0 deletions autoload/clap/client.vim
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,9 @@ let s:should_send_source_fpath = ['tags', 'blines']
function! clap#client#send_request_on_move() abort
let s:req_id += 1
let curline = g:clap.display.getcurline()
if empty(curline)
return
endif
let msg = {
\ 'id': s:req_id,
\ 'session_id': s:session_id,
Expand Down
3 changes: 1 addition & 2 deletions autoload/clap/debugging.vim
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ function! s:get_global_variables() abort
call filter(variable_list, 'v:val !~# ''^clap#icon#''')
call filter(variable_list, 'v:val !~# ''clap#floating_win''')
call filter(variable_list, 'v:val !~# ''clap#display_win''')
call filter(variable_list, 'v:val !~# ''clap#builtin_providers''')
call filter(variable_list, 'v:val !~# ''clap#themes#''')

call sort(variable_list)
Expand All @@ -31,7 +30,7 @@ endfunction

function! s:get_third_party_providers() abort
let all_providers = split(globpath(&runtimepath, 'autoload/clap/provider/*.vim'), "\n")
let third_party_providers = filter(all_providers, 'index(g:clap#builtin_providers, v:val) != -1')
let third_party_providers = filter(all_providers, 'index(clap#builtin_providers(), v:val) != -1')
return third_party_providers
endfunction

Expand Down
10 changes: 8 additions & 2 deletions autoload/clap/filter/async/dyn.vim
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,14 @@ endfunction
function! clap#filter#async#dyn#from_tempfile(tempfile) abort
let s:last_query = g:clap.input.get()

if g:clap_enable_icon && index(['files', 'git_files'], g:clap.provider.id) > -1
let enable_icon_opt = ['--icon-painter=File']
if g:clap_enable_icon
if index(['files', 'git_files'], g:clap.provider.id) > -1
let enable_icon_opt = ['--icon-painter=File']
elseif 'proj_tags' ==# g:clap.provider.id
let enable_icon_opt = ['--icon-painter=ProjTags']
else
let enable_icon_opt = []
endif
else
let enable_icon_opt = []
endif
Expand Down
5 changes: 5 additions & 0 deletions autoload/clap/maple.vim
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,11 @@ endfunction

function! clap#maple#tags_forerunner_command() abort
let global_opt = has_key(g:clap.context, 'no-cache') ? ['--no-cache'] : []

if g:clap_enable_icon
call add(global_opt, '--icon-painter=ProjTags')
endif

return [s:maple_bin] + global_opt + ['tags', '', clap#rooter#working_dir(), '--forerunner']
endfunction

Expand Down
38 changes: 38 additions & 0 deletions crates/icon/src/constants.rs
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,44 @@ pub static EXACTMATCH_ICON_TABLE: &[(&str, char)] = &[
("readme", ''),
("rust-toolchain", ''),
];
pub static TAGKIND_ICON_TABLE: &[(&str, char)] = &[
("augroup", 'פּ'),
("class", ''),
("const", ''),
("constant", ''),
("default", ''),
("enum", ''),
("enumerator", ''),
("field", ''),
("fields", ''),
("func", ''),
("function", ''),
("functions", ''),
("implementation", ''),
("interface", ''),
("macro", ''),
("macros", ''),
("map", 'פּ'),
("member", ''),
("method", ''),
("module", ''),
("modules", ''),
("namespace", ''),
("package", ''),
("packages", ''),
("property", '襁'),
("struct", ''),
("subroutine", '羚'),
("target", ''),
("type", ''),
("typeParameter", ''),
("typedef", ''),
("types", ''),
("union", '鬒'),
("var", ''),
("variable", ''),
("variables", ''),
];

pub fn bsearch_icon_table(c: &str, table: &[(&str, char)]) -> Option<usize> {
table.binary_search_by(|&(key, _)| key.cmp(&c)).ok()
Expand Down
22 changes: 21 additions & 1 deletion crates/icon/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
mod constants;

pub use constants::{bsearch_icon_table, EXACTMATCH_ICON_TABLE, EXTENSION_ICON_TABLE};
pub use constants::*;

use std::path::Path;
use structopt::clap::arg_enum;
Expand Down Expand Up @@ -62,6 +62,14 @@ pub fn prepend_filer_icon(path: &Path, line: &str) -> String {
format!("{} {}", icon_for_filer(path), line)
}

fn get_tagkind_icon(line: &str) -> Icon {
pattern::extract_proj_tags_kind(line)
.and_then(|kind| {
bsearch_icon_table(kind, TAGKIND_ICON_TABLE).map(|idx| TAGKIND_ICON_TABLE[idx].1)
})
.unwrap_or(DEFAULT_ICON)
}

#[inline]
fn grep_icon_for(line: &str) -> Icon {
pattern::extract_fpath_from_grep_line(line)
Expand All @@ -80,6 +88,7 @@ arg_enum! {
pub enum IconPainter {
File,
Grep,
ProjTags
}
}

Expand All @@ -89,6 +98,7 @@ impl IconPainter {
match *self {
Self::File => prepend_icon(raw_str),
Self::Grep => prepend_grep_icon(raw_str),
Self::ProjTags => format!("{} {}", get_tagkind_icon(raw_str), raw_str),
}
}

Expand All @@ -97,6 +107,7 @@ impl IconPainter {
match *self {
Self::File => icon_for(text),
Self::Grep => grep_icon_for(text),
Self::ProjTags => get_tagkind_icon(text),
}
}
}
Expand All @@ -121,4 +132,13 @@ mod tests {
}
}
}

#[test]
fn test_tagkind_icon() {
let line = r#"Blines:19 [implementation@crates/maple_cli/src/cmd/blines.rs] impl Blines {"#;
let icon_for = |kind: &str| {
bsearch_icon_table(kind, TAGKIND_ICON_TABLE).map(|idx| TAGKIND_ICON_TABLE[idx].1)
};
assert_eq!(icon_for("implementation").unwrap(), get_tagkind_icon(line));
}
}
38 changes: 38 additions & 0 deletions crates/icon/tagkind_map.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
{
"func": "\uf794",
"function": "\uf794",
"functions": "\uf794",
"var": "\uf71b",
"variable": "\uf71b",
"variables": "\uf71b",
"const": "\uf888",
"constant": "\uf888",
"method": "\uf6a6",
"package": "\ue612",
"packages": "\ue612",
"enum": "\uf702",
"enumerator": "\uf702",
"module": "\uf136",
"modules": "\uf136",
"type": "\uf7fd",
"typedef": "\uf7fd",
"types": "\uf7fd",
"field": "\uf30b",
"fields": "\uf30b",
"macro": "\uf8a3",
"macros": "\uf8a3",
"map": "\ufb44",
"class": "\uf0e8",
"augroup": "\ufb44",
"struct": "\uf318",
"union": "\ufacd",
"member": "\uf02b",
"target": "\uf893",
"property": "\ufab6",
"interface": "\uf7fe",
"namespace": "\uf475",
"subroutine": "\uf9af",
"implementation": "\uf776",
"typeParameter": "\uf278",
"default": "\uf29c"
}
9 changes: 9 additions & 0 deletions crates/icon/update_constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,15 @@
lines.append('pub static EXACTMATCH_ICON_TABLE: &[(&str, char)] = &[%s];' %
joined_tuples)

with open('tagkind_map.json', 'r') as f:
disordered = json.load(f)
sorted_dict = {k: disordered[k] for k in sorted(disordered)}

joined_tuples = ','.join(
map(lambda kv: '("%s", \'%s\')' % (kv[0], kv[1]), sorted_dict.items()))
lines.append('pub static TAGKIND_ICON_TABLE: &[(&str, char)] = &[%s];' %
joined_tuples)

lines.append('''
pub fn bsearch_icon_table(c: &str, table: &[(&str, char)]) ->Option<usize> {
table.binary_search_by(|&(key, _)| key.cmp(&c)).ok()
Expand Down
2 changes: 1 addition & 1 deletion crates/maple_cli/src/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ impl Maple {
match self.command {
Cmd::Version | Cmd::Upgrade(_) => unreachable!(),
Cmd::Helptags(helptags) => helptags.run()?,
Cmd::Tags(tags) => tags.run(self.no_cache)?,
Cmd::Tags(tags) => tags.run(self.no_cache, self.icon_painter)?,
Cmd::RPC => {
stdio_server::run_forever(std::io::BufReader::new(std::io::stdin()));
}
Expand Down
12 changes: 9 additions & 3 deletions crates/maple_cli/src/cmd/tags.rs
Original file line number Diff line number Diff line change
Expand Up @@ -97,14 +97,20 @@ fn create_tags_cache(args: &[&str], dir: &PathBuf) -> Result<(PathBuf, usize)> {
}

impl Tags {
pub fn run(&self, no_cache: bool) -> Result<()> {
pub fn run(&self, no_cache: bool, icon_painter: Option<icon::IconPainter>) -> Result<()> {
// In case of passing an invalid icon-painter option.
let icon_painter = icon_painter.map(|_| icon::IconPainter::ProjTags);

let mut cmd_args = BASE_TAGS_ARGS.to_vec();

let lang = if let Some(ref languages) = self.languages {
format!("--languages={}", languages)
} else {
String::from("")
};

cmd_args.push(&lang);

if self.forerunner {
let (cache, total) = if no_cache {
create_tags_cache(&cmd_args, &self.dir)?
Expand All @@ -113,7 +119,7 @@ impl Tags {
} else {
create_tags_cache(&cmd_args, &self.dir)?
};
send_response_from_cache(&cache, total, SendResponse::Json, None);
send_response_from_cache(&cache, total, SendResponse::Json, icon_painter);
return Ok(());
} else {
crate::cmd::filter::dynamic::dyn_fuzzy_filter_and_rank(
Expand All @@ -122,7 +128,7 @@ impl Tags {
None,
Some(30),
None,
None,
icon_painter,
LineSplitter::TagNameOnly,
)?;
}
Expand Down
6 changes: 6 additions & 0 deletions crates/pattern/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,12 @@ pub fn extract_proj_tags(line: &str) -> Option<(usize, &str)> {
Some((lnum, fpath))
}

pub fn extract_proj_tags_kind(line: &str) -> Option<&str> {
let cap = PROJ_TAGS.captures(line)?;
let kind = cap.get(3).map(|x| x.as_str())?;
Some(kind)
}

pub fn extract_buf_tags_lnum(line: &str) -> Option<usize> {
let cap = BUFFER_TAGS.captures(line)?;
cap.get(1)
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 @@ -48,7 +48,7 @@ pub fn initialize_global(msg: Message) {
}

pub fn has_icon_support(provider_id: &str) -> bool {
provider_id != "proj_tags" && provider_id != "blines"
provider_id != "blines"
}

pub fn should_skip_leading_icon(provider_id: &str) -> bool {
Expand Down
4 changes: 3 additions & 1 deletion crates/upgrade/src/github.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
use super::{REPO, USER};
use anyhow::{anyhow, Result};
use curl::easy::{Easy, List};
use serde::{Deserialize, Serialize};

const USER: &str = "liuchengxu";
const REPO: &str = "vim-clap";

#[derive(Serialize, Deserialize, Debug)]
pub struct RemoteRelease {
pub tag_name: String,
Expand Down
3 changes: 0 additions & 3 deletions crates/upgrade/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,6 @@ mod github;
use anyhow::{anyhow, Context, Result};
use structopt::StructOpt;

const USER: &str = "liuchengxu";
const REPO: &str = "vim-clap";

/// This command is only invoked when user uses the prebuilt binary, more specifically, exe in
/// vim-clap/bin/maple.
#[derive(StructOpt, Debug, Clone)]
Expand Down
Loading

0 comments on commit 387eff6

Please sign in to comment.