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

feat: add Grapple.find #114

Merged
merged 4 commits into from
Mar 11, 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
81 changes: 53 additions & 28 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ Plug "cbochs/grapple.nvim"
Note, these examples assume you are using the [lazy.nvim](https://github.com/folke/lazy.nvim) package manager.

<details>
<summary>Recommended</summary>
<summary><b>Recommended</b></summary>

```lua
{
Expand All @@ -138,7 +138,7 @@ Note, these examples assume you are using the [lazy.nvim](https://github.com/fol
</details>

<details>
<summary>Harpoon</summary>
<summary><b>Harpoon</b></summary>

Example configuration similar to [harpoon.nvim](https://github.com/ThePrimeagen/harpoon) (based off of this [example setup](https://github.com/ThePrimeagen/harpoon/tree/harpoon2?tab=readme-ov-file#basic-setup)).

Expand Down Expand Up @@ -168,7 +168,7 @@ Example configuration similar to [harpoon.nvim](https://github.com/ThePrimeagen/
</details>

<details>
<summary>Arrow</summary>
<summary><b>Arrow</b></summary>

Example configuration similar to [arrow.nvim](https://github.com/otavioschwanck/arrow.nvim/tree/master).

Expand Down Expand Up @@ -411,31 +411,6 @@ require("grapple").select({ index = 3 })

</details>

#### `Grapple.exists`

Return if a tag exists. Used for statusline components

**API**: `require("grapple").exists(opts)`

**`returns`**: `boolean`

**`opts?`**: [`grapple.options`](#grappleoptions) (one of)

**Note**: Tag is searched based on one of (in order): `index`, `name`, `path`, `buffer`

<details>
<summary><b>Examples</b></summary>

```lua
-- Check whether the current buffer is tagged or not
require("grapple").exists()

-- Check for a tag in a different scope
require("grapple").exists({ scope = "global" })
```

</details>

#### `Grapple.cycle`

Cycle through and select the next or previous available tag for a given scope.
Expand Down Expand Up @@ -519,6 +494,56 @@ require("grapple").quickfix("global")

</details>

#### `Grapple.exists`

Return if a tag exists. Used for statusline components

**API**: `require("grapple").exists(opts)`

**`returns`**: `boolean`

**`opts?`**: [`grapple.options`](#grappleoptions) (one of)

**Note**: Tag is searched based on one of (in order): `index`, `name`, `path`, `buffer`

<details>
<summary><b>Examples</b></summary>

```lua
-- Check whether the current buffer is tagged or not
require("grapple").exists()

-- Check for a tag in a different scope
require("grapple").exists({ scope = "global" })
```

</details>

#### `Grapple.find`

Search for a tag in a given scope.

**API**: `require("grapple").find(opts)`

**`returns`**: [`grapple.tag`](#grapple-tag) | `nil`, `string?` error

**`opts?`**: [`grapple.options`](#grappleoptions) (one of)

**Note**: Tag is searched based on one of (in order): `index`, `name`, `path`, `buffer`

<details>
<summary><b>Examples</b></summary>

```lua
-- Search for a tag by index in the current scope
require("grapple").find({ index = 1 })

-- Search for a named tag in a different scope
require("grapple").find({ name = "bob", scope = "global" })
```

</details>

</details>

### Scope API
Expand Down
40 changes: 30 additions & 10 deletions lua/grapple.lua
Original file line number Diff line number Diff line change
Expand Up @@ -245,37 +245,55 @@ function Grapple.cycle(direction, opts)
end)
end

---Return if a tag exists. Used for statusline components
---Search for a tag in a given scope
---@param opts? grapple.options
function Grapple.exists(opts)
---@return grapple.tag | nil, string? error
function Grapple.find(opts)
local App = require("grapple.app")
local app = App.get()

opts = opts or {}

local exists = false
local app = App.get()
app:enter_without_save(opts.scope, function(container)
---@type grapple.tag | nil
local tag

local err = app:enter_without_save(opts.scope, function(container)
local path, _ = extract_path(opts)
opts.path = path

exists = container:has(opts)
end)
local index, err = container:find(opts)
if not index then
return err
end

tag = assert(container:get({ index = index }))
end, { notify = false })

if err then
return nil, err
end

return exists
return tag, nil
end

---Return if a tag exists. Used for statusline components
---@param opts? grapple.options
function Grapple.exists(opts)
return Grapple.find(opts) ~= nil
end

---Return the name or index of a tag. Used for statusline components
---@param opts? grapple.options
---@return string | integer | nil
function Grapple.name_or_index(opts)
local App = require("grapple.app")
local app = App.get()

opts = opts or {}

---@type string | integer | nil
local name_or_index

local app = App.get()
app:enter_without_save(opts.scope, function(container)
local path, _ = extract_path(opts)
opts.path = path
Expand Down Expand Up @@ -308,6 +326,7 @@ end
function Grapple.statusline()
local App = require("grapple.app")
local app = App.get()

local icon = app.settings.icons and "󰛢 " or ""

local key = Grapple.name_or_index()
Expand All @@ -321,10 +340,10 @@ end
---@return grapple.tag[] | nil, string? error
function Grapple.tags(opts)
local App = require("grapple.app")
local app = App.get()

opts = opts or {}

local app = App.get()
local scope, err = app.scope_manager:get_resolved(opts.scope or app.settings.scope)
if not scope then
return nil, err
Expand Down Expand Up @@ -603,6 +622,7 @@ function Grapple.initialize()
local excluded_subcmds = {
"define_scope",
"exists",
"find",
"initialize",
"key",
"name_or_index",
Expand Down
46 changes: 32 additions & 14 deletions lua/grapple/app.lua
Original file line number Diff line number Diff line change
Expand Up @@ -130,32 +130,50 @@ function App:reset(opts)
end

---@param scope_name? string
---@param callback fun(container: grapple.tag_container): string?
---@param opts { sync: boolean }
---@param callback fun(container: grapple.tag_container): string? error
---@param opts { sync?: boolean, notify?: boolean }
---@return string? error
function App:enter(scope_name, callback, opts)
opts = vim.tbl_extend("keep", opts or {}, {
sync = true,
notify = true,
})

local scope, err = self.scope_manager:get_resolved(scope_name or self.settings.scope)
if not scope then
---@diagnostic disable-next-line: param-type-mismatch
return vim.notify(err, vim.log.levels.ERROR)
if opts.notify then
---@diagnostic disable-next-line: param-type-mismatch
vim.notify(err, vim.log.levels.ERROR)
end
return err
end

---@diagnostic disable-next-line: redefined-local
local err = scope:enter(callback, opts)
local err = scope:enter(callback, { sync = opts.sync })
if err then
vim.notify(err, vim.log.levels.WARN)
if opts.notify then
vim.notify(err, vim.log.levels.WARN)
end
return err
end

return nil
end

---@return grapple.resolved_scope | nil, string? error
---@param callback fun(container: grapple.tag_container): string?
function App:enter_with_save(scope_name, callback)
self:enter(scope_name, callback, { sync = true })
---@param scope_name? string
---@param callback fun(container: grapple.tag_container): string? error
---@param opts? { notify?: boolean }
---@return string? error
function App:enter_with_save(scope_name, callback, opts)
return self:enter(scope_name, callback, { sync = true, notify = opts and opts.notify })
end

---@return grapple.resolved_scope | nil, string? error
---@param callback fun(container: grapple.tag_container): string?
function App:enter_without_save(scope_name, callback)
self:enter(scope_name, callback, { sync = false })
---@param scope_name? string
---@param callback fun(container: grapple.tag_container): string? error
---@param opts? { notify?: boolean }
---@return string? error
function App:enter_without_save(scope_name, callback, opts)
return self:enter(scope_name, callback, { sync = false, notify = opts and opts.notify })
end

return App
1 change: 0 additions & 1 deletion lua/grapple/settings.lua
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
---@class grapple.settings
---@field inner grapple.settings
local Settings = {}

---@class grapple.settings
Expand Down