Skip to content

Instantly share code, notes, and snippets.

@girishji
Created March 10, 2024 14:36
Show Gist options
  • Save girishji/e4dbcb61c1f7292eb884799bc3251b26 to your computer and use it in GitHub Desktop.
Save girishji/e4dbcb61c1f7292eb884799bc3251b26 to your computer and use it in GitHub Desktop.
Async list update with fuzzy search in scope.vim

Here is a representative example of asynchronous list update, and fuzzy searching on the items using scope.vim.

This example spawns a job to obtain a list of files using fd command. Output of fd command is checked every 100ms.

import autoload 'scope/task.vim'
import autoload 'scope/popup.vim'

# Helper function: Filter a list of files using fuzzy matching on typed string
# 'lst' represents a list of all files where each list entry is a dict of 
#   the form {text: filename}
# 'prompt' string is what the user typed so far
def FilterItems(lst: list<dict<any>>, prompt: string): list<any>   
    if prompt->empty()
        # when nothing is typed display all files in the popup window
        return [lst, [lst]]
    else
        var pat = prompt->trim()
        var matches = lst->matchfuzzypos(pat, {key: "text", limit: 1000})
        # return both the original list and filtered list
        return [lst, matches]
    endif
enddef

def FindFile()
    # create the popup object
    var menu: popup.FilterMenu
    menu = popup.FilterMenu.new("File", [],
        (res, key) => {        
            exe $"e {res.text}"
        },
        null_function,
        FilterItems)
        
    # create async job object
    var job: task.AsyncCmd
    job = task.AsyncCmd.new('fd -tf --follow'->split(),
        (items: list<string>) => {
            # this function is called periodically as new file names are received
            if menu.Closed()
                job.Stop()
            endif
            var items_dict: list<dict<any>> = items->mapnew((_, v) => {
                    return {text: v}
                })
            if !menu.SetText(items_dict, FilterItems, 10000)  # stop after 10000 files (for example)
                job.Stop()
            endif
        })
enddef
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment