plugins/neogit: switch to mkNeovimPlugin

This commit is contained in:
Gaetan Lepage 2024-01-24 18:48:09 +01:00 committed by Gaétan Lepage
parent be87309e0c
commit 8c0bdb17e9
5 changed files with 790 additions and 244 deletions

View file

@ -43,7 +43,7 @@
./git/gitlinker.nix ./git/gitlinker.nix
./git/gitmessenger.nix ./git/gitmessenger.nix
./git/gitsigns.nix ./git/gitsigns.nix
./git/neogit.nix ./git/neogit
./languages/clangd-extensions.nix ./languages/clangd-extensions.nix
./languages/debugprint.nix ./languages/debugprint.nix

View file

@ -1,243 +0,0 @@
{
lib,
helpers,
config,
pkgs,
...
}:
with lib; let
cfg = config.plugins.neogit;
sectionDefaultsModule = types.submodule {
options = {
folded = mkOption {
type = types.nullOr types.bool;
default = null;
};
};
};
in {
options = {
plugins.neogit = {
enable = mkEnableOption "neogit";
package = helpers.mkPackageOption "neogit" pkgs.vimPlugins.neogit;
disableSigns = mkOption {
description = "Disable signs";
type = types.nullOr types.bool;
default = null;
};
disableHint = mkOption {
description = "Disable hint";
type = types.nullOr types.bool;
default = null;
};
disableContextHighlighting = mkOption {
description = "Disable the context highlighting";
type = types.nullOr types.bool;
default = null;
};
disableCommitConfirmation = mkOption {
description = "Disable the commit confirmation prompt";
type = types.nullOr types.bool;
default = null;
};
autoRefresh = mkOption {
description = "Enable Auto Refresh";
type = types.nullOr types.bool;
default = null;
};
disableBuiltinNotifications = mkOption {
description = "Disable builtin notifications";
type = types.nullOr types.bool;
default = null;
};
useMagitKeybindings = mkOption {
description = "Enable Magit keybindings";
type = types.nullOr types.bool;
default = null;
};
graphStyle = helpers.defaultNullOpts.mkEnumFirstDefault ["ascii" "unicode"] ''
"ascii" is the graph the git CLI generates
"unicode" is the graph like https://github.com/rbong/vim-flog
'';
commitPopup = mkOption {
description = "Commit popup configuration";
type = types.submodule {
options = {
kind = mkOption {
type = types.nullOr types.str;
default = null;
};
};
};
default = {};
};
kind = mkOption {
description = "The way of opening neogit";
type = types.nullOr types.str;
default = null;
};
signs = mkOption {
description = "Customize displayed signs";
type = types.submodule {
options = {
section = mkOption {
description = "Cosed and opened signs for sections";
type = types.nullOr (types.listOf types.str);
default = null;
};
item = mkOption {
description = "Cosed and opened signs for items";
type = types.nullOr (types.listOf types.str);
default = null;
};
hunk = mkOption {
description = "Cosed and opened signs for hunks";
type = types.nullOr (types.listOf types.str);
default = null;
};
};
};
default = {};
};
integrations = mkOption {
description = "Tools integration";
type = types.submodule {
options = {
diffview = mkOption {
description = "Enable diff popup";
type = types.bool;
default = false;
};
};
};
default = {};
};
sections = mkOption {
description = "Section configuration";
type = types.submodule {
options = {
untracked = mkOption {
description = "Options for untracked section";
type = types.nullOr sectionDefaultsModule;
default = null;
};
unstaged = mkOption {
description = "Options for unstaged section";
type = types.nullOr sectionDefaultsModule;
default = null;
};
staged = mkOption {
description = "Options for staged section";
type = types.nullOr sectionDefaultsModule;
default = null;
};
stashes = mkOption {
description = "Options for stashes section";
type = types.nullOr sectionDefaultsModule;
default = null;
};
unpulled = mkOption {
description = "Options for unpulled section";
type = types.nullOr sectionDefaultsModule;
default = null;
};
unmerged = mkOption {
description = "Options for unmerged section";
type = types.nullOr sectionDefaultsModule;
default = null;
};
recent = mkOption {
description = "Options for recent commits section";
type = types.nullOr sectionDefaultsModule;
default = null;
};
};
};
default = {};
};
mappings = mkOption {
description = "Custom mappings";
type = types.submodule {
options = {
status = mkOption {
type = types.nullOr (types.attrsOf (types.enum [
"Close"
"Depth1"
"Depth2"
"Depth3"
"Depth4"
"Toggle"
"Discard"
"Stage"
"StageUnstaged"
"StageAll"
"GoToFile"
"Unstaged"
"UnstagedStage"
"CommandHistory"
"RefreshBuffer"
"HelpPopup"
"PullPopup"
"PushPopup"
"CommitPopup"
"LogPopup"
"StashPopup"
"BranchPopup"
]));
default = null;
};
};
};
default = {};
};
};
};
config = let
setupOptions = with cfg;
helpers.toLuaObject {
inherit kind integrations signs sections mappings;
disable_signs = disableSigns;
disable_hint = disableHint;
disable_context_highlighting = disableContextHighlighting;
disable_commit_confirmation = disableCommitConfirmation;
auto_refresh = autoRefresh;
disable_builtin_notifications = disableBuiltinNotifications;
use_magit_keybindings = useMagitKeybindings;
commit_popup = commitPopup;
graph_style = graphStyle;
};
in
mkIf cfg.enable {
extraPlugins = with pkgs.vimPlugins;
[
cfg.package
plenary-nvim
]
++ optional cfg.integrations.diffview diffview-nvim;
extraPackages = [pkgs.git];
extraConfigLua = ''
require('neogit').setup(${setupOptions})
'';
};
}

View file

@ -0,0 +1,104 @@
{
lib,
helpers,
config,
pkgs,
...
}:
with lib;
helpers.neovim-plugin.mkNeovimPlugin config {
name = "neogit";
defaultPackage = pkgs.vimPlugins.neogit;
extraPackages = [pkgs.git];
maintainers = [maintainers.GaetanLepage];
# TODO introduced 2024-02-29: remove 2024-04-29
deprecateExtraOptions = true;
imports =
map (
optionPath:
mkRemovedOptionModule
(["plugins" "neogit"] ++ optionPath)
"This option has been removed upstream. Please refer to the plugin documentation to update your configuration."
)
[
["disableCommitConfirmation"]
["disableBuiltinNotifications"]
["useMagitKeybindings "]
["commitPopup"]
["sections" "unmerged"]
["sections" "unpulled"]
];
optionsRenamedToSettings = [
"disableSigns"
"disableHint"
"disableContextHighlighting"
"autoRefresh"
"graphStyle"
"kind"
"signs"
"integrations"
["sections" "untracked"]
["sections" "unstaged"]
["sections" "staged"]
["sections" "stashes"]
["sections" "recent"]
"mappings"
];
settingsOptions = import ./options.nix {inherit lib helpers;};
settingsExample = {
kind = "floating";
commit_popup.kind = "floating";
preview_buffer.kind = "floating";
popup.kind = "floating";
integrations.diffview = false;
disable_commit_confirmation = true;
disable_builtin_notifications = true;
sections = {
untracked.folded = false;
unstaged.folded = false;
staged.folded = false;
stashes.folded = false;
unpulled.folded = false;
unmerged.folded = true;
recent.folded = true;
};
mappings = {
status = {
l = "Toggle";
a = "Stage";
};
};
};
extraConfig = cfg: {
assertions =
map
(
name: {
assertion = let
enabled = cfg.settings.integrations.${name};
isEnabled = (isBool enabled) && enabled;
in
isEnabled
-> config.plugins.${name}.enable;
message = ''
Nixvim (plugins.neogit): You have enabled the `${name}` integration, but `plugins.${name}.enable` is `false`.
'';
}
)
[
"telescope"
"diffview"
"fzf-lua"
];
extraPackages =
optional
(hasInfix "which" (cfg.settings.commit_view.verify_commit.__raw or ""))
pkgs.which;
};
}

View file

@ -0,0 +1,427 @@
{
lib,
helpers,
}:
with lib; let
mkKindOption =
helpers.defaultNullOpts.mkEnum
[
"split"
"vsplit"
"split_above"
"tab"
"floating"
"replace"
"auto"
];
in {
filewatcher = {
interval = helpers.defaultNullOpts.mkUnsignedInt 1000 ''
Interval between two refreshes.
'';
enabled = helpers.defaultNullOpts.mkBool true ''
When enabled, will watch the `.git/` directory for changes and refresh the status buffer
in response to filesystem events.
'';
};
graph_style = helpers.defaultNullOpts.mkEnumFirstDefault ["ascii" "unicode"] ''
- "ascii" is the graph the git CLI generates
- "unicode" is the graph like https://github.com/rbong/vim-flog
'';
disable_hint = helpers.defaultNullOpts.mkBool false ''
Hides the hints at the top of the status buffer.
'';
disable_context_highlighting = helpers.defaultNullOpts.mkBool false ''
Disables changing the buffer highlights based on where the cursor is.
'';
disable_signs = helpers.defaultNullOpts.mkBool false ''
Disables signs for sections/items/hunks.
'';
git_services =
helpers.defaultNullOpts.mkAttrsOf types.str
''
{
"github.com" = "https://github.com/$\{owner}/$\{repository}/compare/$\{branch_name}?expand=1";
"bitbucket.org" = "https://bitbucket.org/$\{owner}/$\{repository}/pull-requests/new?source=$\{branch_name}&t=1";
"gitlab.com" = "https://gitlab.com/$\{owner}/$\{repository}/merge_requests/new?merge_request[source_branch]=$\{branch_name}";
}
''
"Used to generate URL's for branch popup action 'pull request'.";
fetch_after_checkout = helpers.defaultNullOpts.mkBool false ''
Perform a fetch if the newly checked out branch has an upstream or pushRemote set.
'';
telescope_sorter = helpers.mkNullOrLuaFn ''
Allows a different telescope sorter.
Defaults to 'fuzzy_with_index_bias'.
The example below will use the native fzf sorter instead.
By default, this function returns `nil`.
Example:
```lua
require("telescope").extensions.fzf.native_fzf_sorter
```
'';
disable_insert_on_commit =
helpers.defaultNullOpts.mkNullable
(with types; either bool (enum ["auto"]))
"auto"
''
Changes what mode the Commit Editor starts in.
`true` will leave nvim in normal mode, `false` will change nvim to insert mode, and `"auto"`
will change nvim to insert mode IF the commit message is empty, otherwise leaving it in normal
mode.
'';
use_per_project_settings = helpers.defaultNullOpts.mkBool true ''
Scope persisted settings on a per-project basis.
'';
remember_settings = helpers.defaultNullOpts.mkBool true ''
Persist the values of switches/options within and across sessions.
'';
auto_refresh = helpers.defaultNullOpts.mkBool true ''
Neogit refreshes its internal state after specific events, which can be expensive depending on
the repository size.
Disabling `auto_refresh` will make it so you have to manually refresh the status after you open
it.
'';
sort_branches = helpers.defaultNullOpts.mkStr "-committerdate" ''
Value used for `--sort` option for `git branch` command.
By default, branches will be sorted by commit date descending.
Flag description: https://git-scm.com/docs/git-branch#Documentation/git-branch.txt---sortltkeygt
Sorting keys: https://git-scm.com/docs/git-for-each-ref#_options
'';
kind = mkKindOption "tab" ''
Change the default way of opening neogit.
'';
disable_line_numbers = helpers.defaultNullOpts.mkBool true ''
Disable line numbers and relative line numbers.
'';
console_timeout = helpers.defaultNullOpts.mkUnsignedInt 2000 ''
The time after which an output console is shown for slow running commands.
'';
auto_show_console = helpers.defaultNullOpts.mkBool true ''
Automatically show console if a command takes more than `consoleTimeout` milliseconds.
'';
status = {
recent_commit_count = helpers.defaultNullOpts.mkUnsignedInt 10 ''
Recent commit count in the status buffer.
'';
};
commit_editor = {
kind = mkKindOption "auto" "The type of window that should be opened.";
};
commit_select_view = {
kind = mkKindOption "tab" "The type of window that should be opened.";
};
commit_view = {
kind = mkKindOption "vsplit" "The type of window that should be opened.";
verify_commit = helpers.mkNullOrStrLuaOr types.bool ''
Show commit signature information in the buffer.
Can be set to true or false, otherwise we try to find the binary.
Default: "os.execute('which gpg') == 0"
'';
};
log_view = {
kind = mkKindOption "tab" "The type of window that should be opened.";
};
rebase_editor = {
kind = mkKindOption "auto" "The type of window that should be opened.";
};
reflog_view = {
kind = mkKindOption "tab" "The type of window that should be opened.";
};
merge_editor = {
kind = mkKindOption "auto" "The type of window that should be opened.";
};
description_editor = {
kind = mkKindOption "auto" "The type of window that should be opened.";
};
tag_editor = {
kind = mkKindOption "auto" "The type of window that should be opened.";
};
preview_buffer = {
kind = mkKindOption "split" "The type of window that should be opened.";
};
popup = {
kind = mkKindOption "split" "The type of window that should be opened.";
};
signs =
mapAttrs
(n: v:
helpers.defaultNullOpts.mkListOf types.str ''["${v.closed}" "${v.opened}"]'' ''
The icons to use for open and closed ${n}s.
'')
{
hunk = {
closed = "";
opened = "";
};
item = {
closed = ">";
opened = "v";
};
section = {
closed = ">";
opened = "v";
};
};
integrations = {
telescope = helpers.mkNullOrOption types.bool ''
If enabled, use telescope for menu selection rather than `vim.ui.select`.
Allows multi-select and some things that `vim.ui.select` doesn't.
'';
diffview = helpers.mkNullOrOption types.bool ''
Neogit only provides inline diffs.
If you want a more traditional way to look at diffs, you can use `diffview`.
The diffview integration enables the diff popup.
'';
fzf-lua = helpers.mkNullOrOption types.bool ''
If enabled, uses fzf-lua for menu selection.
If the telescope integration is also selected then telescope is used instead.
'';
};
sections =
mapAttrs
(
name: default:
mkOption {
type = with types;
nullOr (submodule {
options = {
folded = mkOption {
type = types.bool;
description = "Whether or not this section should be open or closed by default.";
};
hidden = mkOption {
type = types.bool;
description = "Whether or not this section should be shown.";
};
};
});
inherit default;
description = "Settings for the ${name} section";
}
)
{
sequencer = {
folded = false;
hidden = false;
};
untracked = {
folded = false;
hidden = false;
};
unstaged = {
folded = false;
hidden = false;
};
staged = {
folded = false;
hidden = false;
};
stashes = {
folded = true;
hidden = false;
};
unpulled_upstream = {
folded = true;
hidden = false;
};
unmerged_upstream = {
folded = false;
hidden = false;
};
unpulled_pushRemote = {
folded = true;
hidden = false;
};
unmerged_pushRemote = {
folded = false;
hidden = false;
};
recent = {
folded = true;
hidden = false;
};
rebase = {
folded = true;
hidden = false;
};
};
ignored_settings =
helpers.defaultNullOpts.mkListOf types.str
''
[
"NeogitPushPopup--force-with-lease"
"NeogitPushPopup--force"
"NeogitPullPopup--rebase"
"NeogitCommitPopup--allow-empty"
"NeogitRevertPopup--no-edit"
]
''
''
Table of settings to never persist.
Uses format "Filetype--cli-value".
'';
mappings = let
mkMappingOption = helpers.defaultNullOpts.mkAttrsOf (with types; either str (enum [false]));
in {
commit_editor =
mkMappingOption
''
{
q = "Close";
"<c-c><c-c>" = "Submit";
"<c-c><c-k>" = "Abort";
}
''
"Mappings for the commit editor.";
rebase_editor =
mkMappingOption
''
{
p = "Pick";
r = "Reword";
e = "Edit";
s = "Squash";
f = "Fixup";
x = "Execute";
d = "Drop";
b = "Break";
q = "Close";
"<cr>" = "OpenCommit";
gk = "MoveUp";
gj = "MoveDown";
"<c-c><c-c>" = "Submit";
"<c-c><c-k>" = "Abort";
}
''
"Mappings for the rebase editor.";
finder =
mkMappingOption
''
{
"<cr>" = "Select";
"<c-c>" = "Close";
"<esc>" = "Close";
"<c-n>" = "Next";
"<c-p>" = "Previous";
"<down>" = "Next";
"<up>" = "Previous";
"<tab>" = "MultiselectToggleNext";
"<s-tab>" = "MultiselectTogglePrevious";
"<c-j>" = "NOP";
}
''
"Mappings for the finder.";
popup =
mkMappingOption
''
{
"?" = "HelpPopup";
A = "CherryPickPopup";
D = "DiffPopup";
M = "RemotePopup";
P = "PushPopup";
X = "ResetPopup";
Z = "StashPopup";
b = "BranchPopup";
c = "CommitPopup";
f = "FetchPopup";
l = "LogPopup";
m = "MergePopup";
p = "PullPopup";
r = "RebasePopup";
v = "RevertPopup";
}
''
"Mappings for popups.";
status =
mkMappingOption
''
{
q = "Close";
I = "InitRepo";
"1" = "Depth1";
"2" = "Depth2";
"3" = "Depth3";
"4" = "Depth4";
"<tab>" = "Toggle";
x = "Discard";
s = "Stage";
S = "StageUnstaged";
"<c-s>" = "StageAll";
u = "Unstage";
U = "UnstageStaged";
"$" = "CommandHistory";
"#" = "Console";
Y = "YankSelected";
"<c-r>" = "RefreshBuffer";
"<enter>" = "GoToFile";
"<c-v>" = "VSplitOpen";
"<c-x>" = "SplitOpen";
"<c-t>" = "TabOpen";
"{" = "GoToPreviousHunkHeader";
"}" = "GoToNextHunkHeader";
}
''
"Mappings for status.";
};
notification_icon = helpers.defaultNullOpts.mkStr "󰊢" ''
Icon for notifications.
'';
use_default_keymaps = helpers.defaultNullOpts.mkBool true ''
Set to false if you want to be responsible for creating _ALL_ keymappings.
'';
highlight =
genAttrs ["italic" "bold" "underline"]
(
n:
helpers.defaultNullOpts.mkBool true "Set the ${n} property of the highlight group."
);
}

View file

@ -0,0 +1,258 @@
{pkgs, ...}: {
empty = {
plugins.neogit.enable = true;
};
defaults = {
# Otherwise `os.execute('which gpg')` returns an error and make the whole test derivation fail
# (option `settings.commit_view.verify_commit`)
extraPackages = [pkgs.gnupg];
plugins.neogit = {
enable = true;
settings = {
filewatcher = {
interval = 1000;
enabled = true;
};
graph_style = "ascii";
disable_hint = false;
disable_context_highlighting = false;
disable_signs = false;
git_services = {
"github.com" = "https://github.com/$\{owner}/$\{repository}/compare/$\{branch_name}?expand=1";
"bitbucket.org" = "https://bitbucket.org/$\{owner}/$\{repository}/pull-requests/new?source=$\{branch_name}&t=1";
"gitlab.com" = "https://gitlab.com/$\{owner}/$\{repository}/merge_requests/new?merge_request[source_branch]=$\{branch_name}";
};
telescope_sorter = null;
disable_insert_on_commit = "auto";
use_per_project_settings = true;
remember_settings = true;
auto_refresh = true;
sort_branches = "-committerdate";
kind = "tab";
disable_line_numbers = true;
console_timeout = 2000;
auto_show_console = true;
status = {
recent_commit_count = 10;
};
commit_editor = {
kind = "auto";
};
commit_select_view = {
kind = "tab";
};
commit_view = {
kind = "vsplit";
verify_commit = "os.execute('which gpg') == 0";
};
log_view = {
kind = "tab";
};
rebase_editor = {
kind = "auto";
};
reflog_view = {
kind = "tab";
};
merge_editor = {
kind = "auto";
};
description_editor = {
kind = "auto";
};
tag_editor = {
kind = "auto";
};
preview_buffer = {
kind = "split";
};
popup = {
kind = "split";
};
signs = {
hunk = ["" ""];
item = [">" "v"];
section = [">" "v"];
};
integrations = {
telescope = null;
diffview = null;
fzf-lua = null;
};
sections = {
sequencer = {
folded = false;
hidden = false;
};
untracked = {
folded = false;
hidden = false;
};
unstaged = {
folded = false;
hidden = false;
};
staged = {
folded = false;
hidden = false;
};
stashes = {
folded = true;
hidden = false;
};
unpulled_upstream = {
folded = true;
hidden = false;
};
unmerged_upstream = {
folded = false;
hidden = false;
};
unpulled_pushRemote = {
folded = true;
hidden = false;
};
unmerged_pushRemote = {
folded = false;
hidden = false;
};
recent = {
folded = true;
hidden = false;
};
rebase = {
folded = true;
hidden = false;
};
};
ignored_settings = [
"NeogitPushPopup--force-with-lease"
"NeogitPushPopup--force"
"NeogitPullPopup--rebase"
"NeogitCommitPopup--allow-empty"
"NeogitRevertPopup--no-edit"
];
mappings = {
commit_editor = {
q = "Close";
"<c-c><c-c>" = "Submit";
"<c-c><c-k>" = "Abort";
};
rebase_editor = {
p = "Pick";
r = "Reword";
e = "Edit";
s = "Squash";
f = "Fixup";
x = "Execute";
d = "Drop";
b = "Break";
q = "Close";
"<cr>" = "OpenCommit";
gk = "MoveUp";
gj = "MoveDown";
"<c-c><c-c>" = "Submit";
"<c-c><c-k>" = "Abort";
};
finder = {
"<cr>" = "Select";
"<c-c>" = "Close";
"<esc>" = "Close";
"<c-n>" = "Next";
"<c-p>" = "Previous";
"<down>" = "Next";
"<up>" = "Previous";
"<tab>" = "MultiselectToggleNext";
"<s-tab>" = "MultiselectTogglePrevious";
"<c-j>" = "NOP";
};
popup = {
"?" = "HelpPopup";
A = "CherryPickPopup";
D = "DiffPopup";
M = "RemotePopup";
P = "PushPopup";
X = "ResetPopup";
Z = "StashPopup";
b = "BranchPopup";
c = "CommitPopup";
f = "FetchPopup";
l = "LogPopup";
m = "MergePopup";
p = "PullPopup";
r = "RebasePopup";
v = "RevertPopup";
};
status = {
q = "Close";
I = "InitRepo";
"1" = "Depth1";
"2" = "Depth2";
"3" = "Depth3";
"4" = "Depth4";
"<tab>" = "Toggle";
x = "Discard";
s = "Stage";
S = "StageUnstaged";
"<c-s>" = "StageAll";
u = "Unstage";
U = "UnstageStaged";
"$" = "CommandHistory";
"#" = "Console";
Y = "YankSelected";
"<c-r>" = "RefreshBuffer";
"<enter>" = "GoToFile";
"<c-v>" = "VSplitOpen";
"<c-x>" = "SplitOpen";
"<c-t>" = "TabOpen";
"{" = "GoToPreviousHunkHeader";
"}" = "GoToNextHunkHeader";
};
};
notification_icon = "󰊢";
use_default_keymaps = true;
highlight = {
italic = true;
bold = true;
underline = true;
};
};
};
};
example = {
plugins.neogit = {
enable = true;
settings = {
kind = "floating";
commit_popup.kind = "floating";
preview_buffer.kind = "floating";
popup.kind = "floating";
integrations.diffview = false;
disable_commit_confirmation = true;
disable_builtin_notifications = true;
sections = {
untracked = {
folded = true;
hidden = true;
};
unmerged = {
folded = true;
hidden = false;
};
};
mappings = {
status = {
l = "Toggle";
a = "Stage";
};
};
};
};
};
}