Skip to content

Commit

Permalink
apps/neovim: Fix statusline issue with split windows
Browse files Browse the repository at this point in the history
TL;DR: neovim really needs a version of the '%!' statusline %-expression
that runs the specified expression in the context of the window that the
statusline belongs to, rather than in the context of the
currently-active window and buffer.

Without it, we have to awkwardly hack around this lack by taking
advantage of '%{}' expressions being evaluated within the context of the
window that the statusline belongs to, but they have the limitation that
their %-expressions in their output aren't evaluated.
  • Loading branch information
Shados committed Apr 19, 2021
1 parent ee87b22 commit 882d4ac
Show file tree
Hide file tree
Showing 3 changed files with 67 additions and 46 deletions.
7 changes: 6 additions & 1 deletion apps/neovim/default.nix
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ let
pins = import ../../pins;
neovimSrc = pins.neovim;
flakeCompat = import pins.flake-compat;
# TODO figure out why moonscript filetype doesn't appear to be applying automatically/correctly
in
{
imports = [
Expand Down Expand Up @@ -37,6 +38,7 @@ in
prePluginConfig = ''
-- Early-load settings
local sl -- Mildly hacky forward-declaration to work around a code ordering issue
${builtins.readFile ./prePluginConfig.moon}
'';
extraConfig = ''
Expand Down Expand Up @@ -194,6 +196,8 @@ in
# }}}
];
"ericpruitt/tmux.vim".enable = true;
# TODO debug weird auto-un/folding shit when entering a newline after a
# #-level title in a markdown file with a YAML frontmatter
vim-markdown = {
enable = true;
extraConfig = ''
Expand Down Expand Up @@ -250,6 +254,7 @@ in

# Text/code creation & refactoring {{{
# Code snippets, the mighty slayer of boilerplate
# TODO: Consider building my own solution on top of snippets.nvim instead
neosnippet-vim = {
enable = true;
extraConfig = ''
Expand Down Expand Up @@ -575,7 +580,7 @@ in

# Some transitive dependency specs {{{
"Shados/facade.nvim" = {
after = [
dependencies = [
"Shados/earthshine"
];
};
Expand Down
95 changes: 56 additions & 39 deletions apps/neovim/extraConfig.moon
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@ set "smartcase", true
set "number", true
set "relativenumber", true

-- I have mode information as part of my status line, so don't need this
set "showmode", false

-- Indentation
-- Copy indent to new line
set "autoindent", true
Expand Down Expand Up @@ -193,8 +196,12 @@ map "", "<F10>", syntax_debug_map, {}
-- }}}

-- Status line setup {{{
export setup_status_line, status_line, is_active_statusline
is_active_statusline = -> g.statusline_winid == fn.win_getid!
export setup_status_line, status_line, status_widget_functions, is_active_statusline

status_widget_functions = {}
is_active_statusline = (statusline_winid) ->
statusline_winid == fn.win_getid!

setup_status_line = (widget_groups, highlights) ->
-- TODO rethink this interface to allow same level of flexibility, but
-- cleanly separate content and presentation?
Expand All @@ -214,23 +221,28 @@ setup_status_line = (widget_groups, highlights) ->
else
base

widget_group_strs = {}

for group_idx, widget_group in ipairs widget_groups
widget_group_strs[group_idx] = {}
for {:widget, :callable} in *widget_group
-- Create widget output
output = if callable
fn_idx = #status_widget_functions + 1
status_widget_functions[fn_idx] = widget
"%%{luaeval('status_widget_functions[#{fn_idx}](%i)')}"
else
widget
table.insert widget_group_strs[group_idx], {:callable, widget_str: output}

status_line = ->
statusline_winid = fn.win_getid!
output_line = ""
for idx, widget_group in ipairs widget_groups
-- for idx, {:widget, :callable} in ipairs widgets
group_outputs = {}
for {:widget, :callable} in *widget_group
-- Create widget output
output = if callable
widget!
else
widget
table.insert group_outputs, output

for idx, widget_strs in ipairs widget_group_strs
-- Determine if highlight group needs to recreated from the highlight data
{:highlight, :callable_highlight} = highlights[idx]
highlight = if callable_highlight
highlight group_outputs
highlight statusline_winid
else
highlight
set_highlight = false
Expand All @@ -247,16 +259,23 @@ setup_status_line = (widget_groups, highlights) ->
if set_highlight
cmd (generate_highlight idx, highlight)

widget_group_str = ""
for {:callable, :widget_str} in *widget_strs
if callable
widget_group_str ..= string.format widget_str, statusline_winid
else
widget_group_str ..= widget_str
-- Append highlight information & widget output to the output status line
output_line ..= string.format "%%#%s#%s", (highlight_name idx), (table.concat group_outputs)
output_line ..= string.format "%%#%s#%s", (highlight_name idx), widget_group_str

output_line

o.statusline = [[%!luaeval("status_line()")]]
set "statusline", [[%!luaeval("status_line()")]]
return

sl = {}
do
mode_mapping =
sl.mode_mapping =
n: "NORMAL"
niI: "NORMAL"
niR: "NORMAL"
Expand Down Expand Up @@ -287,27 +306,25 @@ do
['!']: "SHELL"
t: "TERMINAL"

get_mode_str = ->
sl.get_mode_str = ->
-- TODO: mode | PASTE?
-- paste indicator separately?
{ :mode } = api.nvim_get_mode!
if mode_str = mode_mapping[mode]
if mode_str = sl.mode_mapping[mode]
mode_str
else
mode

file_name = ->
sl.file_name = ->
name = fn.expand '%:t'
ext = fn.expand '%:e'
icon = if nvim_web_devicons
nvim_web_devicons.get_icon name, ext, { default: true }

if icon
if nvim_web_devicons
icon = nvim_web_devicons.get_icon name, ext, { default: true }
string.format "%s %s", icon, name
else
name

file_osinfo = ->
sl.file_osinfo = ->
os = string.lower bo.fileformat
icon = switch os
when "unix"
Expand All @@ -318,23 +335,23 @@ do
icon = ''
"#{icon} #{os}"

file_percentage = ->
sl.file_percentage = ->
(fn.round ((fn.line '.') / (fn.line '$') * 100)) .. '%%'

file_encoding = ->
sl.file_encoding = ->
if bo.fenc != ''
bo.fenc
else
o.enc

file_type = ->
sl.file_type = ->
ft = bo.filetype
if ft != ""
ft
else
"none"

paste_mode = ->
sl.paste_mode = ->
if o.paste
"[PASTE]"
else
Expand All @@ -343,15 +360,15 @@ do
active_only = (widget_group) ->
for idx, widget in ipairs widget_group
wrapped_widget = if is_callable widget
() ->
active = is_active_statusline!
(statusline_winid) ->
active = is_active_statusline statusline_winid
if active
widget!
widget statusline_winid
else
""
else
() ->
active = is_active_statusline!
(statusline_winid) ->
active = is_active_statusline statusline_winid
if active
widget
else
Expand All @@ -360,12 +377,12 @@ do
widget_group

widgets = {
(active_only { ' ', get_mode_str, ' ' }),
{ ' ', file_name, ' ' }, -- Filename
{ paste_mode, '%r', '%m' }, -- Paste-mode, read-only & dirty buffer warnings
(active_only { ' ', sl.get_mode_str, ' ' }),
{ ' ', sl.file_name, ' ' }, -- Filename
{ sl.paste_mode, '%r', '%m' }, -- Paste-mode, read-only & dirty buffer warnings
{ '%=' }, -- Left/right breaker
(active_only { ' ', file_osinfo, ' | ', file_encoding, ' | ', file_type, ' ' }),
{ ' ', file_percentage, ' %l:%c ' }, -- Line & column information
(active_only { ' ', sl.file_osinfo, ' | ', sl.file_encoding, ' | ', sl.file_type, ' ' }),
{ ' ', sl.file_percentage, ' %l:%c ' }, -- Line & column information
}

setup_status_line widgets, statusline_highlights
Expand Down
11 changes: 5 additions & 6 deletions apps/neovim/oceanicnext.nix
Original file line number Diff line number Diff line change
Expand Up @@ -57,13 +57,12 @@ in
file_hi = { bg: colors.base03, fg: colors.white }
fileinfo_hi = file_hi
warning_hi = { bg: colors.yellow, fg: colors.base01 }
mode_highlight = (group_outputs) ->
mode_output = group_outputs[2]
if mode_output == "" -- means we're not in active statusline
base_hi
else
{fg, bg} = mode_colors[mode_output]
mode_highlight = (statusline_winid) ->
if is_active_statusline statusline_winid
{fg, bg} = mode_colors[sl.get_mode_str!]
{ :fg, :bg }
else
base_hi
{
mode_highlight
Expand Down

0 comments on commit 882d4ac

Please sign in to comment.