add fish and neovim configuration

This commit is contained in:
Michele Guerini Rocco 2023-07-11 22:05:57 +02:00
parent 53c3d49f2f
commit cb8138dcac
Signed by: rnhmjoj
GPG Key ID: BFBAF4C975F76450
4 changed files with 697 additions and 1 deletions

View File

@ -12,6 +12,8 @@
./nameserver.nix
./custom
./secrets
./fish.nix
./neovim.nix
];
### State

212
fish.nix Normal file
View File

@ -0,0 +1,212 @@
{ ... }:
{
programs.fish.shellAbbrs =
{ e = "nvim";
l = "ls -lh";
ip = "ip -c";
iftop = "iftop -m 70M";
};
programs.fish.shellAliases =
{ namecoin-cli = "namecoin-cli -conf=$XDG_CONFIG_HOME/namecoin"; };
programs.fish.loginShellInit =
''
# Start abduco in ssh
if set -q SSH_CLIENT
# start abduco on ssh
if not set -q ABDUCO_SESSION
exec abduco -A ssh fish
else if test $SHLVL -eq 1
tput rmcup
end
end
'';
programs.fish.interactiveShellInit =
''
## Fish settings
# mixed emacs/vi
fish_hybrid_key_bindings
# kj to normal mode
bind -M insert kj "
if commandline -P;
commandline -f cancel;
else;
set fish_bind_mode default;
commandline -f backward-char repaint-mode;
end"
# fix unquoted URLs
set -U fish_features ampersand-nobg-in-token qmark-noglob
# change default cursor
set fish_cursor_insert underscore
## Color scheme
# syntax highlighting
set fish_color_command green
set fish_color_param normal
set fish_color_comment brcyan
set fish_color_operator purple
set fish_color_escape bryellow
set fish_color_redirection blue
set fish_color_selection --background=black
# completion/history
set fish_pager_color_prefix yellow
set fish_pager_color_description brblue
set fish_pager_color_progress brblack --background=black
set fish_color_search_match --background=black
# man pages colors
# bold, blink stop
set -x LESS_TERMCAP_md (set_color -o bryellow)
set -x LESS_TERMCAP_mb (set_color -u magenta)
set -x LESS_TERMCAP_me (set_color normal)
# standout start/stop
set -x LESS_TERMCAP_so (set_color brblue -b black)
set -x LESS_TERMCAP_se (set_color normal -b normal)
# underline start/stop
set -x LESS_TERMCAP_us (set_color -u brmagenta)
set -x LESS_TERMCAP_ue (set_color normal)
# used default LS_COLORS
eval (dircolors | sed 's/\(\w\+\)=/set \1 /')
## Aliases
# start process and detach
function start
nohup $argv > /dev/null 2>&1 &; disown
end
# start process without network access
function nnet
unshare -nc fish -ic "$argv"
end
set conf (systemctl cat namecoind | awk -F 'conf=| ' '/ExecStart/ {print $3}')
namecoin-cli -conf=$conf $argv
# interactively rename files
function vimv
set tmp (mktemp --tmpdir -d vimv.XXX)
if set -q argv[1]
# directory listing
find $argv[1] -maxdepth 1 | sort | cat -n | tee $tmp/before > $tmp/after
else
# read from stdin
cat -n - | tee $tmp/before > $tmp/after
end
$EDITOR $tmp/after
# only print differing lines
awk '
NR==FNR { line=$0; sub($1, "", line); sub(/\s+/, "", line); lines[$1]=line; next }
NR!=FNR { line=$0; sub($1, "", line); sub(/\s+/, "", line);
if (!($1 in lines)) { printf("rm -vr \"%s\"\n", line); next }
if (lines[$1] != line) printf("mv -vin \"%s\" \"%s\"\n", line, lines[$1])
}
' $tmp/after $tmp/before | sh
rm -r $tmp
end
'';
programs.fish.promptInit =
''
# Outputs colored text
function color
set_color $argv[1]
for i in $argv[2..-1]
echo -n $i
end
set_color normal
end
# Git branch info
function git_branch
if not test -f .git/HEAD
return
end
set branch (git rev-parse --abbrev-ref HEAD 2> /dev/null)
if test $status -ne 0
set branch (cut -f 3 -d '/' .git/HEAD)
else if test $branch = HEAD
set branch (head -c 10 .git/HEAD)
end
timeout 0.1 git diff-files --quiet 2>/dev/null
if test $status -eq 1
set branch (color yellow $branch'*')
else
set branch (color green $branch)
end
timeout 0.1 git status --porcelain 2>/dev/null 1>| read untracked
if test -n "$untracked"
set dirty (color red '*')
end
echo " <$branch$dirty>"
end
# Left prompt
function fish_prompt
if fish_is_root_user
set prompt (color blue Λ)
set user (color red (whoami))
else
set prompt (color blue λ)
set user (color green (whoami))
end
if test \( "$LINES" -lt 10 \) -o \( "$COLUMNS" -lt 30 \)
echo "$prompt "
return
end
if set -q SSH_CLIENT
set host (color yellow (hostname))
else
set host (color green (hostname))
end
set git (git_branch)
set path (color cyan (prompt_pwd))
switch $fish_bind_mode
case default
set mode (color blue n)
case insert
set mode (color red i)
case visual
set mode (color yellow v)
end
echo "$user@$host $mode$path$git"
echo "$prompt "
end
# Right prompt
function fish_right_prompt
set code $status
if test $code -ne 0
set exitcode (color red $code" ")
end
if string match -q '/nix*' $PATH[1]
set nix " <"(color blue nix)">"
end
echo "$exitcode$nix"
end
function fish_mode_prompt; end
function fish_greeting; end
'';
}

479
neovim.nix Normal file
View File

@ -0,0 +1,479 @@
{ config, lib, pkgs, ... }:
let
frameline = pkgs.callPackage (pkgs.fetchFromGitea
{ domain = "maxwell.ydns.eu/git";
owner = "rnhmjoj";
repo = "nvim-frameline";
rev = "v0.1.0";
sha256 = "PrTSSoXbu+qtTsJUv81z+MuTUmB1RHLPEWFQQnu6+J8=";
}) { };
plugins = with pkgs.vimPlugins;
[ # UI
undotree gitsigns-nvim
frameline nvim-fzf
# Syntax
vim-pandoc-syntax
nix-queries
(nvim-treesitter.withPlugins (p: with p;
[ bash fish
html css markdown
nix python
]))
# Misc
vim-fugitive supertab neomake
auto-pairs plenary-nvim
];
pack = pkgs.linkFarm "neovim-plugins"
(map (pkg:
{ name = "pack/${pkg.name}/start/${pkg.name}";
path = toString pkg;
}) (lib.concatMap (p: [p] ++ p.dependencies or []) plugins));
neovim-wrapped = pkgs.runCommand "${pkgs.neovim-unwrapped.name}"
{ nativeBuildInputs = [ pkgs.makeWrapper ]; }
''
mkdir -p "$out"
makeWrapper '${pkgs.neovim-unwrapped}/bin/nvim' "$out/bin/nvim" \
--add-flags "-u ${conf}"
'';
nix-queries = pkgs.writeTextDir "/queries/nix/injections.scm"
''
; /*language*/ highlight (too slow)
; ((comment) @language
; [
; (string_expression (string_fragment) @content)
; (indented_string_expression (string_fragment) @content)
; ]
; (#gsub! @language "/%*%s*([%w%p]+)%s*%*/" "%1"))
; @combined
; writeText highlight
(apply_expression
function:
(apply_expression
function: (_) @_func
argument: (string_expression (string_fragment) @language))
argument: [(string_expression (string_fragment) @content)
(indented_string_expression (string_fragment) @content)]
(#match? @_func "(^|\\.)writeText(Dir)?$")
(#gsub! @language ".*%.(.*)" "%1"))
@combined
'';
conf = pkgs.writeText "init.lua" ''
local opt = vim.opt
local cmd = vim.api.nvim_command
local keymap = vim.keymap.set
local autocmd = vim.api.nvim_create_autocmd
-- Load plugins
opt.packpath = ${builtins.toJSON pack}
opt.runtimepath:prepend(${builtins.toJSON pack})
--
-- Options
--
local cache = os.getenv('XDG_CACHE_HOME')..'/nvim'
opt.directory = cache..'/tmp'
opt.backupdir = cache..'/tmp'
opt.shadafile = cache..'/shada'
opt.undodir = cache..'/undo'
opt.hidden = true -- Hide buffers
opt.mouse = 'a' -- Enable mouse support
opt.ignorecase = true -- Case insensitive search...
opt.smartcase = true -- ...for lowercase terms
opt.fsync = true -- Sync writes
opt.swapfile = false -- Disable swap files
opt.writebackup = true -- Backup file before overwriting...
opt.backup = false -- ...but delete it on success
opt.undofile = true -- Store all changes
opt.modeline = false -- Disable for Security
opt.showmatch = true -- Highlight matched parenthesis
opt.clipboard = 'unnamedplus' -- Yank to clipboard
-- Files to ignore
opt.wildignore = {
'*.so', '*.hi', '*.a', '*.la', '*.mod',
'*/__pycache__/*',
'*/dist/*',
'*/result/*',
'*/.git/*'
}
opt.shiftwidth = 2 -- Tabs
opt.tabstop = 2 --
opt.expandtab = true --
opt.number = true -- Line numbering
opt.smartindent = true -- Indentation
opt.showmode = false -- Disable printing of mode changes
opt.ruler = false -- Already in statusline
opt.fillchars = {
eob=' ', -- Hide ~ on empty lines
vert='', -- make vertical split sign better
fold=' ', -- Hide . in fold markers
}
opt.foldmethod = "expr" -- Folding
opt.foldexpr = 'nvim_treesitter#foldexpr()' --
opt.foldlevel = 99 -- open by default
--
-- OSC 52 clipboard
--
--
if os.getenv('DISPLAY') == nil then
function copy(sel)
return function(lines, _)
local data = vim.fn.system([[base64 -w0]], lines)
io.stdout:write('\027]52;'..sel..';'..data..'\a')
vim.g.fallback_clip = lines
end
end
function paste(sel)
-- currently impossible to implement
return function() return {vim.g.fallback_clip, ""} end
end
vim.g.clipboard = {
name='ssh',
copy={['*']=copy's', ['+']=copy'c'},
paste={['*']=paste's', ['+']=paste'c'},
}
end
--
-- Terminal mode
--
-- Hide some UI elements
autocmd('TermOpen', {pattern='*', command='setlocal nonumber'})
autocmd('TermEnter', {pattern='*', command='set noshowcmd'})
autocmd('TermLeave', {pattern='*', command='set showcmd'})
-- Exit without confirmation
autocmd('TermClose', {pattern='*', command='call feedkeys("\\<CR>")'})
keymap('t', '<C-b>', '<C-\\><C-n>', {noremap=true}) -- Easier escape
keymap('n', '<C-b>', '<Nop>', {noremap=true}) --
keymap('n', '<C-w>-', ':split +term<CR>', {silent=true}) -- Tmux-like moves
keymap('n', '<C-w>|', ':vsplit +term<CR>', {silent=true}) --
keymap('n', '<C-w>t', ':tabnew +term<CR>', {silent=true}) --
keymap('n', '<C-w>c', ':quit<CR>', {silent=true}) --
--
-- Keybindings
--
vim.g.mapleader = ','
function listToggle()
for _, win in ipairs(vim.fn.getwininfo()) do
if win.loclist == 1 then return cmd('lclose') end
end
cmd('lopen')
end
fzf = require'fzf'
function searchFiles()
local query = [[\( -name .git -o -name __pycache__ -o -path ./dist -o -path ./build \) -prune -o -type f]]
coroutine.wrap(function()
res = fzf.fzf('find '..query, "", {border='none'})
cmd('edit '..res[1])
end)()
end
function searchCommands()
coroutine.wrap(function()
local history = {}
for i = 1, vim.fn.histnr("cmd") do
history[i] = vim.fn.histget("cmd", i)
end
res = fzf.fzf(history, "", {border='none'})
vim.fn.feedkeys(':'..res[1], 't')
end)()
end
keymap('n', '<C-p>', searchFiles, {silent=true}) -- Fuzzy search files
keymap('n', '<C-e>', searchCommands, {silent=true}) -- Fuzzy search command history
keymap('n', '<Leader>u', ':UndotreeToggle<CR>', {silent=true}) -- Toggle UndoTree
keymap('n', '<leader>l', listToggle, {silent=true}) -- Toggle Neomake errors
keymap('i', 'kj', '<ESC>', {noremap=true}) -- Exit with kj
keymap('n', 'o', 'o<ESC>', {noremap=true}) -- Add empty lines
keymap('n', 'O', 'O<ESC>', {noremap=true}) --
keymap('x', 'p', 'p:let @+=@0<CR>', {noremap=true, silent=true}) -- Keep selection after p
keymap('c', 'w!!', 'w !sudo tee >/dev/null %', {silent=true}) -- Save with sudo
--
-- Colors
--
opt.bg = 'light' -- Use dark colors
function color(group, args)
vim.api.nvim_set_hl(0, group, args)
end
-- Source code
color('Cursor', {ctermfg=14})
color('Keyword', {ctermfg=04})
color('Define', {ctermfg=03})
color('Type', {ctermfg=06})
color('Identifier', {ctermfg=13})
color('Constant', {ctermfg=03})
color('Function', {ctermfg=02})
color('Include', {ctermfg=04})
color('Statement', {ctermfg=11})
color('String', {ctermfg=03})
color('Number', {ctermfg=04})
color('Comment', {ctermfg=07})
color('SpecialComment', {ctermfg=15})
color('Operator', {ctermfg='none'})
color('Conceal', {ctermfg='none', ctermbg='none'})
-- Text
color('Title', {ctermfg=4})
color('Special', {ctermfg=12})
color('Delimiter', {ctermfg=1})
color('PandocReferenceURL', {ctermfg=3})
color('PandocCiteKey', {ctermfg=6})
color('PandocTableDelims', {ctermfg=8})
color('texBeginEndName', {ctermfg=2})
color('Error', {ctermfg='none', ctermbg='none', underline=true})
-- Editor UI
color('NonText', {ctermfg=0})
color('LineNr', {ctermfg=8})
color('Pmenu', {ctermfg=12, ctermbg=0})
color('Folded', {ctermfg=7, ctermbg=0, cterm={}})
color('VertSplit', {ctermfg=8, cterm={}})
color('FoldColumn', {ctermfg='none', cterm={}})
color('Visual', {ctermfg='none', ctermbg=0})
color('Search', {ctermfg='none', ctermbg=0})
-- Diff mode
color('DiffAdd', {ctermfg=2, ctermbg=0, underline=true})
color('DiffChange', {ctermfg=3, ctermbg=0, underline=true})
color('DiffText', {ctermfg=1, ctermbg=0, underline=true})
color('DiffDelete', {ctermfg=0, ctermbg=1, underline=true})
-- Spelling
color('SpellBad', {ctermfg=1, ctermbg=0, underline=true})
color('SpellCap', {ctermfg=3, underline=true})
-- Neomake
color('NeomakeWarning', {ctermfg=3, underline=true})
color('ErrorMsg', {ctermfg=1, ctermbg='none'})
color('WarningMsg', {ctermfg=3})
-- Git signs
color('SignColumn', {ctermfg=1, ctermbg='none', cterm={}})
color('GitAdd', {ctermfg=2})
color('GitChange', {ctermfg=3})
color('GitDelete', {ctermfg=1})
-- Statusline
color('StatusLine', {ctermfg=8, ctermbg=0, cterm={}})
color('StatusLineNC', {ctermfg=4, ctermbg=0, cterm={}})
color('User1', {ctermfg=8, ctermbg=0}) -- base
color('User2', {ctermfg=3, ctermbg=0}) -- location
color('StatusLineErr', {ctermfg=0, ctermbg=1})
color('StatusLineWarn', {ctermfg=0, ctermbg=3})
color('TablineTab', {ctermfg=8, ctermbg=0})
color('TablineTabCur', {ctermfg=7, ctermbg=8})
color('ModeNormal', {ctermfg=7, ctermbg=14})
color('ModeInsert', {ctermfg=7, ctermbg=1})
color('ModeCommand', {ctermfg=7, ctermbg=4})
color('ModeVisual', {ctermfg=7, ctermbg=3})
color('ModeVLine', {ctermfg=7, ctermbg=11})
color('ModeVBloc', {ctermfg=7, ctermbg=11})
color('ModeTerm', {ctermfg=7, ctermbg=2})
--
-- Plugin options
--
-- Neomake
vim.call('neomake#configure#automake', 'nwr', 750)
vim.g.neomake_warning_sign = {text='W', texthl='WarningMsg'}
vim.g.neomake_error_sign = {text='E', texthl='ErrorMsg'}
vim.g.neomake_highlight_lines = 1
vim.g.neomake_virtualtext_current_error = 0
-- Pandoc Markdown
autocmd({'BufNewFile', 'BufFilePre', 'BufRead'},
{pattern='*.md', command='set filetype=markdown.pandoc'})
-- Git signs
require'gitsigns'.setup{
signs={
add = {hl='GitAdd' , text='+'},
change = {hl='GitChange', text='δ'},
delete = {hl='GitDelete', text='-'},
topdelete = {hl='GitDelete', text=''},
changedelete = {hl='GitChange', text='~'},
},
keymaps={
['n <leader>gb'] = ':lua require"gitsigns".blame_line(true)<CR>',
['n <leader>gp'] = ':lua require"gitsigns".preview_hunk()<CR>',
}
}
-- Tree-sitter
require'nvim-treesitter.configs'.setup{
highlight={enable=true},
indent={enable=true},
}
-- Non built-in filetypes
autocmd({'BufNewFile', 'BufRead'},
{pattern='*.nix', command='setlocal filetype=nix'})
--
-- Statusline
--
--
local frameline = require 'frameline'
local utils = frameline.utils
function mode(win, buf)
if not win.is_active then return end
local k = vim.api.nvim_get_mode().mode
local modes = {
n={'Normal', 'Normal'},
i={'Insert', 'Insert'},
R={'Replas', 'Insert'},
v={'Visual', 'Visual'},
V={'VLine', 'VLine'},
t={'Termin', 'Term'},
['']={'VBloc', 'VBloc'}
}
return utils.highlight('Mode'..modes[k][2], ' '..modes[k][1]..' ')
end
function branch(_, buf)
local head = vim.fn.FugitiveHead()
if buf.modifiable and head ~= "" then return ' '..head end
end
function filename(_, buf)
local delta = ""
if buf.modified then delta = 'Δ' end
if not buf.modifiable then delta = '' end
local fname = buf.name ~= "" and utils.filename or 'new-file'
return delta..fname
end
function neomake()
local res, msg = vim.call('neomake#statusline#LoclistCounts'), ""
if res.E then
msg = msg..utils.highlight('StatusLineErr', ' '..res.E..'E ')
end
if res.W then
msg = msg..utils.highlight('StatusLineWarn', ' '..res.W..'W ')
end
return msg
end
function readonly(_, buf)
if buf.modifiable and buf.readonly then return '' end
end
function encoding(_, buf)
return buf.fileencoding ~= "" and buf.fileencoding or nil
end
function filetype(_, buf)
return buf.filetype ~= "" and buf.filetype or 'no ft'
end
-- Tabline
frameline.setup_tabline(function()
local segments = {}
local api = vim.api
local color = '%#StatusLine#'
-- Tabs
local current = api.nvim_get_current_tabpage()
local label = ' %d %s '
for i, tab in pairs(api.nvim_list_tabpages()) do
-- tab -> active win -> active buf -> name
local active_buf = api.nvim_win_get_buf(api.nvim_tabpage_get_win(tab))
local name = api.nvim_buf_get_name(active_buf)
name = vim.fn.fnamemodify(name, ':t') -- filename only
local group = tab == current and 'TablineTabCur' or 'TablineTab'
table.insert(segments, utils.highlight(group, label:format(i, name)))
end
table.insert(segments, color)
table.insert(segments, utils.split)
-- Current date
table.insert(segments, vim.fn.strftime("%a %H:%M"))
-- Battery level
local level = io.popen('cat /sys/class/power_supply/BAT*/capacity'):read()
local symbol = ' '..utils.highlight('User2', '')..color
local battery = level and symbol..level..'%% ' or ""
table.insert(segments, battery)
return table.concat(segments)
end)
-- Statusline
frameline.setup_statusline(function()
local segments = {}
-- Left section
table.insert(segments, utils.subsection{items={mode}})
table.insert(segments, utils.subsection{
separator=' ',
items={branch, filename, readonly},
})
table.insert(segments, utils.split)
-- Right section
table.insert(segments, utils.subsection{items={neomake}})
table.insert(segments, utils.subsection{
user=2,
separator=':', stop=' ',
items={utils.line_number, utils.column_number},
})
table.insert(segments, utils.subsection{
user=1,
separator=' ',
items={utils.percent, encoding, filetype}
})
return segments
end)
'';
in
{
# nix build -f '<nixpkgs/nixos>' pkgs.neovim for testing
nixpkgs.overlays = lib.singleton (self: super: {
neovim = neovim-wrapped;
});
}

View File

@ -17,13 +17,16 @@
jq ack sshfs abduco
# backup
bup git nfs-utils
bup git
# admin
dnsutils
matrix-synapse
maxwell-notify
smartmontools
# namecoin
namecoin haskellPackages.rosa
];
}