Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor(completion)!: Extract sources to separate classes and remove nvim-compe support #678

Merged
merged 1 commit into from
Feb 21, 2024
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
9 changes: 0 additions & 9 deletions DOCS.md
Original file line number Diff line number Diff line change
Expand Up @@ -1248,15 +1248,6 @@ By default, `omnifunc` is provided in `org` files that autocompletes these types
* Orgfile special keywords (`#+TITLE`, `#+BEGIN_SRC`, `#+ARCHIVE`, etc.)
* Hyperlinks (`* - headlines`, `# - headlines with CUSTOM_ID property`, `headlines matching title`)

If you use [nvim-compe](https://github.com/hrsh7th/nvim-compe) add this to compe setup:
```lua
require'compe'.setup({
source = {
orgmode = true
}
})
```

For [nvim-cmp](https://github.com/hrsh7th/nvim-cmp), add `orgmode` to list of sources:
```lua
require'cmp'.setup({
Expand Down
14 changes: 0 additions & 14 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -132,20 +132,6 @@ EOF
```
#### Completion

<details>
<summary><a href="https://github.com/hrsh7th/nvim-compe"><b>nvim-compe</b></a></summary>
</br>

```lua
require('compe').setup({
source = {
orgmode = true
}
})
```

</details>

<details>
<summary><a href="https://github.com/hrsh7th/nvim-cmp"><b>nvim-cmp</b></a></summary>
</br>
Expand Down
2 changes: 1 addition & 1 deletion ftplugin/org.lua
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ vim.opt_local.omnifunc = 'v:lua.orgmode.omnifunc'
vim.opt_local.commentstring = '# %s'

_G.orgmode.omnifunc = function(findstart, base)
return require('orgmode.org.autocompletion.omni').omnifunc(findstart, base)
return require('orgmode').completion:omnifunc(findstart, base)
end

local abbreviations = {
Expand Down
4 changes: 3 additions & 1 deletion lua/orgmode/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ local auto_instance_keys = {
clock = true,
org_mappings = true,
notifications = true,
completion = true,
}

---@class Org
Expand All @@ -20,6 +21,7 @@ local auto_instance_keys = {
---@field agenda OrgAgenda
---@field capture OrgCapture
---@field clock OrgClock
---@field completion OrgCompletion
---@field org_mappings OrgMappings
---@field notifications OrgNotifications
local Org = {}
Expand Down Expand Up @@ -62,7 +64,7 @@ function Org:init()
self.clock = require('orgmode.clock'):new({
files = self.files,
})
require('orgmode.org.autocompletion').register()
self.completion = require('orgmode.org.autocompletion'):new({ files = self.files })
self.statusline_debounced = require('orgmode.utils').debounce('statusline', function()
return self.clock:get_statusline()
end, 300)
Expand Down
42 changes: 29 additions & 13 deletions lua/orgmode/objects/url.lua
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,10 @@ local fs = require('orgmode.utils.fs')
---@class OrgUrl
---@field str string
local Url = {}

function Url:init(str)
self.str = str
end
Url.__index = Url

function Url.new(str)
local self = setmetatable({}, { __index = Url })
self:init(str)
return self
return setmetatable({ str = str }, Url)
end

---@return boolean
Expand Down Expand Up @@ -44,11 +39,6 @@ function Url:is_file_custom_id()
return self:is_file() and self:get_custom_id() and true or false
end

---@return boolean
function Url:is_file_anchor()
return self:get_dedicated_target() and true
end

---@return boolean
function Url:is_org_link()
return (self:get_dedicated_target() or self:get_custom_id() or self:get_headline()) and true
Expand Down Expand Up @@ -77,7 +67,7 @@ function Url:is_internal_custom_id()
end

function Url:is_dedicated_anchor_or_internal_title()
return self:get_dedicated_target() ~= nil
return self:get_dedicated_target()
end

---@return string | false
Expand Down Expand Up @@ -145,6 +135,11 @@ function Url:get_linenumber()
or self.str:match('^/[^:]+ %+(%d+)$')
end

---@return string | false
function Url:get_protocol()
return self.str:match('^([%w]+):')
end

---@return string | false
function Url:get_filepath()
return
Expand All @@ -166,6 +161,27 @@ function Url:get_filepath()
or self.str:match('^(%./)$')
or self.str:match('^(/)$')
end

function Url:get_file()
return
-- for backwards compatibility
self.str:match('^(file:[^:]+) %+%d+')
or self.str:match('^(%.%./[^:]+) %+%d+')
or self.str:match('^(%./[^:]+) %+%d+')
or self.str:match('^(/[^:]+) %+%d+')
-- official orgmode convention
or self.str:match('^(file:[^:]+)::')
or self.str:match('^(%.%./[^:]+)::')
or self.str:match('^(%./[^:]+)::')
or self.str:match('^(/[^:]+)::')
or self.str:match('^(file:[^:]+)$')
or self.str:match('^(%.%./[^:]+)$')
or self.str:match('^(%./[^:]+)$')
or self.str:match('^(/[^:]+)$')
or self.str:match('^(%.%./)$')
or self.str:match('^(%./)$')
or self.str:match('^(/)$')
end
--
---@return string
function Url:get_headline_completion()
Expand Down
9 changes: 9 additions & 0 deletions lua/orgmode/org/autocompletion/_meta.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
---@meta

---@alias OrgCompletionContext { line: string, base?: string }
---@alias OrgCompletionItem { word: string, menu: string }

---@class OrgCompletionSource
---@field get_name fun(self: OrgCompletionSource): string
---@field get_start fun(self: OrgCompletionSource, context: OrgCompletionContext): number | nil
---@field get_results fun(self: OrgCompletionSource, context: OrgCompletionContext): string[]
11 changes: 7 additions & 4 deletions lua/orgmode/org/autocompletion/cmp.lua
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ if not has_cmp then
return
end

local Omni = require('orgmode.org.autocompletion.omni')
local org = require('orgmode')

local Source = {}

Expand All @@ -25,9 +25,12 @@ function Source:get_trigger_characters(_)
end

function Source:complete(params, callback)
local offset = Omni.find_start() + 1
local input = string.sub(params.context.cursor_before_line, offset)
local results = Omni.get_completions(input)
local offset = org.completion:get_start({ line = params.context.cursor_before_line }) + 1
local base = string.sub(params.context.cursor_before_line, offset)
local results = org.completion:complete({
line = params.context.cursor_before_line,
base = base,
})
local items = {}
for _, item in ipairs(results) do
table.insert(items, {
Expand Down
42 changes: 0 additions & 42 deletions lua/orgmode/org/autocompletion/compe.lua

This file was deleted.

109 changes: 104 additions & 5 deletions lua/orgmode/org/autocompletion/init.lua
Original file line number Diff line number Diff line change
@@ -1,8 +1,107 @@
local function register()
require('orgmode.org.autocompletion.compe')
---@class OrgCompletion
---@field files OrgFiles
---@field private sources OrgCompletionSource[]
---@field private sources_by_name table<string, OrgCompletionSource>
---@field menu string
local OrgCompletion = {
menu = '[Org]',
}
OrgCompletion.__index = OrgCompletion

---@param opts { files: OrgFiles }
function OrgCompletion:new(opts)
local this = setmetatable({
files = opts.files,
sources = {},
sources_by_name = {},
}, OrgCompletion)
this:setup_builtin_sources()
this:register_frameworks()
return this
end

function OrgCompletion:setup_builtin_sources()
self:add_source(require('orgmode.org.autocompletion.sources.todo_keywords'):new())
self:add_source(require('orgmode.org.autocompletion.sources.tags'):new({ completion = self }))
self:add_source(require('orgmode.org.autocompletion.sources.plan'):new({ completion = self }))
self:add_source(require('orgmode.org.autocompletion.sources.directives'):new())
self:add_source(require('orgmode.org.autocompletion.sources.properties'):new({ completion = self }))
self:add_source(require('orgmode.org.autocompletion.sources.hyperlinks'):new({ completion = self }))
end

---@param source OrgCompletionSource
function OrgCompletion:add_source(source)
if self.sources_by_name[source:get_name()] then
error('Completion source ' .. source:get_name() .. ' already exists')
end
self.sources_by_name[source:get_name()] = source
table.insert(self.sources, source)
end

---@param context OrgCompletionContext
---@return OrgCompletionItem
function OrgCompletion:complete(context)
local results = {}
for _, source in ipairs(self.sources) do
if source:get_start(context) then
vim.list_extend(results, self:_get_valid_results(source:get_results(context), context))
end
end

return results
end

function OrgCompletion:_get_valid_results(results, context)
local base = context.base or ''

local valid_results = {}
for _, item in ipairs(results) do
if base == '' or item:find('^' .. vim.pesc(base)) then
table.insert(valid_results, {
word = item,
menu = self.menu,
})
end
end

return valid_results
end

---@param context OrgCompletionContext
function OrgCompletion:get_start(context)
for _, source in ipairs(self.sources) do
local start = source:get_start(context)
if start then
return start
end
end

return -1
end

function OrgCompletion:omnifunc(findstart, base)
if findstart == 1 then
self._context = { line = self:get_line() }
return self:get_start(self._context)
end

self._context = self._context or { line = self:get_line() }
self._context.base = base
return self:complete(self._context)
end

function OrgCompletion:get_line()
local cursor = vim.api.nvim_win_get_cursor(0)
return vim.api.nvim_get_current_line():sub(1, cursor[2])
end

---@param line string
function OrgCompletion:is_headline_line(line)
return line:find([[^%*+%s+]]) ~= nil
end

function OrgCompletion:register_frameworks()
require('orgmode.org.autocompletion.cmp')
end

return {
register = register,
}
return OrgCompletion
Loading
Loading