Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,7 @@ require('opencode').setup({
completion = {
file_sources = {
enabled = true,
preferred_cli_tool = 'fd', -- 'fd','fdfind','rg','git' if nil, it will use the best available tool
preferred_cli_tool = 'server', -- 'fd','fdfind','rg','git','server' if nil, it will use the best available tool, 'server' uses opencode cli to get file list (works cross platform) and supports folders
ignore_patterns = {
'^%.git/',
'^%.svn/',
Expand Down
2 changes: 1 addition & 1 deletion lua/opencode/config.lua
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ M.defaults = {
completion = {
file_sources = {
enabled = true,
preferred_cli_tool = 'fd',
preferred_cli_tool = 'server',
ignore_patterns = {
'^%.git/',
'^%.svn/',
Expand Down
4 changes: 3 additions & 1 deletion lua/opencode/context.lua
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,9 @@ function M.add_file(file)
M.context.mentioned_files = {}
end

if vim.fn.filereadable(file) ~= 1 then
local is_file = vim.fn.filereadable(file) == 1
local is_dir = vim.fn.isdirectory(file) == 1
if not is_file and not is_dir then
vim.notify('File not added to context. Could not read.')
return
end
Expand Down
14 changes: 10 additions & 4 deletions lua/opencode/ui/completion/engines/blink_cmp.lua
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,12 @@ function Source:get_trigger_characters()
local mention_key = config.get_key_for_function('input_window', 'mention')
local slash_key = config.get_key_for_function('input_window', 'slash_commands')
local triggers = {}
if mention_key then table.insert(triggers, mention_key) end
if slash_key then table.insert(triggers, slash_key) end
if mention_key then
table.insert(triggers, mention_key)
end
if slash_key then
table.insert(triggers, slash_key)
end
return triggers
end

Expand Down Expand Up @@ -48,13 +52,15 @@ function Source:get_completions(ctx, callback)
local items = {}
for _, completion_source in ipairs(completion_sources) do
local source_items = completion_source.complete(context)
for _, item in ipairs(source_items) do
for i, item in ipairs(source_items) do
table.insert(items, {
label = item.label,
kind = item.kind == 'file' and 17 or 1, -- 17: File, 1: Text
kind = item.kind == 'file' and 17 or item.kind == 'folder' and 19 or 1, -- 17: File, 19: Folder, 1: Text
detail = item.detail,
documentation = item.documentation,
insertText = item.insert_text or item.label,
sortText = string.format('%02d_%02d_%s', completion_source.priority or 999, i, item.label),
score_offset = -(completion_source.priority or 999) * 1000,
data = {
original_item = item,
},
Expand Down
14 changes: 10 additions & 4 deletions lua/opencode/ui/completion/engines/nvim_cmp.lua
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,12 @@ function M.setup(completion_sources)
local mention_key = config.get_key_for_function('input_window', 'mention')
local slash_key = config.get_key_for_function('input_window', 'slash_commands')
local triggers = {}
if mention_key then table.insert(triggers, mention_key) end
if slash_key then table.insert(triggers, slash_key) end
if mention_key then
table.insert(triggers, mention_key)
end
if slash_key then
table.insert(triggers, slash_key)
end
return triggers
end

Expand Down Expand Up @@ -51,11 +55,13 @@ function M.setup(completion_sources)
for j, item in ipairs(source_items) do
table.insert(items, {
label = item.label,
kind = item.kind == 'file' and cmp.lsp.CompletionItemKind.File or cmp.lsp.CompletionItemKind.Text,
kind = item.kind == 'file' and cmp.lsp.CompletionItemKind.File
or item.kind == 'folder' and cmp.lsp.CompletionItemKind.Folder
or cmp.lsp.CompletionItemKind.Text,
detail = item.detail,
documentation = item.documentation,
insertText = item.insert_text or item.label,
sortText = string.format('%03d_%03d_%s', i, j, item.label),
sortText = string.format('%02d_%02d_%s', completion_source.priority or 999, j, item.label),
data = {
original_item = item,
},
Expand Down
45 changes: 31 additions & 14 deletions lua/opencode/ui/completion/files.lua
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,17 @@ local function run_systemlist(cmd)
end

local function try_tool(tool, args, pattern, max, ignore_patterns)
if type(args) == 'function' then
local promise = args(pattern, max)
local result = promise and promise.and_then and promise:wait()

if result and type(result) == 'table' then
return vim.tbl_filter(should_keep(ignore_patterns), result)
end
end

if vim.fn.executable(tool) then
pattern = vim.fn.shellescape(pattern) or '.'
local result = run_systemlist(tool .. string.format(args, pattern, max))
if result then
return vim.tbl_filter(should_keep(ignore_patterns), result)
Expand All @@ -32,18 +42,20 @@ end
---@param pattern string
---@return string[]
local function find_files_fast(pattern)
pattern = vim.fn.shellescape(pattern) or '.'
local file_config = config.ui.completion.file_sources
local cli_tool = last_successful_tool or file_config.preferred_cli_tool or 'fd'
local cli_tool = last_successful_tool or file_config.preferred_cli_tool or 'server'
local max = file_config.max_files or 10
local ignore_patterns = file_config.ignore_patterns or {}

local tools_order = { 'fd', 'fdfind', 'rg', 'git' }
local tools_order = { 'server', 'fd', 'fdfind', 'rg', 'git' }
local commands = {
fd = ' --type f --type l --full-path --color=never -E .git -E node_modules -i %s --max-results %d 2>/dev/null',
fdfind = ' --type f --type l --color=never -E .git -E node_modules --full-path -i %s --max-results %d 2>/dev/null',
rg = ' --files --no-messages --color=never | grep -i %s 2>/dev/null | head -%d',
git = ' ls-files --cached --others --exclude-standard | grep -i %s | head -%d',
server = function(pattern)
return require('opencode.state').api_client:find_files(pattern)
end,
}

if cli_tool and commands[cli_tool] then
Expand All @@ -66,7 +78,7 @@ end

---@param file string
---@return CompletionItem
local function create_file_item(file)
local function create_file_item(file, suffix)
local filename = vim.fn.fnamemodify(file, ':t')
local dir = vim.fn.fnamemodify(file, ':h')
local file_path = dir == '.' and filename or dir .. '/' .. filename
Expand All @@ -79,10 +91,10 @@ local function create_file_item(file)
if #display_label > max_display_len then
display_label = '...' .. display_label:sub(-(max_display_len - 3))
end

local kind = vim.endswith(file, '/') and 'folder' or 'file'
return {
label = display_label,
kind = 'file',
label = display_label .. (suffix or ''),
kind = kind,
detail = detail,
documentation = 'Path: ' .. detail,
insert_text = file_path,
Expand All @@ -94,7 +106,7 @@ end
---@type CompletionSource
local file_source = {
name = 'files',
priority = 0,
priority = 5,
complete = function(context)
local sort_util = require('opencode.ui.completion.sort')
local file_config = config.ui.completion.file_sources
Expand Down Expand Up @@ -134,12 +146,17 @@ local file_source = {
---Get the list of recent files
---@return CompletionItem[]
function M.get_recent_files()
local project = require('opencode.config_file').get_opencode_project()
local max = config.ui.completion.file_sources.max_files
local is_git = project and project.vcs == 'git'

local recent_files = is_git and M.get_git_changed_files() or M.get_old_files() or {}
return vim.tbl_map(create_file_item, { unpack(recent_files, 1, max) })
local api_client = require('opencode.state').api_client

local result = api_client:get_file_status():wait()
local recent_files = {}
if result then
for _, file in ipairs(result) do
local suffix = table.concat({ file.added and '+' .. file.added, file.removed and '-' .. file.removed }, ' ')
table.insert(recent_files, create_file_item(file.path, ' ' .. suffix))
end
end
return recent_files
end

---Get the list of old files in the current working directory
Expand Down
1 change: 1 addition & 0 deletions lua/opencode/ui/completion/subagents.lua
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ local M = {}
---@type CompletionSource
local subagent_source = {
name = 'subagents',
priority = 1,
complete = function(context)
local subagents = require('opencode.config_file').get_subagents()
local config = require('opencode.config')
Expand Down