-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* feat(header): Adds header.insert logic * feat(header): Adds update logic * feat(header): Adds update autocmd * fix(header): Adds creted_by and updated_by fields * feat(header): Adds FtHeader command * chore(docs): Adds 42 header documentation
- Loading branch information
1 parent
055e171
commit 09ad21d
Showing
6 changed files
with
336 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -24,6 +24,7 @@ You can install the plugin using your favorite package manager: | |
---@type LazySpec | ||
return { | ||
"vinicius507/ft_nvim", | ||
cmd = { "FtHeader", "Norme" }, -- Lazy load the commands. | ||
ft = { "c", "cpp" }, -- Lazy load for .c and .h files. | ||
---@type ft_nvim.Config | ||
opts = {}, | ||
|
@@ -35,6 +36,7 @@ return { | |
```lua | ||
use({ | ||
"vinicius507/ft_nvim", | ||
cmd = { "FtHeader", "Norme" }, -- Lazy load the commands. | ||
ft = { "c", "cpp" }, -- Lazy load for .c and .h files. | ||
config = function() | ||
require("ft_nvim").setup() | ||
|
@@ -57,6 +59,15 @@ The following options are available: | |
|
||
```lua | ||
require("ft_nvim").setup({ | ||
-- Configures the 42 Header integration | ||
header = { | ||
-- Enable the 42 Header integration (default: true). | ||
enable = true, | ||
-- Your Intranet username (default: "marvin"). | ||
username = "marvin", | ||
-- Your Intranet email (default: "[email protected]"). | ||
email = "[email protected]", | ||
}, | ||
-- Configures the norminette integration. | ||
norminette = { | ||
-- Enable the norminette integration (default: true). | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
-- ************************************************************************** -- | ||
-- -- | ||
-- ::: :::::::: -- | ||
-- delimeters.lua :+: :+: :+: -- | ||
-- +:+ +:+ +:+ -- | ||
-- By: vgoncalv <[email protected]> +#+ +:+ +#+ -- | ||
-- +#+#+#+#+#+ +#+ -- | ||
-- Created: 2023/01/13 10:12:09 by vgoncalv #+# #+# -- | ||
-- Updated: 2023/01/13 10:12:09 by vgoncalv ### ########.fr -- | ||
-- -- | ||
-- ************************************************************************** -- | ||
|
||
local delimeters = { | ||
HASHES = { "#", "#" }, | ||
SLASHES = { "/*", "*/" }, | ||
SEMICOLONS = { ";;", ";;" }, | ||
PARENS = { "(*", "*)" }, | ||
DASHES = { "--", "--" }, | ||
PERCENTS = { "%%", "%%" }, | ||
} | ||
|
||
---@alias ft_nvim.Delimeters | ||
---|`delimeters.HASHES` | ||
---|`delimeters.SLASHES` | ||
---|`delimeters.SEMICOLONS` | ||
---|`delimeters.PARENS` | ||
---|`delimeters.DASHES` | ||
---|`delimeters.PERCENTS` | ||
---Common header delimeters between filetypes | ||
|
||
---Language delimeters | ||
---@type table<string, ft_nvim.Delimeters> | ||
local languages_delimeters = { | ||
default = delimeters.HASHES, | ||
c = delimeters.SLASHES, | ||
cpp = delimeters.SLASHES, | ||
css = delimeters.SLASHES, | ||
dockerfile = delimeters.HASHES, | ||
go = delimeters.SLASHES, | ||
groovy = delimeters.SLASHES, | ||
haskell = delimeters.DASHES, | ||
dosini = delimeters.SEMICOLONS, | ||
java = delimeters.SLASHES, | ||
javascript = delimeters.SLASHES, | ||
javascriptreact = delimeters.SLASHES, | ||
latex = delimeters.PERCENTS, | ||
less = delimeters.SLASHES, | ||
lua = delimeters.DASHES, | ||
make = delimeters.HASHES, | ||
objc = delimeters.SLASHES, | ||
ocaml = delimeters.PARENS, | ||
perl = delimeters.HASHES, | ||
php = delimeters.SLASHES, | ||
text = delimeters.HASHES, | ||
python = delimeters.HASHES, | ||
r = delimeters.HASHES, | ||
ruby = delimeters.HASHES, | ||
rust = delimeters.SLASHES, | ||
scss = delimeters.SLASHES, | ||
sh = delimeters.HASHES, | ||
bash = delimeters.HASHES, | ||
sql = delimeters.HASHES, | ||
swift = delimeters.SLASHES, | ||
typescript = delimeters.SLASHES, | ||
typescriptreact = delimeters.SLASHES, | ||
yaml = delimeters.HASHES, | ||
} | ||
|
||
return languages_delimeters |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,170 @@ | ||
---@class ft_nvim.Header | ||
---@field filename string | ||
---@field username string | ||
---@field email string | ||
---@field created_at string | ||
---@field created_by string | ||
---@field updated_at string | ||
---@field updated_by string | ||
|
||
local delimeters = require("ft_nvim.header.delimeters") | ||
local TEMPLATE = { | ||
"********************************************************************************", | ||
"* *", | ||
"* ::: :::::::: *", | ||
"* @FILENAME.................................. :+: :+: :+: *", | ||
"* +:+ +:+ +:+ *", | ||
"* By: @AUTHOR................................ +#+ +:+ +#+ *", | ||
"* +#+#+#+#+#+ +#+ *", | ||
"* Created: @CREATED_AT........ by @CREATED_BY #+# #+# *", | ||
"* Updated: @UPDATED_AT........ by @UPDATED_BY ### ########.fr *", | ||
"* *", | ||
"********************************************************************************", | ||
} | ||
|
||
---@alias ft_nvim.FieldKey "filename" | "author" | "created_at" | "updated_at" | "created_by" | "updated_by" | ||
|
||
---@type table<ft_nvim.FieldKey, fun(header: ft_nvim.Header): string> | ||
local fields = { | ||
filename = function(header) | ||
return header.filename | ||
end, | ||
author = function(header) | ||
return string.format("%s <%s>", header.username, header.email) | ||
end, | ||
created_at = function(header) | ||
return header.created_at | ||
end, | ||
updated_at = function(header) | ||
return header.updated_at | ||
end, | ||
created_by = function(header) | ||
return header.created_by | ||
end, | ||
updated_by = function(header) | ||
return header.updated_by | ||
end, | ||
} | ||
|
||
---@type fun(delims: ft_nvim.Delimeters[]): fun(line: string): string | ||
local function set_delimeters(delims) | ||
return function(line) | ||
local start_delim, end_delim = delims[1], delims[2] | ||
line = string.sub(line, string.len(start_delim) + 2, line:len() - string.len(end_delim) - 1) | ||
|
||
return string.format("%s %s %s", start_delim, line, end_delim) | ||
end | ||
end | ||
|
||
---@type fun(header: ft_nvim.Header): string[] | ||
local function serialize(header) | ||
local lines = TEMPLATE | ||
local annotated_lines = { 4, 6, 8, 9 } | ||
local delims = delimeters[vim.bo.filetype] or delimeters.default | ||
|
||
for _, lineno in ipairs(annotated_lines) do | ||
lines[lineno] = string.gsub(lines[lineno], "(@([%w_]*)%.*)", function(match, key) | ||
key = key:lower() | ||
local data = fields[key] and fields[key](header) | ||
|
||
if not data then | ||
return | ||
end | ||
|
||
return string.format( | ||
"%s%s", | ||
data, | ||
string.rep(" ", match:len() > data:len() and match:len() - data:len() or 0) | ||
) | ||
end) | ||
end | ||
lines = vim.tbl_map(set_delimeters(delims), lines) | ||
table.insert(lines, "") | ||
return lines | ||
end | ||
|
||
---@type fun(lines: string[]): boolean | ||
local function lines_are_header(lines) | ||
if #lines < 11 then | ||
return false | ||
end | ||
|
||
local annotated_lines = { 4, 6, 8, 9 } | ||
local lines_delimeters = { string.match(lines[1], "^([^%s]+) .* ([^%s]+)$") } | ||
|
||
if #lines_delimeters == 0 then | ||
return false | ||
end | ||
|
||
for lineno, template_line in ipairs(TEMPLATE) do | ||
local line = lines[lineno] | ||
template_line = set_delimeters(lines_delimeters)(template_line) | ||
|
||
if vim.tbl_contains(annotated_lines, lineno) then | ||
template_line = string.gsub(template_line, "@[%w_]+%.*", function(match) | ||
local range = { string.find(template_line, match, 1, true) } | ||
return string.sub(line, unpack(range)) | ||
end) | ||
end | ||
|
||
template_line = string.gsub(template_line, "[+*]", "%%%1") | ||
|
||
if not string.match(line, template_line) then | ||
return false | ||
end | ||
end | ||
|
||
return true | ||
end | ||
|
||
return { | ||
---@type fun(bufnr: number): boolean | ||
buf_has_header = function(bufnr) | ||
local lines = vim.api.nvim_buf_get_lines(bufnr, 0, #TEMPLATE, false) | ||
return lines_are_header(lines) | ||
end, | ||
---@type fun(bufnr: number, opts: ft_nvim.HeaderConfig) | ||
insert = function(bufnr, opts) | ||
local header = { | ||
filename = vim.fn.expand("%:t"), | ||
username = opts.username, | ||
email = opts.email, | ||
created_at = vim.fn.strftime("%Y/%m/%d %H:%M:%S"), | ||
created_by = opts.username, | ||
updated_at = vim.fn.strftime("%Y/%m/%d %H:%M:%S"), | ||
updated_by = opts.username, | ||
} | ||
local lines = serialize(header) | ||
|
||
vim.api.nvim_buf_set_lines(bufnr, 0, 0, false, lines) | ||
end, | ||
---@type fun(bufnr: number, opts: ft_nvim.HeaderConfig) | ||
update = function(bufnr, opts) | ||
local header = {} | ||
local lines = vim.api.nvim_buf_get_lines(bufnr, 0, #TEMPLATE, false) | ||
|
||
if not lines_are_header(lines) then | ||
return | ||
end | ||
|
||
for lineno, template_line in ipairs(TEMPLATE) do | ||
local line = lines[lineno] | ||
|
||
for annotation, key in string.gmatch(template_line, "(@([%w_]+)%.*)") do | ||
key = key:lower() | ||
local range = { string.find(template_line, annotation) } | ||
if key == "author" then | ||
header.username = string.match(line, "(%w+) <.*>") | ||
header.email = string.match(line, "%w+ <(.*)>") | ||
else | ||
---@diagnostic disable-next-line: param-type-mismatch | ||
header[key] = vim.fn.trim(string.sub(line, unpack(range))) | ||
end | ||
end | ||
end | ||
header.updated_at = vim.fn.strftime("%Y/%m/%d %H:%M:%S") | ||
header.updated_by = opts.username | ||
lines = serialize(header) | ||
vim.api.nvim_buf_set_lines(bufnr, 0, 12, false, lines) | ||
end, | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
---@class ft_nvim.HeaderConfig | ||
---@field enabled boolean | ||
---@field username string? | ||
---@field email string? | ||
--- | ||
---Example: | ||
---@code | ||
---require("ft_nvim.header").setup({ | ||
--- enabled = true, | ||
--- username = "marvin", | ||
--- email = "[email protected]", | ||
---}) | ||
---@endcode | ||
|
||
local header = require("ft_nvim.header.header") | ||
|
||
return { | ||
---@type fun(opts: ft_nvim.HeaderConfig) | ||
setup = function(opts) | ||
if not opts.enabled then | ||
return | ||
end | ||
|
||
vim.api.nvim_create_user_command("FtHeader", function() | ||
if header.buf_has_header(0) then | ||
header.update(0, opts) | ||
end | ||
header.insert(0, opts) | ||
end, { desc = "Upsert École 42 header" }) | ||
|
||
vim.api.nvim_create_autocmd("BufWritePre", { | ||
group = vim.api.nvim_create_augroup("FtHeader", { clear = true }), | ||
callback = function(ctx) | ||
header.update(ctx.buf, opts) | ||
end, | ||
}) | ||
end, | ||
---@type fun(opts: unknown): boolean | ||
validate = function(opts) | ||
if type(opts) ~= "table" then | ||
return false | ||
end | ||
|
||
if opts.enabled ~= nil and type(opts.enabled) ~= "boolean" then | ||
return false | ||
end | ||
|
||
if opts.username ~= nil and type(opts.username) ~= "string" then | ||
return false | ||
end | ||
|
||
if opts.email ~= nil and type(opts.email) ~= "string" then | ||
return false | ||
end | ||
|
||
return true | ||
end, | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,17 +1,30 @@ | ||
---@class ft_nvim.Config | ||
---@field norminette? ft_nvim.NorminetteConfig | ||
---@field header? ft_nvim.HeaderConfig | ||
|
||
---@type ft_nvim.Config | ||
local default_opts = { | ||
header = { | ||
enabled = true, | ||
username = "marvin", | ||
email = "[email protected]", | ||
}, | ||
norminette = { | ||
enabled = true, | ||
cmd = "norminette", | ||
}, | ||
} | ||
local header = require("ft_nvim.header") | ||
local norminette = require("ft_nvim.norminette") | ||
|
||
---@type fun(opts: ft_nvim.Config) | ||
local function validate(opts) | ||
vim.validate({ | ||
header = { | ||
opts.header, | ||
header.validate, | ||
"ft_nvim.HeaderConfig", | ||
}, | ||
norminette = { | ||
opts.norminette, | ||
norminette.validate, | ||
|
@@ -23,11 +36,15 @@ end | |
return { | ||
---@param opts ft_nvim.Config | ||
setup = function(opts) | ||
opts = vim.tbl_deep_extend("force", default_opts, opts or {}) | ||
validate(opts) | ||
opts = vim.tbl_deep_extend("force", default_opts, opts) | ||
|
||
if opts.norminette.enabled then | ||
norminette.setup(opts.norminette) | ||
end | ||
|
||
if opts.header.enabled then | ||
header.setup(opts.header) | ||
end | ||
end, | ||
} |