Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Statusline isn't working as expected #134

Closed
SingularisArt opened this issue Aug 30, 2022 · 6 comments
Closed

Statusline isn't working as expected #134

SingularisArt opened this issue Aug 30, 2022 · 6 comments

Comments

@SingularisArt
Copy link
Contributor

SingularisArt commented Aug 30, 2022

Expected Behavior

I'm expecting the statusline to look like your statusline.

Actual Behavior

The statusline looks similiar to yours, but it doesn't have any coloring and when I modify the file, I get the following error:

Error detected while processing TextChangedI Autocommands for "*":
Error executing lua callback: ...laris/.local/share/deathvim/dvim/lua/dvim/statusline.lua:244: Vim(highlight):E421: Color name or n
umber not recognized: ctermbg=#505050 ctermfg=#d0d0d0 gui=italic
stack traceback:
        [C]: in function 'cmd'
        ...laris/.local/share/deathvim/dvim/lua/dvim/statusline.lua:244: in function 'update_highlight'
        ...laris/.local/share/deathvim/dvim/lua/dvim/statusline.lua:90: in function 'check_modified'
        ...ngularis/.local/share/deathvim/dvim/lua/dvim/augroup.lua:8: in function <...ngularis/.local/share/deathvim/dvim/lua/dvim
/augroup.lua:7>

Steps to Reproduce the Problem

Here's the content of statusline.lua:

local pinnacle = require("wincent.pinnacle")

local statusline = {}

local async = false
local async_lhs_color = "Constant"
local default_lhs_color = "Identifier"
local modified_lhs_color = "ModeMsg"
local status_highlight = default_lhs_color

local update_statusline = function(default, action)
  local result
  local filetype = vim.bo.filetype

  if filetype == "command-t" then
    -- Use Command-T-provided buffer name.
    --
    -- Note that we have to use `vim.fn.bufname()` here to
    -- produce the desired result (eg. "Command-T [Files]").
    -- `vim.api.nvim_buf_get_name(0)` isn't suitable because it prepends
    -- the current working directory (eg. "/Some/path/to/Command-T
    -- [Files]").
    result = "  " .. vim.fn.bufname()
  elseif filetype == "diff" then
    if vim.b.isUndotreeBuffer == 1 then
      -- Less ugly than, say, "diffpanel_3".
      result = "Undotree preview"
    else
      result = 1
    end
  elseif filetype == "undotree" then
    -- Don't override; undotree does its own thing.
    result = 0
  elseif filetype == "qf" then
    if action == "blur" then
      result = "%{v:lua.dvim.statusline.gutterpadding()}"
          .. " "
          .. " "
          .. " "
          .. " "
          .. "%<"
          .. "%q"
          .. " "
          .. '%{get(w:,"quickfix_title","")}'
          .. "%="
    else
      result = vim.g.DvimQuickfixStatusline or ""
    end
  else
    result = 1
  end

  if result == 0 then
    -- Do nothing.
  elseif result == 1 then
    vim.wo.statusline = default
  else
    -- Apply custom statusline.
    vim.wo.statusline = result
  end
end

statusline.async_start = function()
  async = true
  statusline.check_modified()
end

statusline.async_finish = function()
  async = false
  statusline.check_modified()
end

statusline.blur_statusline = function()
  -- Default blurred statusline (buffer number: filename).
  local blurred = "%{v:lua.dvim.statusline.gutterpadding()}"
  blurred = blurred .. " " -- space
  blurred = blurred .. " " -- space
  blurred = blurred .. " " -- space
  blurred = blurred .. " " -- space
  blurred = blurred .. "%<" -- truncation point
  blurred = blurred .. "%f" -- filename
  blurred = blurred .. "%=" -- split left/right halves (makes background cover whole)
  update_statusline(blurred, "blur")
end

statusline.check_modified = function()
  local modified = vim.bo.modified
  if modified and status_highlight ~= modified_lhs_color then
    status_highlight = modified_lhs_color
    statusline.update_highlight()
  elseif not modified then
    if async and status_highlight ~= async_lhs_color then
      status_highlight = async_lhs_color
      statusline.update_highlight()
    elseif not async and status_highlight ~= default_lhs_color then
      status_highlight = default_lhs_color
      statusline.update_highlight()
    end
  end
end

-- Returns the 'fileencoding', if it's not UTF-8.
statusline.fileencoding = function()
  local fileencoding = vim.bo.fileencoding
  if #fileencoding > 0 and fileencoding ~= "utf-8" then
    return "," .. fileencoding
  else
    return ""
  end
end

-- Returns relative path to current file's directory.
statusline.fileprefix = function()
  local basename = vim.fn.fnamemodify(vim.fn.expand("%:h"), ":p:~:.")
  if basename == "" or basename == "." then
    return ""
  else
    return basename:gsub("/$", "") .. "/"
  end
end

-- Returns the 'filetype' (not using the %Y format because I don't want caps).
statusline.filetype = function()
  local filetype = vim.bo.filetype
  if #filetype > 0 then
    return "," .. filetype
  else
    return ""
  end
end

statusline.focus_statusline = function()
  -- `setlocal statusline=` will revert to global 'statusline' setting.
  update_statusline("", "focus")
end

statusline.gutterpadding = function()
  local signcolumn = 0
  local option = vim.wo.signcolumn
  if option == "yes" then
    signcolumn = 2
  elseif option == "auto" then
    local signs = vim.fn.sign_getplaced("")
    if #signs[1].signs > 0 then
      signcolumn = 2
    end
  end

  local minwidth = 2
  local numberwidth = vim.wo.numberwidth
  local row = vim.api.nvim_buf_line_count(0)
  local gutterwidth = math.max((#tostring(row) + 1), minwidth, numberwidth) + signcolumn
  local padding = (" "):rep(gutterwidth - 1)
  return padding
end

statusline.lhs = function()
  local padding = statusline.gutterpadding()

  if vim.bo.modified then
    -- HEAVY BALLOT X - Unicode: U+2718, UTF-8: E2 9C 98
    return padding .. ""
  else
    return padding .. "  "
  end
end

statusline.rhs = function()
  local rhs = " "

  if vim.fn.winwidth(0) > 80 then
    local column = vim.fn.virtcol(".")
    local width = vim.fn.virtcol("$")
    local line = vim.api.nvim_win_get_cursor(0)[1]
    local height = vim.api.nvim_buf_line_count(0)

    -- Add padding to stop RHS from changing too much as we move the cursor.
    local padding = #tostring(height) - #tostring(line)
    if padding > 0 then
      rhs = rhs .. (" "):rep(padding)
    end

    rhs = rhs .. "" -- (Literal, \u2113 "SCRIPT SMALL L").
    rhs = rhs .. line
    rhs = rhs .. "/"
    rhs = rhs .. height
    rhs = rhs .. " 𝚌 " -- (Literal, \u1d68c "MATHEMATICAL MONOSPACE SMALL C").
    rhs = rhs .. column
    rhs = rhs .. "/"
    rhs = rhs .. width
    rhs = rhs .. " "

    -- Add padding to stop rhs from changing too much as we move the cursor.
    if #tostring(column) < 2 then
      rhs = rhs .. " "
    end
    if #tostring(width) < 2 then
      rhs = rhs .. " "
    end
  end

  return rhs
end

statusline.set = function()
  -- For comparison, the default statusline is:
  --
  --    %<%f\ %h%m%r%=%-14.(%l,%c%V%)\ %P
  --
  vim.opt.statusline = ""
      .. "%7*" -- Switch to User7 highlight group
      .. "%{v:lua.dvim.statusline.lhs()}" -- Red/green/orange modified/activity status.
      .. "%*" -- Reset highlight group.
      .. "%4*" -- Switch to User4 highlight group (Powerline arrow).
      .. "" -- Powerline arrow.
      .. "%*" -- Reset highlight group.
      .. " " -- Space.
      .. "%<" -- Truncation point, if not enough width available.
      .. "%{v:lua.dvim.statusline.fileprefix()}" -- Relative path to file's directory.
      .. "%3*" -- Switch to User3 highlight group (bold).
      .. "%t" -- Filename.
      .. "%*" -- Reset highlight group.
      .. " " -- Space.
      .. "%1*" -- Switch to User1 highlight group (italics).
      .. "%(" -- Start item group.
      .. "[" -- Left bracket (literal).
      .. "%R" -- Read-only flag: ,RO or nothing.
      .. "%{v:lua.dvim.statusline.filetype()}" -- Filetype (not using %Y because I don't want caps).
      .. "%{v:lua.dvim.statusline.fileencoding()}" -- File-encoding if not UTF-8.
      .. "]" -- Right bracket (literal).
      .. "%)" -- End item group.
      .. "%*" -- Reset highlight group.
      .. "%=" -- Split point for left and right groups.
      .. " " -- Space.
      .. "" -- Powerline arrow.
      .. "%5*" -- Switch to User5 highlight group.
      .. "%{v:lua.dvim.statusline.rhs()}" -- Line/column info.
      .. "%*" -- Reset highlight group.
end

statusline.update_highlight = function()
  -- Update StatusLine to use italics (used for filetype).
  local highlight = pinnacle.italicize("StatusLine")
  vim.cmd("highlight User1 " .. highlight)

  -- Update MatchParen to use italics (used for blurred statuslines).
  highlight = pinnacle.italicize("MatchParen")
  vim.cmd("highlight User2 " .. highlight)

  -- StatusLine + bold (used for file names).
  highlight = pinnacle.embolden("StatusLine")
  vim.cmd("highlight User3 " .. highlight)

  -- Inverted Error styling, for left-hand side "Powerline" triangle.
  local fg = pinnacle.extract_fg(status_highlight)
  local bg = pinnacle.extract_bg("StatusLine")
  vim.cmd("highlight User4 " .. pinnacle.highlight({ bg = bg, fg = fg }))

  -- And opposite for the buffer number area.
  vim.cmd("highlight User7 " .. pinnacle.highlight({
    bg = fg,
    fg = pinnacle.extract_fg("Normal"),
    term = "bold",
  }))

  -- Right-hand side section.
  bg = pinnacle.extract_fg("Cursor")
  fg = pinnacle.extract_fg("User3")
  vim.cmd("highlight User5 " .. pinnacle.highlight({
    bg = fg,
    fg = bg,
    term = "bold",
  }))

  -- Right-hand side section + italic (used for %).
  vim.cmd("highlight User6 " .. pinnacle.highlight({
    bg = fg,
    fg = bg,
    term = "bold,italic",
  }))

  vim.cmd("highlight clear StatusLineNC")
  vim.cmd("highlight! link StatusLineNC User1")
end

return statusline

Here's the content of augroup.lua:

local api = vim.api

local statuslineGroup = api.nvim_create_augroup("Statusline", { clear = true })
api.nvim_create_autocmd({ "BufWinEnter", "BufWritePost", "FileWritePost", "TextChanged", "TextChangedI", "WinEnter" },
  {
    pattern = "*",
    callback = function()
      dvim.statusline.check_modified()
    end,
    group = statuslineGroup,
  })

api.nvim_create_autocmd({ "ColorScheme" }, {
  pattern = "*",
  callback = function()
    dvim.statusline.update_highlight()
  end,
  group = statuslineGroup,
})

I then call these files in my init.lua like so:

statusline = require("statusline")
statusline.set()
require("augroup")

Question

I'm currently using TreeSitter and when I try to implement the blur/focus methods you use, I can't get TreeSitter disabled for the inactive buffers. How would you deal with this?
Also, how would I add the gps to the statusline right after the file type next to the filename?

Specifications

  • Version: NVIM v0.8.0-dev-973-g253f0ffd8d
  • Platform: Arch Linux 5.19.5-zen1-1-zen Vim: alphabetize settings.vim #1 ZEN SMP PREEMPT_DYNAMIC +0000 x86_64 GNU/Linux
  • Subsystem: EndeavourOS
@wincent
Copy link
Owner

wincent commented Aug 30, 2022

You should be able to debug this by strategically inserting some print(vim.inspect(value)) statements right before the lines where the error is being thrown. You'll probably find that in a spot like this (not sure if this is the exact spot that is error, but it will be something like this):

local fg = pinnacle.extract_fg(status_highlight)
local bg = pinnacle.extract_bg("StatusLine")
print(vim.inspect(fg))
print(vim.inspect(bg))
vim.cmd("highlight User4 " .. pinnacle.highlight({ bg = bg, fg = fg }))

If, say, fg or bg ends up being an empty string, that could cause the :highlight command to error, and so the next step is debugging why the associated highlight group (eg. StatusLine, or Identifier etc) doesn't have that set.

I'm using base16-vim, and I find that all the highlight groups have defined values. In your local set-up, something else must be happening; fixing it might mean doing something to the colorscheme, or to your statusline.lua file.

I'm currently using TreeSitter and when I try to implement the blur/focus methods you use, I can't get TreeSitter disabled for the inactive buffers. How would you deal with this?
Also, how would I add the gps to the statusline right after the file type next to the filename?

I'm not using either of those, so I don't have any specific advice to offer about them.

@SingularisArt
Copy link
Contributor Author

After a little digging, I found the issue. For some reason, when using the pinnacle plugin, the highlight variable was being set to: ctermbg=#505050 ctermfg=#d0d0d0 gui=italic. So, I just added :gsub("cterm", "gui") at the end of each line when modifying the highlight variable.

I'm going to keep this issue open since I'm currently working on getting the statusbar to work with gps and to get TreeSitter working along with the focus/blur method. Once I've completed these tasks, I'll post my results here and close the issue, just in case anyone else wants the same.

@SingularisArt
Copy link
Contributor Author

Alrighty. I just completed the gps part of the statusbar. Here's how the statusbar looks like.

Screenshot_2022-08-30_14-15-40

Here's the code (I put this right after: .. "%)" -- End item group.)

      .. "%*" -- Reset highlight group.
      .. "%3*" -- Switch to User3 highlight group (bold).
      .. "%= %<%{%v:lua.require'nvim-navic'.get_location()%} %=" -- Navic in Center.
      .. "%*" -- Reset highlight group.

Of course, to get this working, you need to have nvim-navic installed and configured.
Here's my configuration for nvim-navic.

I'll try and get the TreeSitter + focus/blur done today and close this issue as soon as possible.

@SingularisArt
Copy link
Contributor Author

Finally. I figured out the final issue. I disable TreeSitter and IndentLine by adding the following autocmds:

autocmd("BufEnter", "*", "TSBufEnable highlight")
autocmd("BufEnter", "*", "IndentBlanklineToggle")
autocmd("BufLeave", "*", "TSBufDisable highlight")
autocmd("BufLeave", "*", "IndentBlanklineDisable")

This does bring about the following issues. When opening something like a float, it disables highlighters and indentation, but after leaving, it doesn't bring them back.

@wincent How would you create an autocmd that only triggers when leaving a buffer, and then re-entering another buffer?

@wincent
Copy link
Owner

wincent commented Sep 11, 2022

@wincent How would you create an autocmd that only triggers when leaving a buffer, and then re-entering another buffer?

Unfortunately, autocmds are notoriously fiddly, especially once you have multiple plug-in installed, firing autocmds, listening to autocmds, suppressing autocmds (eg. with :noautocmd, 'eventignore') etc. I don't really have any generic advice here, other than using 'verbose', :verbose, 'verbosefile' to capture debug information about what events are being triggered, and in what order, and to work from there.

@wincent
Copy link
Owner

wincent commented Mar 14, 2024

Closing some old stale issues.

@wincent wincent closed this as completed Mar 14, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants