commit 45f1acb86f9be90cb5682f88530f27b63173074b Author: Chen Asraf Date: Mon May 15 02:09:42 2023 +0300 chore: setup diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..c1d757f --- /dev/null +++ b/.editorconfig @@ -0,0 +1,9 @@ +[*] +tab_width = 2 +indent_size = 2 +indent_style = space +insert_final_newline = true +trim_trailing_whitespace = true + +[*.md] +trim_trailing_whitespace = false diff --git a/.eslintignore b/.eslintignore new file mode 100644 index 0000000..a52a73c --- /dev/null +++ b/.eslintignore @@ -0,0 +1,2 @@ +templates/ +scaffolds/ diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100644 index 0000000..c38a05b --- /dev/null +++ b/.github/CODEOWNERS @@ -0,0 +1 @@ +* @chenasraf diff --git a/.github/ISSUE_TEMPLATE/Bug_report.md b/.github/ISSUE_TEMPLATE/Bug_report.md new file mode 100644 index 0000000..12315f0 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/Bug_report.md @@ -0,0 +1,24 @@ +--- +name: Bug report +about: It helps making the plugin more stable. +--- + +## Description + + + +## Steps to reproduce + +1. I did the command `...` +2. Then I saw `...` +3. Error + +## Expected behavior + + + +## Environment + +- Neovim version: [e.g. 0.5.x / 0.6.x / 0.7.x / 0.8.x / Nightly] +- text-transform version: [e.g. latest / 0.1.2 / dev] +- Plugin clash: [e.g. Telescope float window / lsp diagnostic] diff --git a/.github/ISSUE_TEMPLATE/Feature_request.md b/.github/ISSUE_TEMPLATE/Feature_request.md new file mode 100644 index 0000000..8f8cf6c --- /dev/null +++ b/.github/ISSUE_TEMPLATE/Feature_request.md @@ -0,0 +1,13 @@ +--- +name: Feature request +about: Suggest anything that would make your life easier, or the plugin better. +--- + +## Describe the problem + + + +## Describe the solution + + + diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 0000000..656bf0c --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,7 @@ +## 📃 Summary + + + +## 📸 Preview + + diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml new file mode 100644 index 0000000..43a5ef9 --- /dev/null +++ b/.github/workflows/main.yml @@ -0,0 +1,102 @@ +name: Release + +on: + push: + branches: [master] + pull_request: + types: [opened, synchronize] + +concurrency: + group: github.head_ref + cancel-in-progress: true + +jobs: + lint: + runs-on: ubuntu-latest + name: lint + steps: + - uses: actions/checkout@v3 + + - uses: JohnnyMorganz/stylua-action@v2 + with: + token: ${{ secrets.GITHUB_TOKEN }} + version: latest + args: --check . + + documentation: + runs-on: ubuntu-latest + name: documentation + steps: + - uses: actions/checkout@v3 + with: + fetch-depth: 2 + + - name: setup neovim + uses: rhysd/action-setup-vim@v1 + with: + neovim: true + version: v0.8.3 + + - name: generate documentation + run: make documentation-ci + + - name: check docs diff + run: exit $(git status --porcelain doc | wc -l | tr -d " ") + + # tests: + # needs: + # - lint + # - documentation + # runs-on: ubuntu-latest + # timeout-minutes: 2 + # strategy: + # matrix: + # neovim_version: ['v0.7.2', 'v0.8.3', 'v0.9.0', 'nightly'] + + # steps: + # - uses: actions/checkout@v3 + + # - run: date +%F > todays-date + + # - name: restore cache for today's nightly. + # uses: actions/cache@v3 + # with: + # path: _neovim + # key: ${{ runner.os }}-x64-${{ hashFiles('todays-date') }} + + # - name: setup neovim + # uses: rhysd/action-setup-vim@v1 + # with: + # neovim: true + # version: ${{ matrix.neovim_version }} + + # - name: run tests + # run: make test-ci + + release: + name: release + if: ${{ github.ref == 'refs/heads/master' }} + permissions: write-all + needs: + - lint + - documentation + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + + - uses: google-github-actions/release-please-action@v3 + id: release + with: + release-type: simple + package-name: text-transform.nvim + + - name: tag stable versions + if: ${{ steps.release.outputs.release_created }} + run: | + git config user.name github-actions[bot] + git config user.email github-actions[bot]@users.noreply.github.com + git remote add gh-token "https://${{ secrets.GITHUB_TOKEN }}@github.com/google-github-actions/release-please-action.git" + git tag -d stable || true + git push origin :stable || true + git tag -a stable -m "Last Stable Release" + git push origin stable diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..4b3caad --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +deps +**.DS_Store +.luarc.json diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 0000000..a52a73c --- /dev/null +++ b/.prettierignore @@ -0,0 +1,2 @@ +templates/ +scaffolds/ diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 0000000..548c817 --- /dev/null +++ b/.prettierrc @@ -0,0 +1,15 @@ +{ + "printWidth": 100, + "semi": false, + "singleQuote": true, + "trailingComma": "all", + "overrides": [ + { + "files": "*.md", + "options": { + "printWidth": 100, + "proseWrap": "always" + } + } + ] +} diff --git a/.styluaignore b/.styluaignore new file mode 100644 index 0000000..c7f3cb4 --- /dev/null +++ b/.styluaignore @@ -0,0 +1,2 @@ +deps/ +**/mini/ diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..4dc68c6 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,2 @@ +# Changelog + diff --git a/FUNDING.yml b/FUNDING.yml new file mode 100644 index 0000000..c665b77 --- /dev/null +++ b/FUNDING.yml @@ -0,0 +1,12 @@ +# These are supported funding model platforms + +github: chenasraf +patreon: # Replace with a single Patreon username +open_collective: # Replace with a single Open Collective username +ko_fi: casraf +tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel +community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry +liberapay: # Replace with a single Liberapay username +issuehunt: # Replace with a single IssueHunt username +otechie: # Replace with a single Otechie username +custom: ["https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=TSH3C3ABGQM22¤cy_code=ILS&source=url"] diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..8ff8382 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2023 Chen Asraf + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..33820ec --- /dev/null +++ b/Makefile @@ -0,0 +1,34 @@ +# we disable the `all` command because some external tool might run it automatically +.SUFFIXES: + +all: + +# runs all the test files. +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 }) } })" + +# installs `mini.nvim`, used for both the tests and documentation. +deps: + @mkdir -p deps + git clone --depth 1 https://github.com/echasnovski/mini.nvim deps/mini.nvim + +# installs deps before running tests, useful for the CI. +test-ci: deps test + +# generates the documentation. +documentation: + nvim --headless --noplugin -u ./scripts/minimal_init.lua -c "lua require('mini.doc').generate()" -c "qa!" + +# installs deps before running the documentation generation, useful for the CI. +documentation-ci: deps documentation + +# performs a lint check and fixes issue if possible, following the config in `stylua.toml`. +lint: + stylua . + +# setup +setup: + ./scripts/setup.sh diff --git a/README.md b/README.md new file mode 100644 index 0000000..4e2ba62 --- /dev/null +++ b/README.md @@ -0,0 +1,132 @@ +

+

text-transform.nvim

+

+ +

+ > A catch phrase that describes your plugin. +

+ +
+ > Drag your video (<10MB) here to host it for free on GitHub. +
+ +
+ +> Videos don't work on GitHub mobile, so a GIF alternative can help users. + +_[GIF version of the showcase video for mobile users](SHOWCASE_GIF_LINK)_ + +
+ +## ⚡️ Features + +> Write short sentences describing your plugin features + +- FEATURE 1 +- FEATURE .. +- FEATURE N + +## 📋 Installation + +
+ + + + + + + + + + + + + + + + + + + + + +
Package managerSnippet
+ +[wbthomason/packer.nvim](https://github.com/wbthomason/packer.nvim) + + + +```lua +-- stable version +use {"text-transform.nvim", tag = "*" } +-- dev version +use {"text-transform.nvim"} +``` + +
+ +[junegunn/vim-plug](https://github.com/junegunn/vim-plug) + + + +```lua +-- stable version +Plug "text-transform.nvim", { "tag": "*" } +-- dev version +Plug "text-transform.nvim" +``` + +
+ +[folke/lazy.nvim](https://github.com/folke/lazy.nvim) + + + +```lua +-- stable version +require("lazy").setup({{"text-transform.nvim", version = "*"}}) +-- dev version +require("lazy").setup({"text-transform.nvim"}) +``` + +
+
+ +## ☄ Getting started + +> Describe how to use the plugin the simplest way + +## ⚙ Configuration + +> The configuration list sometimes become cumbersome, making it folded by default reduce the noise of the README file. + +
+Click to unfold the full list of options with their default values + +> **Note**: The options are also available in Neovim by calling `:h text-transform.options` + +```lua +require("text-transform").setup({ + -- you can copy the full list from lua/text-transform/config.lua +}) +``` + +
+ +## 🧰 Commands + +| Command | Description | +|-------------|----------------------------| +| `:Toggle` | Enables the plugin. | + +## ⌨ Contributing + +PRs and issues are always welcome. Make sure to provide as much context as possible when opening one. + +## 🗞 Wiki + +You can find guides and showcase of the plugin on [the Wiki](https://github.com/chenasraf/text-transform.nvim/wiki) + +## 🎭 Motivations + +> If alternatives of your plugin exist, you can provide some pros/cons of using yours over the others. diff --git a/doc/tags b/doc/tags new file mode 100644 index 0000000..9a3781a --- /dev/null +++ b/doc/tags @@ -0,0 +1,2 @@ +TextTransform.options text-transform.txt /*TextTransform.options* +TextTransform.setup() text-transform.txt /*TextTransform.setup()* diff --git a/doc/text-transform.txt b/doc/text-transform.txt new file mode 100644 index 0000000..9436a23 --- /dev/null +++ b/doc/text-transform.txt @@ -0,0 +1,31 @@ +============================================================================== +------------------------------------------------------------------------------ + *TextTransform.options* + `TextTransform.options` +Your plugin configuration with its default values. + +Default values: +> + TextTransform.options = { + -- Prints useful logs about what event are triggered, and reasons actions are executed. + debug = false, + keymap = { + "~", + }, + } + +< + +------------------------------------------------------------------------------ + *TextTransform.setup()* + `TextTransform.setup`({options}) +Define your text-transform setup. + +Parameters~ +{options} `(table)` Module config table. See |TextTransform.options|. + +Usage~ +`require("text-transform").setup()` (add `{}` with your |TextTransform.options| table) + + + vim:tw=78:ts=8:noet:ft=help:norl: \ No newline at end of file diff --git a/lua/text-transform/config.lua b/lua/text-transform/config.lua new file mode 100644 index 0000000..0f34dfd --- /dev/null +++ b/lua/text-transform/config.lua @@ -0,0 +1,28 @@ +local TextTransform = {} + +--- Your plugin configuration with its default values. +--- +--- Default values: +---@eval return MiniDoc.afterlines_to_code(MiniDoc.current.eval_section) +TextTransform.options = { + -- Prints useful logs about what event are triggered, and reasons actions are executed. + debug = false, + keymap = { + "~", + }, +} + +--- Define your text-transform setup. +--- +---@param options table Module config table. See |TextTransform.options|. +--- +---@usage `require("text-transform").setup()` (add `{}` with your |TextTransform.options| table) +function TextTransform.setup(options) + options = options or {} + + TextTransform.options = vim.tbl_deep_extend("keep", options, TextTransform.options) + + return TextTransform.options +end + +return TextTransform diff --git a/lua/text-transform/init.lua b/lua/text-transform/init.lua new file mode 100644 index 0000000..8441a50 --- /dev/null +++ b/lua/text-transform/init.lua @@ -0,0 +1,41 @@ +local M = require("text-transform.main") +local TextTransform = {} + +-- Toggle the plugin by calling the `enable`/`disable` methods respectively. +function TextTransform.toggle() + -- when the config is not set to the global object, we set it + if _G.TextTransform.config == nil then + _G.TextTransform.config = require("text-transform.config").options + end + + _G.TextTransform.state = M.toggle() +end + +-- starts TextTransform and set internal functions and state. +function TextTransform.enable() + if _G.TextTransform.config == nil then + _G.TextTransform.config = require("text-transform.config").options + end + + local state = M.enable() + + if state ~= nil then + _G.TextTransform.state = state + end + + return state +end + +-- disables TextTransform and reset internal functions and state. +function TextTransform.disable() + _G.TextTransform.state = M.disable() +end + +-- setup TextTransform options and merge them with user provided ones. +function TextTransform.setup(opts) + _G.TextTransform.config = require("text-transform.config").setup(opts) +end + +_G.TextTransform = TextTransform + +return _G.TextTransform diff --git a/lua/text-transform/main.lua b/lua/text-transform/main.lua new file mode 100644 index 0000000..57b8a49 --- /dev/null +++ b/lua/text-transform/main.lua @@ -0,0 +1,49 @@ +local D = require("text-transform.util.debug") + +-- internal methods +local TextTransform = {} + +-- state +local S = { + -- Boolean determining if the plugin is enabled or not. + enabled = false, +} + +---Toggle the plugin by calling the `enable`/`disable` methods respectively. +---@private +function TextTransform.toggle() + if S.enabled then + return TextTransform.disable() + end + + return TextTransform.enable() +end + +---Initializes the plugin. +---@private +function TextTransform.enable() + if S.enabled then + return S + end + + S.enabled = true + + return S +end + +---Disables the plugin and reset the internal state. +---@private +function TextTransform.disable() + if not S.enabled then + return S + end + + -- reset the state + S = { + enabled = false, + } + + return S +end + +return TextTransform diff --git a/lua/text-transform/util/debug.lua b/lua/text-transform/util/debug.lua new file mode 100644 index 0000000..3347dec --- /dev/null +++ b/lua/text-transform/util/debug.lua @@ -0,0 +1,61 @@ +local D = {} + +---prints only if debug is true. +--- +---@param scope string: the scope from where this function is called. +---@param str string: the formatted string. +---@param ... any: the arguments of the formatted string. +---@private +function D.log(scope, str, ...) + if _G.TextTransform.config ~= nil and not _G.TextTransform.config.debug then + return + end + + local info = debug.getinfo(2, "Sl") + local line = "" + + if info then + line = "L" .. info.currentline + end + + print( + string.format( + "[text-transform:%s %s in %s] > %s", + os.date("%H:%M:%S"), + line, + scope, + string.format(str, ...) + ) + ) +end + +---prints the table if debug is true. +--- +---@param table table: the table to print. +---@param indent number?: the default indent value, starts at 0. +---@private +function D.tprint(table, indent) + if _G.TextTransform.config ~= nil and not _G.TextTransform.config.debug then + return + end + + if not indent then + indent = 0 + end + + for k, v in pairs(table) do + local formatting = string.rep(" ", indent) .. k .. ": " + if type(v) == "table" then + print(formatting) + D.tprint(v, indent + 1) + elseif type(v) == "boolean" then + print(formatting .. tostring(v)) + elseif type(v) == "function" then + print(formatting .. "FUNCTION") + else + print(formatting .. v) + end + end +end + +return D diff --git a/plugin/text-transform.lua b/plugin/text-transform.lua new file mode 100644 index 0000000..64700a7 --- /dev/null +++ b/plugin/text-transform.lua @@ -0,0 +1,164 @@ +-- You can use this loaded variable to enable conditional parts of your plugin. +if _G.TextTransformLoaded then + return +end + +_G.TextTransformLoaded = true + +local function into_words(str) + local words = {} + local word = "" + + local previous_is_upper = false + for i = 1, #str do + local char = str:sub(i, i) + -- split on uppercase letters + if char:match("%u") and not previous_is_upper then + if word ~= "" then + table.insert(words, word) + end + previous_is_upper = true + word = char + -- split on underscores, hyphens, and spaces + elseif char:match("[%_%-%s]") then + if word ~= "" then + table.insert(words, word) + previous_is_upper = false + end + word = "" + else + word = word .. char + previous_is_upper = char:match("%u") + end + end + if word ~= "" then + table.insert(words, word) + previous_is_upper = false + end + return words +end + +function IntoWords(string) + print(vim.inspect(into_words(string))) +end + +function CamelCase(string) + local words = into_words(string) + local camel_case = "" + for i, word in ipairs(words) do + if i == 1 then + camel_case = camel_case .. word:lower() + else + camel_case = camel_case .. word:sub(1, 1):upper() .. word:sub(2):lower() + end + end + return camel_case +end + +function SnakeCase(string) + local words = into_words(string) + local snake_case = "" + for i, word in ipairs(words) do + if i == 1 then + snake_case = snake_case .. word:lower() + else + snake_case = snake_case .. "_" .. word:lower() + end + end + return snake_case +end + +function PascalCase(string) + local words = into_words(string) + local pascal_case = "" + for _, word in ipairs(words) do + pascal_case = pascal_case .. word:sub(1, 1):upper() .. word:sub(2):lower() + end + return pascal_case +end + +function KebabCase(string) + local words = into_words(string) + local kebab_case = "" + for i, word in ipairs(words) do + if i == 1 then + kebab_case = kebab_case .. word:lower() + else + kebab_case = kebab_case .. "-" .. word:lower() + end + end + return kebab_case +end + +function DotCase(string) + local words = into_words(string) + local dot_case = "" + for i, word in ipairs(words) do + if i == 1 then + dot_case = dot_case .. word:lower() + else + dot_case = dot_case .. "." .. word:lower() + end + end + return dot_case +end + +function TitleCase(string) + local words = into_words(string) + local title_case = "" + for i, word in ipairs(words) do + title_case = title_case .. word:sub(1, 1):upper() .. word:sub(2):lower() + if i ~= #words then + title_case = title_case .. " " + end + end + return title_case +end + +function ReplaceCurrentSelection(transform) + local selection = vim.fn.getline("'<", "'>") + local transformed = transform(selection) + vim.fn.setline("'<", transformed) +end + +function ReplaceCurrentWord(transform) + local word = vim.fn.expand("") + local transformed = transform(word) + vim.cmd("normal ciw" .. transformed) +end + +local should_test = false + +if should_test then + local map = { + ["CamelCase"] = CamelCase, + ["SnakeCase"] = SnakeCase, + ["PascalCase"] = PascalCase, + ["KebabCase"] = KebabCase, + ["DotCase"] = DotCase, + ["TitleCase"] = TitleCase, + } + + for k, tst in pairs(map) do + print(k .. ": " .. "hello_world" .. " => " .. tst("hello_world")) + print(k .. ": " .. "HELLO_WORLD" .. " => " .. tst("HELLO_WORLD")) + print(k .. ": " .. "HelloWorld" .. " => " .. tst("HelloWorld")) + print(k .. ": " .. "Hello-World" .. " => " .. tst("Hello-World")) + end +end +-- use input from current word in editor +vim.cmd("amenu Transforms.&camelCase :lua ReplaceCurrentWord(CamelCase)") +vim.cmd("amenu Transforms.&snake_case :lua ReplaceCurrentWord(SnakeCase)") +vim.cmd("amenu Transforms.&PascalCase :lua ReplaceCurrentWord(PascalCase)") +vim.cmd("amenu Transforms.&kebab-case :lua ReplaceCurrentWord(KebabCase)") +vim.cmd("amenu Transforms.&dot\\.case :lua ReplaceCurrentWord(DotCase)") +vim.cmd("amenu Transforms.&Title\\ Case :lua ReplaceCurrentWord(TitleCase)") + +for i in TextTransform.config.keymap do + vim.keymap.set( + { "n", "v" }, + _G.TextTransform.config.keymap[i], + "popup Transforms", + { silent = true } + ) +end diff --git a/scripts/minimal_init.lua b/scripts/minimal_init.lua new file mode 100644 index 0000000..362995b --- /dev/null +++ b/scripts/minimal_init.lua @@ -0,0 +1,15 @@ +-- Add current directory to 'runtimepath' to be able to use 'lua' files +vim.cmd([[let &rtp.=','.getcwd()]]) + +-- Set up 'mini.test' and 'mini.doc' only when calling headless Neovim (like with `make test` or `make documentation`) +if #vim.api.nvim_list_uis() == 0 then + -- Add 'mini.nvim' to 'runtimepath' to be able to use 'mini.test' + -- Assumed that 'mini.nvim' is stored in 'deps/mini.nvim' + vim.cmd("set rtp+=deps/mini.nvim") + + -- Set up 'mini.test' + require("mini.test").setup() + + -- Set up 'mini.doc' + require("mini.doc").setup() +end diff --git a/scripts/setup.sh b/scripts/setup.sh new file mode 100755 index 0000000..2695c62 --- /dev/null +++ b/scripts/setup.sh @@ -0,0 +1,79 @@ +#!/bin/bash + +USAGE="\033[0;37m[INFO] - usage: USERNAME=my-github-username PLUGIN_NAME=my-awesome-plugin REPOSITORY_NAME=my-awesome-plugin.nvim make setup\n\033[0m" + +echo -e $USAGE + +if [[ -z "$USERNAME" ]]; then + echo -e "\t> No USERNAME provided, what's your GitHub/GitLab username?" + read USERNAME +fi + +if [[ -z "$REPOSITORY_NAME" ]]; then + REPOSITORY_NAME=$(basename -s .git `git config --get remote.origin.url`) + + read -rp $'\t> No REPOSITORY_NAME provided, is \033[1;32m'"$REPOSITORY_NAME"$'\033[0m good? [Y/n]\n' yn + case $yn in + [Yy]* );; + [Nn]* ) + echo -e "\t> Enter your repository name" + read REPOSITORY_NAME + ;; + * ) + echo -e $USAGE + exit 1;; + esac +fi + +if [[ -z "$PLUGIN_NAME" ]]; then + DEFAULT_REPOSITORY_NAME=$(echo "$REPOSITORY_NAME" | sed -e "s/\.nvim//") + read -rp $'\t> No PLUGIN_NAME provided, defaulting to \033[1;32m'"$DEFAULT_REPOSITORY_NAME"$'\033[0m, continue? [Y/n]\n' yn + case $yn in + [Yy]* ) + PLUGIN_NAME=$DEFAULT_REPOSITORY_NAME + ;; + [Nn]* ) + echo -e "\t> Enter your plugin name" + read PLUGIN_NAME + ;; + * ) + echo -e $USAGE + exit 1;; + esac +fi + +echo -e "Username: \033[1;32m$USERNAME\033[0m\nRepository: \033[1;32m$REPOSITORY_NAME\033[0m\nPlugin: \033[1;32m$PLUGIN_NAME\033[0m\n\n\tRenaming placeholder files..." + +rm -rf doc +mv plugin/your-plugin-name.lua plugin/$PLUGIN_NAME.lua +mv lua/your-plugin-name lua/$PLUGIN_NAME +mv README_TEMPLATE.md README.md + +echo -e "\tReplacing placeholder names..." + +PASCAL_CASE_PLUGIN_NAME=$(echo "$PLUGIN_NAME" | perl -pe 's/(^|-)./uc($&)/ge;s/-//g') + +grep -rl "YourPluginName" .github/ plugin/ tests/ lua/ | xargs sed -i "" -e "s/YourPluginName/$PASCAL_CASE_PLUGIN_NAME/g" +grep -rl "your-plugin-name" README.md .github/ plugin/ tests/ lua/ | xargs sed -i "" -e "s/your-plugin-name/$PLUGIN_NAME/g" +grep -rl "YOUR_GITHUB_USERNAME" README.md .github/ | xargs sed -i "" -e "s/YOUR_GITHUB_USERNAME/$USERNAME/g" +grep -rl "YOUR_REPOSITORY_NAME" README.md .github/ | xargs sed -i "" -e "s/YOUR_REPOSITORY_NAME/$REPOSITORY_NAME/g" + +echo -e "\n\033[1;32mOK.\033[0m" + +echo -e "\tFetching dependencies (tests and documentation generator)..." + +make deps + +echo -e "\n\033[1;32mOK.\033[0m" + +echo -e "\tGenerating docs..." + +make documentation + +echo -e "\n\033[1;32mOK.\033[0m" + +echo -e "\tRunning tests..." + +make test + +echo -e "\n\033[1;32mOK.\033[0m" diff --git a/stylua.toml b/stylua.toml new file mode 100644 index 0000000..6376ab8 --- /dev/null +++ b/stylua.toml @@ -0,0 +1,5 @@ +indent_type = "Spaces" +indent_width = 4 +column_width = 100 +quote_style = "AutoPreferDouble" +no_call_parentheses = false diff --git a/tests/helpers.lua b/tests/helpers.lua new file mode 100644 index 0000000..d34828e --- /dev/null +++ b/tests/helpers.lua @@ -0,0 +1,166 @@ +-- partially imported from https://github.com/echasnovski/mini.nvim +local Helpers = {} + +-- Add extra expectations +Helpers.expect = vim.deepcopy(MiniTest.expect) + +-- The error message returned when a test fails. +local function errorMessage(str, pattern) + return string.format("Pattern: %s\nObserved string: %s", vim.inspect(pattern), str) +end + +-- Check equality of a global `field` against `value` in the given `child` process. +-- @usage global_equality(child, "_G.TextTransformLoaded", true) +Helpers.expect.global_equality = MiniTest.new_expectation( + "variable in child process matches", + function(child, field, value) + return Helpers.expect.equality(child.lua_get(field), value) + end, + errorMessage +) + +-- Check type equality of a global `field` against `value` in the given `child` process. +-- @usage global_type_equality(child, "_G.TextTransformLoaded", "boolean") +Helpers.expect.global_type_equality = MiniTest.new_expectation( + "variable type in child process matches", + function(child, field, value) + return Helpers.expect.global_equality(child, "type(" .. field .. ")", value) + end, + errorMessage +) + +-- Check equality of a config `field` against `value` in the given `child` process. +-- @usage option_equality(child, "debug", true) +Helpers.expect.config_equality = MiniTest.new_expectation( + "config option matches", + function(child, field, value) + return Helpers.expect.global_equality(child, "_G.TextTransform.config." .. field, value) + end, + errorMessage +) + +-- Check type equality of a config `field` against `value` in the given `child` process. +-- @usage config_type_equality(child, "debug", "boolean") +Helpers.expect.config_type_equality = MiniTest.new_expectation( + "config option type matches", + function(child, field, value) + return Helpers.expect.global_equality( + child, + "type(_G.TextTransform.config." .. field .. ")", + value + ) + end, + errorMessage +) + +-- Check equality of a state `field` against `value` in the given `child` process. +-- @usage state_equality(child, "enabled", true) +Helpers.expect.state_equality = MiniTest.new_expectation( + "state matches", + function(child, field, value) + return Helpers.expect.global_equality(child, "_G.TextTransform.enabled." .. field, value) + end, + errorMessage +) + +-- Check type equality of a state `field` against `value` in the given `child` process. +-- @usage state_type_equality(child, "enabled", "boolean") +Helpers.expect.state_type_equality = MiniTest.new_expectation( + "state type matches", + function(child, field, value) + return Helpers.expect.global_equality( + child, + "type(_G.TextTransform.state." .. field .. ")", + value + ) + end, + errorMessage +) + +Helpers.expect.match = MiniTest.new_expectation("string matching", function(str, pattern) + return str:find(pattern) ~= nil +end, errorMessage) + +Helpers.expect.no_match = MiniTest.new_expectation("no string matching", function(str, pattern) + return str:find(pattern) == nil +end, errorMessage) + +-- Monkey-patch `MiniTest.new_child_neovim` with helpful wrappers +Helpers.new_child_neovim = function() + local child = MiniTest.new_child_neovim() + + local prevent_hanging = function(method) + -- stylua: ignore + if not child.is_blocked() then return end + + local msg = + string.format("Can not use `child.%s` because child process is blocked.", method) + error(msg) + end + + child.setup = function() + child.restart({ "-u", "scripts/minimal_init.lua" }) + + -- Change initial buffer to be readonly. This not only increases execution + -- speed, but more closely resembles manually opened Neovim. + child.bo.readonly = false + end + + child.set_lines = function(arr, start, finish) + prevent_hanging("set_lines") + + if type(arr) == "string" then + arr = vim.split(arr, "\n") + end + + child.api.nvim_buf_set_lines(0, start or 0, finish or -1, false, arr) + end + + child.get_lines = function(start, finish) + prevent_hanging("get_lines") + + return child.api.nvim_buf_get_lines(0, start or 0, finish or -1, false) + end + + child.set_cursor = function(line, column, win_id) + prevent_hanging("set_cursor") + + child.api.nvim_win_set_cursor(win_id or 0, { line, column }) + end + + child.get_cursor = function(win_id) + prevent_hanging("get_cursor") + + return child.api.nvim_win_get_cursor(win_id or 0) + end + + child.set_size = function(lines, columns) + prevent_hanging("set_size") + + if type(lines) == "number" then + child.o.lines = lines + end + + if type(columns) == "number" then + child.o.columns = columns + end + end + + child.get_size = function() + prevent_hanging("get_size") + + return { child.o.lines, child.o.columns } + end + + child.expect_screenshot = function(opts, path, screenshot_opts) + if child.fn.has("nvim-0.8") == 0 then + MiniTest.skip("Screenshots are tested for Neovim>=0.8 (for simplicity).") + end + + MiniTest.expect.reference_screenshot(child.get_screenshot(screenshot_opts), path, opts) + end + + return child +end + +return Helpers diff --git a/tests/test_API.lua b/tests/test_API.lua new file mode 100644 index 0000000..01193a4 --- /dev/null +++ b/tests/test_API.lua @@ -0,0 +1,58 @@ +local helpers = dofile("tests/helpers.lua") + +-- See https://github.com/echasnovski/mini.nvim/blob/main/lua/mini/test.lua for more documentation + +local child = helpers.new_child_neovim() +local eq_global, eq_config, eq_state = + helpers.expect.global_equality, helpers.expect.config_equality, helpers.expect.state_equality +local eq_type_global, eq_type_config, eq_type_state = + helpers.expect.global_type_equality, + helpers.expect.config_type_equality, + helpers.expect.state_type_equality + +local T = MiniTest.new_set({ + hooks = { + -- This will be executed before every (even nested) case + pre_case = function() + -- Restart child process with custom 'init.lua' script + child.restart({ "-u", "scripts/minimal_init.lua" }) + end, + -- This will be executed one after all tests from this set are finished + post_once = child.stop, + }, +}) + +-- Tests related to the `setup` method. +T["setup()"] = MiniTest.new_set() + +T["setup()"]["sets exposed methods and default options value"] = function() + child.lua([[require('text-transform').setup()]]) + + -- global object that holds your plugin information + eq_type_global(child, "_G.TextTransform", "table") + + -- public methods + eq_type_global(child, "_G.TextTransform.toggle", "function") + eq_type_global(child, "_G.TextTransform.disable", "function") + eq_type_global(child, "_G.TextTransform.enable", "function") + + -- config + eq_type_global(child, "_G.TextTransform.config", "table") + + -- assert the value, and the type + eq_config(child, "debug", false) + eq_type_config(child, "debug", "boolean") +end + +T["setup()"]["overrides default values"] = function() + child.lua([[require('text-transform').setup({ + -- write all the options with a value different than the default ones + debug = true, + })]]) + + -- assert the value, and the type + eq_config(child, "debug", true) + eq_type_config(child, "debug", "boolean") +end + +return T