or run

tessl search
Log in

Version

Workspace
tessl
Visibility
Public
Created
Last updated
Describes
npmpkg:npm/coc.nvim@0.0.x

docs

index.md
tile.json

tessl/npm-coc-nvim

tessl install tessl/npm-coc-nvim@0.0.0

LSP based intellisense engine for neovim & vim8.

search.mddocs/reference/

Workspace Search [Intermediate]

Complexity: Intermediate | Category: Reference | Keywords: search, grep, ripgrep, find, workspace

Common Tasks: Search codebase | Find patterns | Search by filetype | Context search | Save results

Workspace-wide code search with ripgrep integration. Search across your entire project with powerful filtering and context options.

Table of Contents

  • Common Tasks
  • Commands
  • Configuration
  • Usage Examples
  • Error Handling
  • Troubleshooting
  • See Also

Common Tasks

Basic Search

:CocSearch TODO

Search for pattern across workspace.

Search with File Filter

:CocSearch --glob '*.js' import

Search only in JavaScript files.

Case Insensitive Search

:CocSearch -i error

Search ignoring case.

Search Word Under Cursor

nnoremap <leader>sw :exe 'CocSearch '.expand('<cword>')<CR>

Quick search for word at cursor.

Interactive Grep

:CocList grep

Open fuzzy-searchable grep interface.

Commands

:CocSearch

:CocSearch [options] {pattern}

Search workspace for pattern using ripgrep.

Parameters:

  • pattern - Pattern to search for (required)

Options:

  • -e, --regexp PATTERN - Use regexp pattern (default)
  • -F, --fixed-strings - Use fixed string matching (literal)
  • -w, --word-regexp - Match whole words only
  • -S, --smart-case - Smart case matching (case insensitive unless pattern has uppercase)
  • -i, --ignore-case - Case insensitive search
  • -s, --case-sensitive - Case sensitive matching
  • -g, --glob PATTERN - Include files matching glob pattern
  • --hidden - Search hidden files and directories
  • --no-ignore - Don't respect .gitignore and other ignore files
  • -x, --context NUM - Show NUM lines of context around matches
  • -A, --after-context NUM - Show NUM lines after each match
  • -B, --before-context NUM - Show NUM lines before each match

Returns: Opens search results in quickfix or location list

Example:

" Basic search
:CocSearch TODO

" Whole word search
:CocSearch -w function

" Case insensitive
:CocSearch -i error

" Search with glob
:CocSearch --glob '*.js' import

" Search with context
:CocSearch -A 3 -B 3 error

" Search hidden files
:CocSearch --hidden config

" Multiple globs
:CocSearch --glob '*.{js,ts}' export

Advanced Usage:

" Regex search
:CocSearch -e 'function \w+\('

" Fixed string (escape special chars)
:CocSearch -F 'import * from'

" Smart case (case insensitive unless uppercase present)
:CocSearch -S Pattern

" Exclude files
:CocSearch --glob '!*.test.js' function

" Search in specific directory
:CocSearch --glob 'src/**/*.ts' interface

:CocList grep

:CocList grep [pattern]

Interactive grep interface with fuzzy matching and preview.

Parameters:

  • pattern - Initial search pattern (optional)

Features:

  • Fuzzy matching of search results
  • Live preview of matches
  • Interactive filtering
  • Quick navigation

Example:

" Open grep list
:CocList grep

" Grep with initial pattern
:CocList grep TODO

" Grep word under cursor
:exe 'CocList --input='.expand('<cword>').' grep'

" Grep in normal mode (non-interactive start)
:CocList --normal grep

Keybindings in List:

  • <Tab> - Select/deselect item
  • <C-s> - Open in split
  • <C-v> - Open in vertical split
  • <C-t> - Open in new tab
  • <C-p> / <C-n> - Navigate up/down
  • <Esc> - Exit list

Configuration

Configure search behavior in coc-settings.json:

{
  "list.source.grep.command": "rg",
  "list.source.grep.args": [
    "--color", "never",
    "--line-number",
    "--smart-case",
    "--no-heading"
  ],
  "list.source.grep.defaultArgs": [],
  "search.followSymlinks": true
}

Settings:

list.source.grep.command

  • Type: string
  • Default: "rg"
  • Description: Grep command to use (ripgrep recommended)

list.source.grep.args

  • Type: array<string>
  • Default: ["--color", "never", "--line-number", "--smart-case", "--no-heading"]
  • Description: Default arguments for grep command

list.source.grep.defaultArgs

  • Type: array<string>
  • Default: []
  • Description: Additional default arguments

search.followSymlinks

  • Type: boolean
  • Default: true
  • Description: Follow symbolic links when searching

Example Configuration:

{
  "list.source.grep.command": "rg",
  "list.source.grep.args": [
    "--color", "never",
    "--line-number",
    "--smart-case",
    "--no-heading",
    "--hidden",
    "--glob", "!.git/*"
  ],
  "search.followSymlinks": true
}

Usage Examples

Search Mappings

Common search mappings:

" Search word under cursor
nnoremap <leader>sw :exe 'CocSearch '.expand('<cword>')<CR>

" Search visual selection
vnoremap <leader>sw :<C-u>call <SID>SearchVisual()<CR>

function! s:SearchVisual() abort
  let saved = @"
  normal! gvy
  let pattern = escape(@", '\')
  let @" = saved
  execute 'CocSearch ' . pattern
endfunction

" Interactive grep
nnoremap <leader>fg :CocList grep<CR>

" Grep word under cursor interactively
nnoremap <leader>fw :exe 'CocList --input='.expand('<cword>').' grep'<CR>

" Search in current buffer
nnoremap <leader>fb :exe 'CocList --input='.bufname('%').' grep'<CR>

Search by Filetype

Helper functions for filetype-specific search:

function! SearchInFileType(pattern, filetype) abort
  let glob = '*.' . a:filetype
  execute 'CocSearch --glob ' . shellescape(glob) . ' ' . shellescape(a:pattern)
endfunction

" Define commands for common filetypes
command! -nargs=+ SearchJS call SearchInFileType(<f-args>, 'js')
command! -nargs=+ SearchTS call SearchInFileType(<f-args>, 'ts')
command! -nargs=+ SearchPY call SearchInFileType(<f-args>, 'py')
command! -nargs=+ SearchRB call SearchInFileType(<f-args>, 'rb')
command! -nargs=+ SearchGO call SearchInFileType(<f-args>, 'go')

" Usage:
" :SearchJS import
" :SearchPY class

Search with Context

Show surrounding lines:

" Show 3 lines before and after matches
:CocSearch -A 3 -B 3 error

" Show 5 lines of context
:CocSearch -x 5 TODO

" Search with custom context mapping
nnoremap <leader>sc :call <SID>SearchWithContext()<CR>

function! s:SearchWithContext() abort
  let pattern = input('Search: ')
  if empty(pattern)
    return
  endif

  let context = input('Context lines [3]: ')
  let context = empty(context) ? 3 : str2nr(context)

  execute printf('CocSearch -A %d -B %d %s', context, context, shellescape(pattern))
endfunction

Search Exclusions

Exclude files and directories:

function! SearchExclude(pattern, ...) abort
  let cmd = 'CocSearch'

  " Add exclusion globs
  for exclude in a:000
    let cmd .= ' --glob !' . shellescape(exclude)
  endfor

  let cmd .= ' ' . shellescape(a:pattern)
  execute cmd
endfunction

command! -nargs=+ SearchExclude call SearchExclude(<f-args>)

" Usage:
" :SearchExclude TODO '*.min.js' 'node_modules/**' 'dist/**'

" Common exclusions function
function! SearchClean(pattern) abort
  call SearchExclude(a:pattern,
    \ '*.min.js',
    \ '*.min.css',
    \ 'node_modules/**',
    \ 'dist/**',
    \ 'build/**',
    \ '.git/**'
    \ )
endfunction

command! -nargs=1 SearchClean call SearchClean(<q-args>)

Regex Search

Advanced pattern matching:

" Search for pattern with regex
function! RegexSearch(pattern) abort
  execute 'CocSearch -e ' . shellescape(a:pattern)
endfunction

command! -nargs=1 RgxSearch call RegexSearch(<q-args>)

" Examples:
" :RgxSearch 'function \w+\('
" :RgxSearch 'class \w+ extends'
" :RgxSearch 'import.*from'

" Common patterns
command! SearchFunctions RgxSearch 'function \w+\s*\('
command! SearchClasses RgxSearch 'class \w+'
command! SearchImports RgxSearch 'import.*from'
command! SearchTODOs RgxSearch 'TODO|FIXME|HACK|XXX|NOTE'

Multi-Pattern Search

Search for multiple patterns:

function! SearchMultiple(...) abort
  let results = {}

  for pattern in a:000
    let output = system('rg --count ' . shellescape(pattern))
    let count = 0

    for line in split(output, '\n')
      let parts = split(line, ':')
      if len(parts) >= 2
        let count += str2nr(parts[-1])
      endif
    endfor

    let results[pattern] = count
  endfor

  echo '=== Search Results ==='
  for [pattern, count] in items(results)
    echo pattern . ': ' . count . ' occurrences'
  endfor
endfunction

command! -nargs=+ MultiSearch call SearchMultiple(<f-args>)

" Usage:
" :MultiSearch TODO FIXME HACK

Search Statistics

Count occurrences and file statistics:

function! CountSearchResults(pattern) abort
  let output = system('rg --count ' . shellescape(a:pattern))
  let lines = split(output, '\n')
  let total = 0
  let files = 0

  for line in lines
    let parts = split(line, ':')
    if len(parts) >= 2
      let count = str2nr(parts[-1])
      if count > 0
        let total += count
        let files += 1
      endif
    endif
  endfor

  echo printf('Found %d occurrences in %d files', total, files)
endfunction

command! -nargs=1 SearchCount call CountSearchResults(<q-args>)

" Search statistics by file type
function! SearchStatsByType(pattern) abort
  let types = ['js', 'ts', 'py', 'rb', 'go', 'java', 'c', 'cpp']
  let results = {}

  echo 'Counting...'
  for type in types
    let cmd = 'rg --type ' . type . ' --count ' . shellescape(a:pattern)
    let output = system(cmd)
    let count = 0

    for line in split(output, '\n')
      let parts = split(line, ':')
      if len(parts) >= 2
        let count += str2nr(parts[-1])
      endif
    endfor

    if count > 0
      let results[type] = count
    endif
  endfor

  echo '=== Results by File Type ==='
  for [type, count] in items(results)
    echo type . ': ' . count . ' occurrences'
  endfor
endfunction

command! -nargs=1 SearchStats call SearchStatsByType(<q-args>)

Search History

Track recent searches:

let g:search_history = []

function! AddToSearchHistory(pattern) abort
  " Don't add duplicates
  let idx = index(g:search_history, a:pattern)
  if idx >= 0
    call remove(g:search_history, idx)
  endif

  call insert(g:search_history, a:pattern)

  " Keep only last 20 searches
  if len(g:search_history) > 20
    call remove(g:search_history, 20, -1)
  endif
endfunction

function! ShowSearchHistory() abort
  if len(g:search_history) == 0
    echo 'No search history'
    return
  endif

  echo '=== Recent Searches ==='
  for i in range(len(g:search_history))
    echo (i + 1) . '. ' . g:search_history[i]
  endfor
endfunction

command! SearchHistory call ShowSearchHistory()

" Repeat last search
function! RepeatLastSearch() abort
  if len(g:search_history) == 0
    echo 'No previous search'
    return
  endif

  execute 'CocSearch ' . shellescape(g:search_history[0])
endfunction

command! SearchRepeat call RepeatLastSearch()
nnoremap <leader>sr :SearchRepeat<CR>

" Track CocSearch commands
autocmd CmdlineLeave : if getcmdtype() ==# ':' && getcmdline() =~# '^CocSearch' |
  \ let pattern = matchstr(getcmdline(), 'CocSearch\s\+\zs.*') |
  \ if !empty(pattern) | call AddToSearchHistory(pattern) | endif |
  \ endif

Search in Git Changes

Search only in modified files:

function! SearchInGitModified(pattern) abort
  let files = system('git diff --name-only')
  let file_list = join(split(files, '\n'), ' ')

  if empty(file_list)
    echo 'No modified files'
    return
  endif

  execute '!rg ' . shellescape(a:pattern) . ' ' . file_list
endfunction

command! -nargs=1 SearchModified call SearchInGitModified(<q-args>)

" Search in git staged files
function! SearchInGitStaged(pattern) abort
  let files = system('git diff --cached --name-only')
  let file_list = join(split(files, '\n'), ' ')

  if empty(file_list)
    echo 'No staged files'
    return
  endif

  execute '!rg ' . shellescape(a:pattern) . ' ' . file_list
endfunction

command! -nargs=1 SearchStaged call SearchInGitStaged(<q-args>)

Save Search Results

Export search results to file:

function! SaveSearchResults(pattern, filename) abort
  let output = system('rg ' . shellescape(a:pattern))

  if v:shell_error != 0
    echohl ErrorMsg
    echo 'Search failed or no results found'
    echohl None
    return
  endif

  call writefile(split(output, '\n'), a:filename)
  echo 'Search results saved to ' . a:filename
endfunction

command! -nargs=+ SaveSearch call SaveSearchResults(<f-args>)

" Usage:
" :SaveSearch TODO todo-list.txt

" Save with timestamp
function! SaveSearchWithTimestamp(pattern) abort
  let timestamp = strftime('%Y%m%d_%H%M%S')
  let filename = 'search_' . timestamp . '.txt'
  call SaveSearchResults(a:pattern, filename)
endfunction

command! -nargs=1 SaveSearchTS call SaveSearchWithTimestamp(<q-args>)

Context-Aware Search

Search based on current context:

function! ContextSearch(pattern) abort
  let ft = &filetype
  let globs = {
    \ 'javascript': '*.{js,jsx}',
    \ 'typescript': '*.{ts,tsx}',
    \ 'python': '*.py',
    \ 'ruby': '*.rb',
    \ 'go': '*.go',
    \ 'rust': '*.rs',
    \ 'java': '*.java'
    \ }

  if has_key(globs, ft)
    execute 'CocSearch --glob ' . shellescape(globs[ft]) . ' ' . shellescape(a:pattern)
  else
    execute 'CocSearch ' . shellescape(a:pattern)
  endif
endfunction

command! -nargs=1 CtxSearch call ContextSearch(<q-args>)

" Map to context search word under cursor
nnoremap <leader>cs :exe 'CtxSearch '.expand('<cword>')<CR>

Search TODO Comments

Find all TODO markers:

function! SearchTODOs() abort
  execute 'CocSearch -w "TODO\|FIXME\|HACK\|XXX\|NOTE\|BUG"'
endfunction

command! SearchTODOs call SearchTODOs()
nnoremap <leader>st :SearchTODOs<CR>

" By author
function! SearchTODOsByAuthor(author) abort
  let pattern = printf('TODO.*%s\|FIXME.*%s', a:author, a:author)
  execute 'CocSearch -e ' . shellescape(pattern)
endfunction

command! -nargs=1 SearchMyTODOs call SearchTODOsByAuthor(<q-args>)

Error Handling

Check Ripgrep Installation

Verify ripgrep is available:

function! CheckRipgrep() abort
  if !executable('rg')
    echohl ErrorMsg
    echo 'Error: ripgrep (rg) not found in PATH'
    echo 'Install from: https://github.com/BurntSushi/ripgrep'
    echohl None
    return 0
  endif
  return 1
endfunction

" Check before searching
function! SafeSearch(pattern) abort
  if !CheckRipgrep()
    return
  endif
  execute 'CocSearch ' . shellescape(a:pattern)
endfunction

Handle Empty Results

Check for empty results:

function! SearchWithFeedback(pattern) abort
  execute 'CocSearch ' . shellescape(a:pattern)

  " Check if results found
  let qflist = getqflist()
  if empty(qflist)
    echohl WarningMsg
    echo 'No matches found for: ' . a:pattern
    echohl None
  else
    echo 'Found ' . len(qflist) . ' matches'
  endif
endfunction

Validate Patterns

Check pattern is valid:

function! ValidatedSearch(pattern) abort
  if empty(a:pattern)
    echohl ErrorMsg
    echo 'Error: empty search pattern'
    echohl None
    return
  endif

  " Check for problematic patterns
  if a:pattern =~# '^\s*$'
    echohl ErrorMsg
    echo 'Error: pattern is only whitespace'
    echohl None
    return
  endif

  execute 'CocSearch ' . shellescape(a:pattern)
endfunction

Troubleshooting

Problem: Ripgrep Not Found

Problem: :CocSearch fails with command not found.

Solutions:

  1. Install ripgrep:

    # macOS
    brew install ripgrep
    
    # Ubuntu/Debian
    sudo apt install ripgrep
    
    # Windows
    choco install ripgrep
  2. Verify installation:

    :!rg --version
  3. Check PATH:

    :echo $PATH

Problem: Search Not Finding Files

Problem: Search doesn't find expected files.

Solutions:

  1. Check .gitignore:

    " Search hidden/ignored files
    :CocSearch --hidden --no-ignore pattern
  2. Verify glob pattern:

    " Test glob
    :CocSearch --glob '*.js' import
  3. Check file permissions:

    # Ensure files are readable
    ls -la

Problem: Too Many Results

Problem: Search returns overwhelming number of results.

Solutions:

  1. Use more specific patterns:

    " Whole word only
    :CocSearch -w pattern
    
    " Add context to pattern
    :CocSearch 'import.*component'
  2. Exclude directories:

    :CocSearch --glob '!node_modules/**' --glob '!dist/**' pattern
  3. Use file type filters:

    :CocSearch --glob '*.js' pattern

Problem: Slow Search

Problem: Search takes too long in large codebases.

Solutions:

  1. Exclude build artifacts:

    {
      "list.source.grep.args": [
        "--glob", "!node_modules/**",
        "--glob", "!dist/**",
        "--glob", "!build/**",
        "--glob", "!*.min.js"
      ]
    }
  2. Use .ignore file:

    # Create .ignore in project root
    echo "node_modules/" >> .ignore
    echo "dist/" >> .ignore
  3. Search specific directories:

    :CocSearch --glob 'src/**/*.js' pattern

Problem: Regex Not Working

Problem: Regex patterns don't match as expected.

Solutions:

  1. Use -e flag explicitly:

    :CocSearch -e 'pattern.*with.*regex'
  2. Escape special characters:

    :CocSearch 'import \* from'
  3. Test regex with ripgrep directly:

    rg -e 'your.*pattern'

Problem: Case Sensitivity Issues

Problem: Search doesn't respect case preferences.

Solutions:

  1. Use smart case:

    :CocSearch -S pattern
  2. Force case insensitive:

    :CocSearch -i pattern
  3. Configure default in settings:

    {
      "list.source.grep.args": [
        "--smart-case"
      ]
    }

See Also

  • List Interface - Fuzzy finder and grep interface
  • Code Navigation - Symbol-based navigation
  • Workspace - Workspace operations
  • Symbols - Symbol search