1
0
mirror of https://github.com/SpaceVim/SpaceVim.git synced 2025-02-02 23:00:04 +08:00

Improve cscope layer (#4418)

This commit is contained in:
Wang Shidong 2021-08-22 14:35:22 +08:00 committed by GitHub
parent 938ad16611
commit 5c8e9ac781
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 201 additions and 158 deletions

View File

@ -21,6 +21,7 @@ scriptencoding utf-8
let s:self = {}
let s:self._json = SpaceVim#api#import('data#json')
let s:self._string = SpaceVim#api#import('data#string')
let s:self.box_width = 40
" http://jrgraphix.net/r/Unicode/2500-257F
" http://www.alanflavell.org.uk/unicode/unidata.html
@ -58,16 +59,16 @@ function! s:self.drawing_table(json, ...) abort
let items = self._json.json_decode(a:json)
let col = len(keys(items[0]))
let top_line = top_left_corner
\ . repeat(repeat(top_bottom_side, 15) . top_middle, col - 1)
\ . repeat(top_bottom_side, 15)
\ . repeat(repeat(top_bottom_side, self.box_width) . top_middle, col - 1)
\ . repeat(top_bottom_side, self.box_width)
\ . top_right_corner
let middle_line = left_middle
\ . repeat(repeat(top_bottom_side, 15) . middle, col - 1)
\ . repeat(top_bottom_side, 15)
\ . repeat(repeat(top_bottom_side, self.box_width) . middle, col - 1)
\ . repeat(top_bottom_side, self.box_width)
\ . right_middle
let bottom_line = bottom_left_corner
\ . repeat(repeat(top_bottom_side, 15) . bottom_middle, col - 1)
\ . repeat(top_bottom_side, 15)
\ . repeat(repeat(top_bottom_side, self.box_width) . bottom_middle, col - 1)
\ . repeat(top_bottom_side, self.box_width)
\ . bottom_right_corner
call add(table, top_line)
let tytle = side
@ -77,14 +78,14 @@ function! s:self.drawing_table(json, ...) abort
let keys = a:1
endif
for key in keys
let tytle .= self._string.fill(key , 15) . side
let tytle .= self._string.fill_middle(key , self.box_width) . side
endfor
call add(table, tytle)
call add(table, middle_line)
for item in items
let value_line = side
for key in keys
let value_line .= self._string.fill(item[key], 15) . side
let value_line .= self._string.fill(item[key], self.box_width) . side
endfor
call add(table, value_line)
call add(table, middle_line)

View File

@ -38,3 +38,29 @@ function! SpaceVim#layers#cscope#health() abort
call SpaceVim#layers#cscope#config()
return 1
endfunction
function! SpaceVim#layers#cscope#set_variable(var) abort
let g:cscope_cmd = get(a:var,
\ 'cscope_command',
\ 'cscope')
let g:cscope_auto_update = get(a:var,
\ 'auto_update',
\ 1)
let g:cscope_open_location = get(a:var,
\ 'open_location',
\ 1)
let g:cscope_preload_path = get(a:var,
\ 'preload_path',
\ '')
endfunction
function! SpaceVim#layers#cscope#get_options() abort
return ['cscope_command',
\ 'auto_update',
\ 'open_location',
\ 'preload_path']
endfunction

View File

@ -45,19 +45,18 @@ set cpo&vim
" where to store cscope file?
function! s:echo(msg) abort
echon a:msg
endfunction
let s:logger = SpaceVim#logger#derive('cscope')
let s:notify = SpaceVim#api#import('notify')
let s:notify.timeout = 5000
let s:box = SpaceVim#api#import('unicode#box')
let s:box.box_width = 40
let s:FILE = SpaceVim#api#import('file')
let s:JOB = SpaceVim#api#import('job')
let s:JSON = SpaceVim#api#import('data#json')
let s:cscope_cache_dir = s:FILE.unify_path('~/.cache/SpaceVim/cscope/')
let s:cscope_db_index = s:cscope_cache_dir.'index'
let s:dbs = {}
""
" search your {word} with {action} in the database suitable for current
" file.
@ -65,7 +64,7 @@ function! cscope#find(action, word) abort
let dirtyDirs = []
for d in keys(s:dbs)
if s:dbs[d]['dirty'] == 1
call add(dirtyDirs, s:dbs[d].root)
call add(dirtyDirs, d)
endif
endfor
if len(dirtyDirs) > 0
@ -79,8 +78,14 @@ function! cscope#find(action, word) abort
lw
endif
catch
echohl WarningMsg | echo 'Can not find '.a:word.' with querytype as '.a:action.'.' | echohl None
let message = 'Can not find '.a:word.' with querytype as '.a:action.'.'
let s:notify.notify_max_width = strwidth(message) + 10
call s:notify.notify(message, 'WarningMsg')
endtry
elseif dbl == 2 " the database does not init, the process has been started.
let message = 'start to init database, please try later!'
let s:notify.notify_max_width = strwidth(message) + 10
call s:notify.notify(message, 'WarningMsg')
endif
endfunction
@ -93,8 +98,8 @@ endfunction
function! s:CheckNewFile(dir, newfile) abort
let id = s:dbs[a:dir]['id']
let dir = s:FILE.path_to_fname(a:dir)
let id = s:dbs[dir]['id']
let cscope_files = s:cscope_cache_dir. dir .'/cscope.files'
let files = readfile(cscope_files)
" @todo support threshold
@ -117,41 +122,52 @@ function! s:FlushIndex() abort
endfunction
function! s:ListFiles(dir) abort
let d = []
let f = []
let cwd = a:dir
try
while cwd != ''
let a = split(globpath(cwd, '*'), "\n")
for fn in a
if getftype(fn) ==# 'dir'
if !exists('g:cscope_ignored_dir') || fn !~? g:cscope_ignored_dir
call add(d, fn)
endif
elseif getftype(fn) !=# 'file'
continue
else
if stridx(fn, ' ') !=# -1
let fn = '"'.fn.'"'
endif
call add(f, fn)
endif
endfor
let cwd = len(d) ? remove(d, 0) : ''
endwhile
catch /^Vim:Interrupt$/
catch
echo 'caught' v:exception
endtry
return f
function! s:on_list_file_exit(id, date, event) abort
endfunction
let s:list_files_process = {}
function! s:list_files_stdout(id, data, event) abort
call extend(s:list_files_process['jobid' . a:id].cscope_files, a:data)
endfunction
function! s:list_files_exit(id, date, event) abort
if a:date == 0
call writefile(s:list_files_process['jobid' . a:id].cscope_files,
\ s:list_files_process['jobid' . a:id].cscope_files_path
\ )
call s:run_create_database_job(s:list_files_process['jobid' . a:id].dir,
\ s:list_files_process['jobid' . a:id].cscope_files_path,
\ s:list_files_process['jobid' . a:id].cscope_db,
\ s:list_files_process['jobid' . a:id].load,
\ )
else
call s:logger.warn('failed to list files in dir:' . s:list_files_process['jobid' . a:id].dir)
endif
endfunction
function! s:list_project_files(dir, cscope_files, cscope_db, load) abort
let jobid = s:JOB.start(['rg', '--color=never', '--files', a:dir], {
\ 'on_stdout' : function('s:list_files_stdout'),
\ 'on_exit' : function('s:list_files_exit')
\ })
let s:list_files_process['jobid' . jobid] = {
\ 'jobid' : jobid,
\ 'dir' : a:dir,
\ 'cscope_files' : [],
\ 'cscope_db' : a:cscope_db,
\ 'load' : a:load,
\ 'cscope_files_path' : a:cscope_files
\ }
endfunction
""
" update all existing cscope databases in case that you disable cscope database
" auto update.
function! cscope#update_databeses() abort
call s:updateDBs(map(keys(s:dbs), 's:dbs[v:val].root'))
call s:updateDBs(keys(s:dbs))
endfunction
@ -159,12 +175,13 @@ endfunction
" Create databases for current project
function! cscope#create_databeses() abort
let dir = SpaceVim#plugins#projectmanager#current_root()
call s:InitDB(dir)
call s:init_database(dir, 0)
endfunction
" 0 -- loaded
" 1 -- cancelled
" 2 -- init db
function! s:AutoloadDB(dir) abort
let ret = 0
let m_dir = s:GetBestPath(a:dir)
@ -173,8 +190,8 @@ function! s:AutoloadDB(dir) abort
let m_dir = input('', a:dir, 'dir')
if m_dir !=# ''
let m_dir = s:CheckAbsolutePath(m_dir, a:dir)
call s:InitDB(m_dir)
call s:LoadDB(m_dir)
call s:init_database(m_dir, 1)
let ret = 2
else
let ret = 1
endif
@ -189,9 +206,8 @@ endfunction
function! s:updateDBs(dirs) abort
for d in a:dirs
call s:CreateDB(d, 0)
call s:create_database(d, 0, 0)
endfor
call s:FlushIndex()
endfunction
@ -201,21 +217,24 @@ function! cscope#clear_databases(...) abort
silent cs kill -1
if a:0 == 0
let s:dbs = {}
call s:notify.notify('All databases cleared!', 'String')
call s:RmDBfiles()
else
let dir = s:FILE.path_to_fname(a:1)
let id = s:dbs[dir]['id']
call delete(s:cscope_cache_dir. dir . '/cscope.files')
call delete(s:cscope_cache_dir. dir . '/cscope.db')
unlet s:dbs[dir]
call s:echo('database cleared: ' . s:cscope_cache_dir. dir .'/cscope.db')
unlet s:dbs[a:1]
let message = 'databases cleared:' . a:1
let s:notify.notify_max_width = strwidth(message) + 10
call s:notify.notify(message, 'WarningMsg')
call s:logger.info('database cleared: ' . s:cscope_cache_dir. dir .'/cscope.db')
call s:FlushIndex()
endif
endfunction
" complete function for command :CscopeClear
function! cscope#listDirs(A,L,P) abort
return map(keys(s:dbs), 's:dbs[v:val].root')
return keys(s:dbs)
endfunction
function! ToggleLocationList() abort
@ -234,11 +253,11 @@ function! ToggleLocationList() abort
endfunction
function! s:GetBestPath(dir) abort
let f = s:FILE.path_to_fname(a:dir)
let f = a:dir
let bestDir = ''
for d in keys(s:dbs)
if stridx(f, d) == 0 && len(d) > len(bestDir)
return s:dbs[d].root
return d
endif
endfor
return ''
@ -268,24 +287,27 @@ endfunction
" 2. loadtimes:
" 3. dirty:
" 4. root: path of the project
"
" the argv: dir, load?
"
" if load == 1, the database will be loaded after init
function! s:InitDB(dir) abort
function! s:init_database(dir, load) abort
call s:logger.debug('start to init database for:' . a:dir)
let id = localtime()
let dir = s:FILE.path_to_fname(a:dir)
let s:dbs[dir] = {}
let s:dbs[dir]['id'] = id
let s:dbs[dir]['loadtimes'] = 0
let s:dbs[dir]['dirty'] = 0
let s:dbs[dir]['root'] = a:dir
call s:CreateDB(a:dir, 1)
call s:FlushIndex()
let s:dbs[a:dir] = {}
let s:dbs[a:dir]['id'] = id
let s:dbs[a:dir]['loadtimes'] = 0
let s:dbs[a:dir]['dirty'] = 0
let s:dbs[a:dir]['root'] = a:dir
call s:create_database(a:dir, 1, a:load)
endfunction
function! s:add_databases(db) abort
exe 'silent cs add ' . a:db
if cscope_connection(2, a:db) == 1
call s:echo('cscope added: ' . a:db)
call s:logger.info('cscope added: ' . a:db)
return 0
else
return 1
@ -296,26 +318,35 @@ function! s:LoadDB(dir) abort
let dir = s:FILE.path_to_fname(a:dir)
silent cs kill -1
call s:add_databases(s:cscope_cache_dir . dir .'/cscope.db')
let s:dbs[dir]['loadtimes'] = s:dbs[dir]['loadtimes'] + 1
let s:dbs[a:dir]['loadtimes'] = s:dbs[a:dir]['loadtimes'] + 1
call s:FlushIndex()
endfunction
function! cscope#list_databases() abort
let dirs = keys(s:dbs)
let databases = []
if len(dirs) == 0
echo 'You have no cscope dbs now.'
call s:notify.notify('no cscope dbs now.', 'WarningMsg')
call s:notify.notify('Press SPC m c i to init.', 'WarningMsg')
else
let s = [' PROJECT_ROOT LOADTIMES']
for d in dirs
let id = s:dbs[d]['id']
if cscope_connection(2, s:cscope_cache_dir. d . '/cscope.db') == 1
let l = printf('* %s %d', s:dbs[d].root, s:dbs[d]['loadtimes'])
" let l = printf('* %s %d', s:dbs[d].root, )
let l = {
\ 'project' : '* ' .d,
\ 'loadtimes' : s:dbs[d]['loadtimes']
\ }
else
let l = printf(' %s %d', s:dbs[d].root, s:dbs[d]['loadtimes'])
let l = {
\ 'project' : ' ' .d,
\ 'loadtimes' : s:dbs[d]['loadtimes']
\ }
endif
call add(s, l)
call add(databases, l)
endfor
echo join(s, "\n")
let table = s:box.drawing_table(s:JSON.json_encode(databases), ['project', 'loadtimes'])
echo join(table, "\n")
endif
endfunction
@ -336,9 +367,8 @@ function! cscope#preloadDB() abort
let m_dir = s:CheckAbsolutePath(m_dir, m_dir)
let m_key = s:FILE.path_to_fname(m_dir)
if !has_key(s:dbs, m_key)
call s:InitDB(m_dir)
call s:init_database(m_dir, 1)
endif
call s:LoadDB(m_dir)
endfor
endfunction
@ -364,33 +394,58 @@ function! cscope#onChange() abort
endif
endfunction
function! s:CreateDB(dir, init) abort
function! s:on_create_db_exit(id, data, event) abort
let d = s:create_db_process['jobid' . a:id].dir
if a:data !=# 0
echohl WarningMsg | echo 'Failed to create cscope database for ' . d | echohl None
else
let s:dbs[d]['dirty'] = 0
let message = 'database created for: ' . d
let s:notify.notify_max_width = strwidth(message) + 10
call s:notify.notify(message, 'WarningMsg')
if s:create_db_process['jobid' . a:id].load
call s:LoadDB(d)
else
call s:FlushIndex()
endif
endif
endfunction
let s:create_db_process = {}
" argvs:
" dir: the path of project
" init: init database?
" load: load after init
function! s:create_database(dir, init, load) abort
let dir = s:FILE.path_to_fname(a:dir)
let id = s:dbs[dir]['id']
let cscope_files = s:cscope_cache_dir . dir . '/cscope.files'
let cscope_db = s:cscope_cache_dir . dir . '/cscope.db'
if ! isdirectory(s:cscope_cache_dir . dir)
call mkdir(s:cscope_cache_dir . dir)
endif
if !filereadable(cscope_files) || a:init
let files = s:ListFiles(a:dir)
call writefile(files, cscope_files)
endif
try
exec 'silent cs kill '.cscope_db
catch
endtry
let save_x = @x
redir @x
exec 'silent !'.g:cscope_cmd.' -b -i '.cscope_files.' -f'.cscope_db
redi END
if @x =~# "\nCommand terminated\n"
echohl WarningMsg | echo 'Failed to create cscope database for ' . a:dir | echohl None
else
let s:dbs[dir]['dirty'] = 0
call s:echo('database created: ' . cscope_db)
if !isdirectory(s:cscope_cache_dir . dir)
call mkdir(s:cscope_cache_dir . dir)
endif
let @x = save_x
if !filereadable(cscope_files) || a:init
call s:list_project_files(a:dir, cscope_files, cscope_db, a:load)
endif
endfunction
function! s:run_create_database_job(dir, cscope_files, cscope_db, load) abort
let jobid = s:JOB.start([g:cscope_cmd, '-b', '-i', a:cscope_files, '-f', a:cscope_db], {
\ 'on_exit' : function('s:on_create_db_exit')
\ })
let s:create_db_process['jobid' . jobid] = {
\ 'jobid' : jobid,
\ 'dir' : a:dir,
\ 'load' : a:load,
\ 'cscope_db' : a:cscope_db,
\ }
endfunction
""

View File

@ -1,35 +0,0 @@
let s:LOG = SpaceVim#api#import('logger')
call s:LOG.set_name('cscope.vim')
call s:LOG.set_level(1)
call s:LOG.set_silent(1)
call s:LOG.set_verbose(1)
function! cscope#logger#info(msg)
call s:LOG.info(a:msg)
endfunction
function! cscope#logger#view()
let info = "### cscope.vim runtime log :\n\n"
let info .= "```log\n"
let info .= s:LOG.view(s:LOG.level)
let info .= "\n```\n"
tabnew +setl\ nobuflisted
nnoremap <buffer><silent> q :bd!<CR>
for msg in split(info, "\n")
call append(line('$'), msg)
endfor
normal! "_dd
setl nomodifiable
setl buftype=nofile
setl filetype=markdown
endfunction
function! cscope#logger#clear() abort
call s:LOG.clear(1)
endfunction

View File

@ -4,10 +4,9 @@ Shidong Wang *cscope.vim*
==============================================================================
CONTENTS *cscope.vim-contents*
1. Introduction...........................................|cscope.vim-intro|
2. Configuration.........................................|cscope.vim-config|
3. Commands............................................|cscope.vim-commands|
4. KEY MAPPINGS....................................|cscope.vim-key-mappings|
5. FAQ......................................................|cscope.vim-faq|
2. Commands............................................|cscope.vim-commands|
3. KEY MAPPINGS....................................|cscope.vim-key-mappings|
4. FAQ......................................................|cscope.vim-faq|
==============================================================================
INTRODUCTION *cscope.vim-intro*
@ -34,12 +33,6 @@ database.
Cscove frees you from creating/connecting/updating cscope database, let you
focus on code browsing.
==============================================================================
CONFIGURATION *cscope.vim-config*
*g:cscope_silent*
Silent or not when run cscope command. by default it is 1.
==============================================================================
COMMANDS *cscope.vim-commands*

View File

@ -7,8 +7,6 @@
"=============================================================================
if !exists('g:cscope_silent')
""
" Silent or not when run cscope command. by default it is 1.
let g:cscope_silent = 1
endif
@ -41,7 +39,7 @@ com! -nargs=? -complete=customlist,cscope#listDirs CscopeClear call cscope#clear
" List all the cscope databases.
com! -nargs=0 CscopeList call cscope#list_databases()
if exists('g:cscope_preload_path')
if exists('g:cscope_preload_path') && !empty(g:cscope_preload_path)
call cscope#preloadDB()
endif

View File

@ -9,10 +9,10 @@ lang: zh
<!-- vim-markdown-toc GFM -->
- [模块描述](#模块描述)
- [模块特性](#模块特性)
- [安装依赖及启用模块](#安装依赖及启用模块)
- [安装 cscope](#安装-cscope)
- [启用模块](#启用模块)
- [模块选项](#模块选项)
- [快捷键](#快捷键)
<!-- vim-markdown-toc -->
@ -23,11 +23,6 @@ lang: zh
如果想要了解更多关于 cscope 和其它类似工具之间的区别,请阅读 [Comparison with Similar Tools](https://github.com/oracle/opengrok/wiki/Comparison-with-Similar-Tools)
## 模块特性
- 通过 cscope 为 C 和 C++ 建立索引,并提供查询功能
- 通过 Pycscope 为 Python 建立索引,并提供查询功能
## 安装依赖及启用模块
### 安装 cscope
@ -53,6 +48,13 @@ scoop install cscope
name = "cscope"
```
## 模块选项
- `cscope_command`: 设置 `cscope` 可执行命令的路径。
- `auto_update`: 启用/禁用数据库自动更新,若启用,则在保存文件时自动更新数据库。
- `open_location`: 启用/禁用自动打开搜索结果列表。
- `preload_path`: 设置预加载的数据量路径。
## 快捷键
| 快捷键 | 功能描述 |

View File

@ -7,26 +7,21 @@ description: "cscope layer provides a smart cscope and pycscope helper for Space
<!-- vim-markdown-toc GFM -->
- [Description](#description)
- [Features](#features)
- [Intro](#intro)
- [Install](#install)
- [cscope](#cscope)
- [layer](#layer)
- [Layer options](#layer-options)
- [Key bindings](#key-bindings)
<!-- vim-markdown-toc -->
## Description
## Intro
This layer provides a smart [Cscope](http://cscope.sourceforge.net/) and [PyCscope](https://github.com/portante/pycscope) helper for SpaceVim.
For more info about the differences between Cscope and other similar tools, please read [Comparison with Similar Tools](https://github.com/oracle/opengrok/wiki/Comparison-with-Similar-Tools)
## Features
- Tag indexing and searching for C-C++ via Cscope
- Tag indexing and searching for python via PyCscope
## Install
### cscope
@ -50,6 +45,14 @@ To use this configuration layer, add it to your configuration file.
name = "cscope"
```
## Layer options
- `cscope_command`: set the command or path of `cscope` executable.
- `auto_update`: enable/disable auto udpate when saving files.
- `open_location`: enable/disable open location list after searching.
- `preload_path`: set the proload paths.
## Key bindings
| Key Binding | Description |