Skip to content

Commit

Permalink
feat!: improve template helpers and state manager (#14)
Browse files Browse the repository at this point in the history
## 📃 Summary

While the template is still a pretty good starting point, improvements
have been made on [my main
plugin](https://github.com/shortcuts/no-neck-pain.nvim) for better
developer experience, we can port them here.
  • Loading branch information
shortcuts authored Mar 15, 2024
1 parent 0cbfb9a commit 9cc87ad
Show file tree
Hide file tree
Showing 13 changed files with 271 additions and 152 deletions.
16 changes: 8 additions & 8 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,27 +15,27 @@ jobs:
runs-on: ubuntu-latest
name: lint
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4

- uses: JohnnyMorganz/stylua-action@v2
with:
token: ${{ secrets.GITHUB_TOKEN }}
version: latest
args: --check .
args: --check . -g '*.lua' -g '!deps/'

documentation:
runs-on: ubuntu-latest
name: documentation
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
with:
fetch-depth: 2

- name: setup neovim
uses: rhysd/action-setup-vim@v1
with:
neovim: true
version: v0.8.3
version: v0.9.4

- name: generate documentation
run: make documentation-ci
Expand All @@ -51,15 +51,15 @@ jobs:
timeout-minutes: 2
strategy:
matrix:
neovim_version: ['v0.7.2', 'v0.8.3', 'v0.9.1', 'nightly']
neovim_version: ['v0.7.2', 'v0.8.3', 'v0.9.4', 'nightly']

steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4

- run: date +%F > todays-date

- name: restore cache for today's nightly.
uses: actions/cache@v3
uses: actions/cache@v4
with:
path: _neovim
key: ${{ runner.os }}-x64-${{ hashFiles('todays-date') }}
Expand All @@ -80,7 +80,7 @@ jobs:
- tests
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4

- uses: google-github-actions/release-please-action@v3
id: release
Expand Down
14 changes: 12 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,17 @@ test:
nvim --version | head -n 1 && echo ''
nvim --headless --noplugin -u ./scripts/minimal_init.lua \
-c "lua require('mini.test').setup()" \
-c "lua MiniTest.run({ execute = { reporter = MiniTest.gen_reporter.stdout({ group_depth = 1 }) } })"
-c "lua MiniTest.run({ execute = { reporter = MiniTest.gen_reporter.stdout({ group_depth = 2 }) } })"

# runs all the test files on the nightly version, `bob` must be installed.
test-nightly:
bob use nightly
make test

# runs all the test files on the 0.8.3 version, `bob` must be installed.
test-0.8.3:
bob use 0.8.3
make test

# installs `mini.nvim`, used for both the tests and documentation.
deps:
Expand All @@ -27,7 +37,7 @@ documentation-ci: deps documentation

# performs a lint check and fixes issue if possible, following the config in `stylua.toml`.
lint:
stylua .
stylua . -g '*.lua' -g '!deps/'

# setup
setup:
Expand Down
10 changes: 6 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
- Minimal run time, ideal for free plans
- Docs with [mini.nvim `doc` plugin](https://github.com/echasnovski/mini.nvim/blob/main/lua/mini/doc.lua)
- Tests with [mini.nvim `test` plugin](https://github.com/echasnovski/mini.nvim/blob/main/lua/mini/test.lua)
- Versioned testing with [`bob`](https://github.com/MordechaiHadad/bob)
- Linting with [Stylua](https://github.com/JohnnyMorganz/StyLua)

## 📋 Installation
Expand All @@ -29,6 +30,7 @@
> This section is only required if you wish to use the linter provided by the template.
- [Install Stylua linter](https://github.com/JohnnyMorganz/StyLua#installation)
- [Install `bob` neovim version manager](https://github.com/MordechaiHadad/bob)

## ☄ Getting started

Expand All @@ -55,7 +57,7 @@ gh repo create my-awesome-plugin --template shortcuts/neovim-plugin-boilerplate

### 2 - Replace placeholder names with your plugin name

#### Automatically
#### Automatically

The [setup script](https://github.com/shortcuts/neovim-plugin-boilerplate/blob/main/scripts/setup.sh) will rename files and placeholder names for you. Once done, you can remove anything `setup` related if you want to.

Expand All @@ -67,12 +69,12 @@ make setup
USERNAME=my-github-username PLUGIN_NAME=my-awesome-plugin REPOSITORY_NAME=my-awesome-plugin.nvim make setup
```

#### Manually
#### ✍️ Manually

> **Note**:
> The placeholder names are purposely written with different casing. Make sure to keep it.
#### File names
##### File names

```sh
rm -rf doc
Expand All @@ -82,7 +84,7 @@ mv README_TEMPLATE.md README.md

```

#### Search and replace placeholder occurrences:
##### Search and replace placeholder occurrences:

```vim
:vimgrep /YourPluginName/ **/*
Expand Down
21 changes: 19 additions & 2 deletions doc/neovim-plugin-boilerplate.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,20 @@
==============================================================================
------------------------------------------------------------------------------
*YourPluginName.toggle()*
`YourPluginName.toggle`()
Toggle the plugin by calling the `enable`/`disable` methods respectively.

------------------------------------------------------------------------------
*YourPluginName.enable()*
`YourPluginName.enable`()
Initializes the plugin, sets event listeners and internal state.

------------------------------------------------------------------------------
*YourPluginName.disable()*
`YourPluginName.disable`()
Disables the plugin, clear highlight groups and autocmds, closes side buffers and resets the internal state.


==============================================================================
------------------------------------------------------------------------------
*YourPluginName.options*
Expand All @@ -18,10 +35,10 @@ Default values:
`YourPluginName.setup`({options})
Define your your-plugin-name setup.

Parameters~
Parameters ~
{options} `(table)` Module config table. See |YourPluginName.options|.

Usage~
Usage ~
`require("your-plugin-name").setup()` (add `{}` with your |YourPluginName.options| table)


Expand Down
3 changes: 3 additions & 0 deletions doc/tags
Original file line number Diff line number Diff line change
@@ -1,2 +1,5 @@
YourPluginName.disable() neovim-plugin-boilerplate.txt /*YourPluginName.disable()*
YourPluginName.enable() neovim-plugin-boilerplate.txt /*YourPluginName.enable()*
YourPluginName.options neovim-plugin-boilerplate.txt /*YourPluginName.options*
YourPluginName.setup() neovim-plugin-boilerplate.txt /*YourPluginName.setup()*
YourPluginName.toggle() neovim-plugin-boilerplate.txt /*YourPluginName.toggle()*
33 changes: 31 additions & 2 deletions lua/your-plugin-name/config.lua
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
local D = require("your-plugin-name.util.debug")

local YourPluginName = {}

--- Your plugin configuration with its default values.
Expand All @@ -9,15 +11,42 @@ YourPluginName.options = {
debug = false,
}

---@private
local defaults = vim.deepcopy(YourPluginName.options)

--- Defaults YourPluginName options by merging user provided options with the default plugin values.
---
---@param options table Module config table. See |YourPluginName.options|.
---
---@private
function YourPluginName.defaults(options)
local tde = function(t1, t2)
return vim.deepcopy(vim.tbl_deep_extend("keep", t1 or {}, t2 or {}))
end

YourPluginName.options = tde(options, defaults)

-- let your user know that they provided a wrong value, this is reported when your plugin is executed.
assert(
type(YourPluginName.options.debug) == "boolean",
"`debug` must be a boolean (`true` or `false`)."
)

return YourPluginName.options
end

--- Define your your-plugin-name setup.
---
---@param options table Module config table. See |YourPluginName.options|.
---
---@usage `require("your-plugin-name").setup()` (add `{}` with your |YourPluginName.options| table)
function YourPluginName.setup(options)
options = options or {}
YourPluginName.options = YourPluginName.defaults(options or {})

-- Useful for later checks that requires nvim 0.9 features at runtime.
YourPluginName.options.hasNvim9 = vim.fn.has("nvim-0.9") == 1

YourPluginName.options = vim.tbl_deep_extend("keep", options, YourPluginName.options)
D.warnDeprecation(YourPluginName.options)

return YourPluginName.options
end
Expand Down
27 changes: 11 additions & 16 deletions lua/your-plugin-name/init.lua
Original file line number Diff line number Diff line change
@@ -1,39 +1,34 @@
local M = require("your-plugin-name.main")
local C = require("your-plugin-name.config")

local YourPluginName = {}

-- Toggle the plugin by calling the `enable`/`disable` methods respectively.
--- Toggle the plugin by calling the `enable`/`disable` methods respectively.
function YourPluginName.toggle()
-- when the config is not set to the global object, we set it
if _G.YourPluginName.config == nil then
_G.YourPluginName.config = require("your-plugin-name.config").options
_G.YourPluginName.config = C.options
end

_G.YourPluginName.state = M.toggle()
M.toggle("publicAPI_toggle")
end

-- starts YourPluginName and set internal functions and state.
--- Initializes the plugin, sets event listeners and internal state.
function YourPluginName.enable()
if _G.YourPluginName.config == nil then
_G.YourPluginName.config = require("your-plugin-name.config").options
end

local state = M.enable()

if state ~= nil then
_G.YourPluginName.state = state
_G.YourPluginName.config = C.options
end

return state
M.enable("publicAPI_enable")
end

-- disables YourPluginName and reset internal functions and state.
--- Disables the plugin, clear highlight groups and autocmds, closes side buffers and resets the internal state.
function YourPluginName.disable()
_G.YourPluginName.state = M.disable()
M.disable("publicAPI_disable")
end

-- setup YourPluginName options and merge them with user provided ones.
function YourPluginName.setup(opts)
_G.YourPluginName.config = require("your-plugin-name.config").setup(opts)
_G.YourPluginName.config = C.setup(opts)
end

_G.YourPluginName = YourPluginName
Expand Down
58 changes: 32 additions & 26 deletions lua/your-plugin-name/main.lua
Original file line number Diff line number Diff line change
@@ -1,49 +1,55 @@
local S = require("your-plugin-name.state")
local D = require("your-plugin-name.util.debug")

-- internal methods
local YourPluginName = {}

-- state
local S = {
-- Boolean determining if the plugin is enabled or not.
enabled = false,
}

---Toggle the plugin by calling the `enable`/`disable` methods respectively.
-- Toggle the plugin by calling the `enable`/`disable` methods respectively.
--
--- @param scope string: internal identifier for logging purposes.
---@private
function YourPluginName.toggle()
if S.enabled then
return YourPluginName.disable()
function YourPluginName.toggle(scope)
if S.getEnabled(S) then
return YourPluginName.disable(scope)
end

return YourPluginName.enable()
return YourPluginName.enable(scope)
end

---Initializes the plugin.
--- Initializes the plugin, sets event listeners and internal state.
---
--- @param scope string: internal identifier for logging purposes.
---@private
function YourPluginName.enable()
if S.enabled then
return S
function YourPluginName.enable(scope)
if S.getEnabled(S) then
D.log(scope, "Plugin is already enabled.")

return
end

S.enabled = true
-- sets the plugin as `enabled`
S.setEnabled(S)

return S
-- saves the state globally to `_G.YourPluginName.state`
S.save(S)
end

---Disables the plugin and reset the internal state.
--- Disables the plugin for the given tab, clear highlight groups and autocmds, closes side buffers and resets the internal state.
---
--- @param scope string: internal identifier for logging purposes.
---@private
function YourPluginName.disable()
if not S.enabled then
return S
function YourPluginName.disable(scope)
if not S.getEnabled(S) then
D.log(scope, "Plugin is already disabled.")

return
end

-- reset the state
S = {
enabled = false,
}
-- resets the state to its initial value
S.init(S)

return S
-- saves the state globally to `_G.YourPluginName.state`
S.save(S)
end

return YourPluginName
36 changes: 36 additions & 0 deletions lua/your-plugin-name/state.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
local D = require("your-plugin-name.util.debug")

local State = { enabled = false }

---Sets the state to its original value.
---
---@private
function State:init()
self.enabled = false
end

---Saves the state in the global _G.YourPluginName.state object.
---
---@private
function State:save()
D.log("state.save", "saving state globally to _G.YourPluginName.state")

_G.YourPluginName.state = self
end

---Whether the YourPluginName is enabled or not.
---
---@private
function State:setEnabled()
self.enabled = true
end

---Whether the YourPluginName is enabled or not.
---
---@return boolean: the `enabled` state value.
---@private
function State:getEnabled()
return self.enabled
end

return State
Loading

0 comments on commit 9cc87ad

Please sign in to comment.