├── lua ├── drupal │ ├── default_config.lua │ ├── utils │ │ ├── init.lua │ │ └── flatten.lua │ ├── snippets │ │ ├── general.lua │ │ ├── docs.md │ │ └── hooks.lua │ └── services.lua └── drupal.lua ├── LICENSE └── README.md /lua/drupal/default_config.lua: -------------------------------------------------------------------------------- 1 | return { 2 | services_cmp_trigger_character = '@', 3 | get_drush_executable = function() 4 | return "drush" 5 | end, 6 | enabled_snippets = { 7 | general = true, 8 | hooks = true, 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /lua/drupal/utils/init.lua: -------------------------------------------------------------------------------- 1 | local M = {} 2 | 3 | M.current_dir = function () 4 | local path = vim.api.nvim_buf_get_name(0) 5 | return path:match("(.*/)") 6 | end 7 | 8 | M.file_exists = function(name) 9 | local f = io.open(name, "r") 10 | if f ~= nil then 11 | io.close(f) 12 | return true 13 | else 14 | return false 15 | end 16 | end 17 | 18 | return M 19 | -------------------------------------------------------------------------------- /lua/drupal.lua: -------------------------------------------------------------------------------- 1 | local M = {} 2 | 3 | function M.setup(cfg) 4 | M.__conf = vim.tbl_deep_extend("keep", cfg or {}, require("drupal.default_config")) 5 | require("drupal.services").setup(M.__conf) 6 | if M.__conf.enabled_snippets.hooks then 7 | require("drupal.snippets.hooks") 8 | end 9 | if M.__conf.enabled_snippets.general then 10 | require("drupal.snippets.general") 11 | end 12 | end 13 | 14 | return M 15 | -------------------------------------------------------------------------------- /lua/drupal/snippets/general.lua: -------------------------------------------------------------------------------- 1 | local luasnip = require("luasnip") 2 | 3 | local s = luasnip.snippet 4 | local t = luasnip.text_node 5 | local i = luasnip.insert_node 6 | 7 | local snippets = { 8 | -- Create an inheritdoc doc block. 9 | s("ihdoc", { 10 | t({ "/**", "" }), 11 | t({ " * {@inheritdoc}", "" }), 12 | t({ " */" }) 13 | }), 14 | -- Create an empty doc block. 15 | s("/**", { 16 | t({ "/**", "" }), 17 | t({ " * " }), 18 | i(0), 19 | t({ "", " */" }) 20 | }), 21 | } 22 | 23 | luasnip.add_snippets("php", snippets) 24 | -------------------------------------------------------------------------------- /lua/drupal/snippets/docs.md: -------------------------------------------------------------------------------- 1 | # Snippets 2 | 3 | ## General snippets 4 | The following snippets are available when the `enabled_snippets.general` option is set to true. 5 | 6 | An **X** marks the final cursor position. 7 | 8 | Empty docblock: `/**` 9 | ```php 10 | /** 11 | * X 12 | */ 13 | ``` 14 | 15 | Inheritdoc doc block: `ihdoc` 16 | ```php 17 | /** 18 | * {@inheritdoc} 19 | */X 20 | ``` 21 | 22 | ## Hooks 23 | Snippets for core and contrib hooks are available when the `enabled_snippets.hooks` option is set to true. 24 | The list of possible hooks is fetched when the module is loaded, and is cached in `/tmp/hooks.txt`. 25 | 26 | To use the snippets simply type `hook_` followed by the name of the hook you need to implement. 27 | -------------------------------------------------------------------------------- /lua/drupal/utils/flatten.lua: -------------------------------------------------------------------------------- 1 | local function noop(...) 2 | return ... 3 | end 4 | 5 | -- convert a nested table to a flat table 6 | local function flatten(t, sep, key_modifier, res) 7 | if type(t) ~= 'table' then 8 | return t 9 | end 10 | 11 | if sep == nil then 12 | sep = '.' 13 | end 14 | 15 | if res == nil then 16 | res = {} 17 | end 18 | 19 | if key_modifier == nil then 20 | key_modifier = noop 21 | end 22 | 23 | for k, v in pairs(t) do 24 | if type(v) == 'table' then 25 | local v = flatten(v, sep, key_modifier, {}) 26 | for k2, v2 in pairs(v) do 27 | res[key_modifier(k) .. sep .. key_modifier(k2)] = v2 28 | end 29 | else 30 | res[key_modifier(k)] = v 31 | end 32 | end 33 | return res 34 | end 35 | 36 | return flatten 37 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) Jonathan Morris 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /lua/drupal/snippets/hooks.lua: -------------------------------------------------------------------------------- 1 | local utils = require("drupal.utils") 2 | local Job = require('plenary.job') 3 | local luasnip = require("luasnip") 4 | 5 | local s = luasnip.snippet 6 | local t = luasnip.text_node 7 | local i = luasnip.insert_node 8 | local f = luasnip.function_node 9 | 10 | vim.api.nvim_create_autocmd("BufRead", { 11 | pattern = "*.module,*.theme,*.install,*.deploy", 12 | callback = function () 13 | local tmp_file_path = "/tmp/hooks.txt" 14 | local hooks = {} 15 | if utils.file_exists(tmp_file_path) then 16 | for line in io.lines(tmp_file_path) do 17 | table.insert(hooks, line) 18 | end 19 | end 20 | 21 | -- Regenerate tmp file if empty or it doesn't exist. 22 | if next(hooks) == nil then 23 | hooks = Job:new({ 24 | command = 'rg', 25 | args = { '-e', 'function hook_', '-uu', '-g', '*.api.php', '--no-filename', vim.loop.cwd() }, 26 | env = { PATH = vim.env.PATH }, 27 | }):sync(1500) 28 | 29 | local file = assert(io.open(tmp_file_path, "w")) 30 | for _, name in pairs(hooks) do 31 | file:write(name .. "\n") 32 | end 33 | file:close() 34 | end 35 | 36 | local get_filename = function () 37 | return vim.fn.expand('%:t:r') 38 | end 39 | 40 | local snippets = {} 41 | for _, name in pairs(hooks) do 42 | local _, _, hook_name = string.find(name, 'function (.+)%(') 43 | local _, _, signature = string.find(name, 'function hook(.+)') 44 | table.insert(snippets, 45 | s(hook_name, { 46 | t({ "/**", "" }), 47 | t({ " * Implements " .. hook_name .. "().", "" }), 48 | t({ " */", "" }), 49 | t("function "), 50 | f(get_filename, {}), 51 | t({ signature, "\t" }), 52 | i(0), 53 | t({ "", "}" }), 54 | })) 55 | end 56 | 57 | luasnip.add_snippets("php", snippets) 58 | end 59 | }) 60 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # drupal.nvim 2 | 3 | **:warning: Archived. Check out [drupal_ls](https://github.com/jdrupal-dev/drupal_ls) which has all of the features from this plugin + much more.** 4 | 5 | ## :lock: Requirements 6 | 7 | - [plenary.nvim](https://github.com/nvim-lua/plenary.nvim) (used for running drush) 8 | - [nvim-cmp](https://github.com/hrsh7th/nvim-cmp) (currently autocompletion requires nvim-cmp) 9 | - [cmp_luasnip](https://github.com/saadparwaiz1/cmp_luasnip) (required for adding hook snippets) 10 | - [ripgrep](https://github.com/BurntSushi/ripgrep) (needs to be installed on your machine) 11 | - [drush](https://www.drush.org/12.x) (needs to be installed on your machine/project) 12 | 13 | ## :package: Installation 14 | 15 | Install this plugin using your favorite plugin manager, and then call 16 | `require("drupal").setup()`. 17 | 18 | ### [lazy.nvim](https://github.com/folke/lazy.nvim) 19 | 20 | Default configuration can be found in `lua/drupal/default_config.lua`. 21 | 22 | ```lua 23 | { 24 | "jdrupal-dev/drupal.nvim", 25 | dependencies = { "nvim-lua/plenary.nvim" }, 26 | config = function() 27 | require("drupal").setup({ 28 | services_cmp_trigger_character = "@", 29 | get_drush_executable = function(current_dir) 30 | -- You can use current_dir if you have different ways of 31 | -- executing drush across your Drupal projects. 32 | return "drush" 33 | end, 34 | }) 35 | end 36 | } 37 | ``` 38 | ## :sparkles: Features 39 | 40 | ### Autocomplete services 41 | 42 | You need the `devel` module installed for this feature to work.\ 43 | The `drush devel:services` command is used to get a list of all available Drupal services. 44 | 45 | To trigger the autocompletion of services you need to input the trigger character, which by default is "@". 46 | ```php 47 | \Drupal::service('@entity_') // Now you should see services beginning with entity_. 48 | ``` 49 | ### Snippets 50 | 51 | A few practical snippets are provided, you can find the complete list of snippets in `lua/drupal/snippets/docs.md`. 52 | 53 | LuaSnip snippets are automatically generated for hooks when opening nvim in a Drupal project. 54 | 55 | You can use the snippets by typing `hook_` in a `.module` or `.theme` file. 56 | When the snippet is used `hook` will automatically get replaced with the name of the current module. 57 | 58 | For example, typing `hook_theme + Enter` in `my_module.module` will generate the following code: 59 | ```php 60 |