403 lines
20 KiB
Fennel
403 lines
20 KiB
Fennel
(import-macros {: deferred_cmd} :../macros/cmd)
|
|
|
|
(let [mod {}
|
|
api vim.api
|
|
heirline-utils (require :heirline.utils)
|
|
heirline-conditions (require :heirline.conditions)
|
|
web-devicons (require :nvim-web-devicons)
|
|
colors (. (require :nifoc.theme) :colors)
|
|
formatting (require :nifoc.formatting)
|
|
repo (require :nifoc.repo)
|
|
nifoc-treesitter (require :nifoc.treesitter)
|
|
navic (require :nvim-navic)
|
|
neogit (require :neogit)
|
|
telescope-builtin (require :telescope.builtin)
|
|
telescope-themes (require :telescope.themes)]
|
|
(fn buffer-variable-exists? [key]
|
|
(not= (. vim :b key) nil))
|
|
|
|
(fn get-current-line []
|
|
(let [cl (api.nvim_win_get_cursor 0)]
|
|
(. cl 1)))
|
|
|
|
(fn get-total-lines []
|
|
(api.nvim_buf_line_count 0))
|
|
|
|
(fn max-number [nums]
|
|
(math.max (unpack nums)))
|
|
|
|
(fn truncate-string [str max-length ellipsis]
|
|
(if (> (length str) max-length) (.. (str:sub 1 max-length) ellipsis) str))
|
|
|
|
;; Utils
|
|
(set mod.default-hl #{:bg colors.black})
|
|
(set mod.space {:provider " "})
|
|
(set mod.spacer {:provider " " :hl {:fg colors.bg :bg colors.bg}})
|
|
(set mod.push-right {:provider "%="})
|
|
(set mod.space-if-count {:condition #(> $1.check-count 0) :provider " "})
|
|
(set mod.space-if-length {:condition #(> $1.check-length 0) :provider " "})
|
|
(set mod.space-if-count-or-length
|
|
{:condition #(or (> $1.check-count 0) (> $1.check-length 0))
|
|
:provider " "})
|
|
;; Mode
|
|
(set mod.vi-mode {:init #(set $1.mode (. (api.nvim_get_mode) :mode))
|
|
:update {1 :ModeChanged
|
|
:pattern "*:*"
|
|
:callback (vim.schedule_wrap #(vim.cmd.redrawstatus))}
|
|
:static {:mode-names {:n :NORMAL
|
|
:no :O-PENDING
|
|
:nov :O-PENDING
|
|
:noV :O-PENDING
|
|
"no\022" :O-PENDING
|
|
:niI :NORMAL
|
|
:niR :NORMAL
|
|
:niV :NORMAL
|
|
:nt :NORMAL
|
|
:v :VISUAL
|
|
:vs :VISUAL
|
|
:V :V-LINE
|
|
:Vs :V-LINE
|
|
"\022" :V-BLOCK
|
|
"\022s" :V-BLOCK
|
|
:s :SELECT
|
|
:S :S-LINE
|
|
"\019" :S-BLOCK
|
|
:i :INSERT
|
|
:ic :INSERT
|
|
:ix :INSERT
|
|
:R :REPLACE
|
|
:Rc :REPLACE
|
|
:Rx :REPLACE
|
|
:Rv :V-REPLACE
|
|
:Rvc :V-REPLACE
|
|
:Rvx :V-REPLACE
|
|
:c :COMMAND
|
|
:cv :EX
|
|
:ce :EX
|
|
:r :REPLACE
|
|
:rm :MORE
|
|
:r? :CONFIRM
|
|
:! :SHELL
|
|
:t :TERMINAL}
|
|
:mode-hl {:n {:fg colors.black
|
|
:bg colors.purple
|
|
:bold true}
|
|
:i {:fg colors.black
|
|
:bg colors.green
|
|
:bold true}
|
|
:v {:fg colors.black
|
|
:bg colors.pink
|
|
:bold true}
|
|
:V {:fg colors.black
|
|
:bg colors.pink
|
|
:bold true}
|
|
"\022" {:fg colors.black
|
|
:bg colors.pink
|
|
:bold true}
|
|
:c {:fg colors.black
|
|
:bg colors.yellow
|
|
:bold true}
|
|
:s {:fg colors.black
|
|
:bg colors.orange
|
|
:bold true}
|
|
:S {:fg colors.black
|
|
:bg colors.orange
|
|
:bold true}
|
|
"\019" {:fg colors.black
|
|
:bg colors.orange
|
|
:bold true}
|
|
:R {:fg colors.black
|
|
:bg colors.yellow
|
|
:bold true}
|
|
:r {:fg colors.black
|
|
:bg colors.yellow
|
|
:bold true}
|
|
:! {:fg colors.black
|
|
:bg colors.purple
|
|
:bold true}
|
|
:t {:fg colors.black
|
|
:bg colors.purple
|
|
:bold true}}}
|
|
:provider #(.. " " (. $1 :mode-names $1.mode) " ")
|
|
:hl (fn [self]
|
|
(let [short-mode (self.mode:sub 1 1)]
|
|
(. self :mode-hl short-mode)))})
|
|
;; Filetype
|
|
(set mod.filetype-block {:init #(set $1.filename (api.nvim_buf_get_name 0))})
|
|
(set mod.file-icon {:init (fn [self]
|
|
(let [filename self.filename
|
|
ext (vim.fn.fnamemodify filename ":e")
|
|
(icon color) (web-devicons.get_icon_color filename
|
|
ext
|
|
{:default true})]
|
|
(set self.icon icon)
|
|
(set self.icon-color color)))
|
|
:provider #(when $1.icon
|
|
(.. $1.icon " "))
|
|
:hl #{:fg $1.icon-color}})
|
|
(set mod.filetype {:provider #(let [ft vim.bo.filetype]
|
|
(if (> (ft:len) 0) ft "no ft"))
|
|
:hl {:fg colors.white}})
|
|
(set mod.encoding {:provider (fn []
|
|
(let [vim-enc (if (not= vim.bo.fenc nil)
|
|
vim.bo.fenc
|
|
vim.o.enc)
|
|
enc (if (> (vim-enc:len) 0) vim-enc
|
|
"no enc")]
|
|
(.. enc " ")))
|
|
:hl {:fg colors.white}})
|
|
(set mod.filetype-block
|
|
(heirline-utils.insert mod.filetype-block mod.file-icon mod.filetype
|
|
{:provider " | " :hl {:fg colors.white}}
|
|
mod.encoding))
|
|
;; git
|
|
(set mod.git
|
|
{:condition heirline-conditions.is_git_repo
|
|
:static {:git-repo-icons {:github ""
|
|
:gitlab ""
|
|
:forgejo ""
|
|
:default ""}}
|
|
:init (fn [self]
|
|
(let [git-status vim.b.gitsigns_status_dict]
|
|
(set self.git-repo-icon (. self :git-repo-icons repo.type))
|
|
(set self.git-head git-status.head)
|
|
(set self.git-added (or git-status.added 0))
|
|
(set self.git-removed (or git-status.removed 0))
|
|
(set self.git-changed (or git-status.changed 0))
|
|
(set self.check-count
|
|
(max-number [self.git-added
|
|
self.git-removed
|
|
self.git-changed]))
|
|
(set self.check-length (length self.git-head))))
|
|
1 mod.space-if-count-or-length
|
|
2 {:provider #(.. " " $1.git-repo-icon " ")
|
|
:on_click {:name :heirline_git_repo_type
|
|
:callback #(repo.open-repo)}
|
|
:hl {:fg colors.black :bg colors.orange :bold true}}
|
|
3 {:provider #(.. $1.git-head " ")
|
|
:on_click {:name :heirline_git_branch
|
|
:callback #(neogit.open {:kind :split})}
|
|
:hl {:fg colors.black :bg colors.orange :bold true}}
|
|
4 mod.space
|
|
5 {:provider #(.. " " $1.git-added " ")
|
|
:hl {:fg colors.bright_green}}
|
|
6 {:provider #(.. " " $1.git-removed " ")
|
|
:hl {:fg colors.bright_red}}
|
|
7 {:provider #(.. " " $1.git-changed) :hl {:fg colors.cyan}}})
|
|
;; Diagnostics
|
|
(set mod.diagnostics {:condition heirline-conditions.has_diagnostics
|
|
:init (fn [self]
|
|
(let [d vim.diagnostic]
|
|
(set self.errors
|
|
(length (d.get 0
|
|
{:severity d.severity.ERROR})))
|
|
(set self.warnings
|
|
(length (d.get 0
|
|
{:severity d.severity.WARN})))
|
|
(set self.info
|
|
(length (d.get 0
|
|
{:severity d.severity.INFO})))
|
|
(set self.hints
|
|
(length (d.get 0
|
|
{:severity d.severity.HINT})))
|
|
(set self.check-count
|
|
(max-number [self.errors
|
|
self.warnings
|
|
self.info
|
|
self.hints]))))
|
|
:update [:DiagnosticChanged :BufEnter]
|
|
:on_click {:name :heirline_diagnostics_list
|
|
:callback #(telescope-builtin.diagnostics (telescope-themes.get_ivy {:bufnr 0}))}
|
|
1 mod.space-if-count
|
|
2 {:provider (fn [self]
|
|
(let [spacer (if (or (> self.warnings 0)
|
|
(> self.info 0)
|
|
(> self.hints 0))
|
|
" "
|
|
"")]
|
|
(when (> self.errors 0)
|
|
(.. " " self.errors spacer))))
|
|
:hl {:fg colors.red}}
|
|
3 {:provider (fn [self]
|
|
(let [spacer (if (or (> self.info 0)
|
|
(> self.hints 0))
|
|
" "
|
|
"")]
|
|
(when (> self.warnings 0)
|
|
(.. " " self.warnings spacer))))
|
|
:hl {:fg colors.yellow}}
|
|
4 {:provider (fn [self]
|
|
(let [spacer (if (> self.hints 0) " "
|
|
"")]
|
|
(when (> self.info 0)
|
|
(.. " " self.info spacer))))
|
|
:hl {:fg colors.cyan}}
|
|
5 {:provider (fn [self]
|
|
(when (> self.hints 0)
|
|
(.. " " self.hints)))
|
|
:hl {:fg colors.cyan}}})
|
|
;; Current Function
|
|
(set mod.current-function
|
|
{:condition heirline-conditions.lsp_attached
|
|
:init #(if (navic.is_available)
|
|
(set $1.check-length 1)
|
|
(set $1.check-length 0))
|
|
:update :CursorMoved
|
|
1 mod.space-if-length
|
|
2 {:provider #(string.gsub (navic.get_location) "%%" "%%%%")
|
|
:hl {:fg colors.white}}})
|
|
(set mod.navic
|
|
{:condition #(navic.is_available 0)
|
|
:static {:type-hl {:File :Directory
|
|
:Module "@include"
|
|
:Namespace "@namespace"
|
|
:Package "@include"
|
|
:Class "@structure"
|
|
:Method "@method"
|
|
:Property "@property"
|
|
:Field "@field"
|
|
:Constructor "@constructor"
|
|
:Enum "@field"
|
|
:Interface "@type"
|
|
:Function "@function"
|
|
:Variable "@variable"
|
|
:Constant "@constant"
|
|
:String "@string"
|
|
:Number "@number"
|
|
:Boolean "@boolean"
|
|
:Array "@field"
|
|
:Object "@type"
|
|
:Key "@keyword"
|
|
:Null "@comment"
|
|
:EnumMember "@field"
|
|
:Struct "@structure"
|
|
:Event "@keyword"
|
|
:Operator "@operator"
|
|
:TypeParameter "@type"}
|
|
:separator " "
|
|
:enc (fn [line col winnr]
|
|
(let [enc-line (bit.lshift line 16)
|
|
enc-col (bit.lshift col 6)]
|
|
(bit.bor enc-line enc-col winnr)))
|
|
:dec (fn [c]
|
|
(let [line (bit.rshift c 16)
|
|
col (-> c (bit.rshift 6) (bit.band 1023))
|
|
winnr (bit.band c 63)]
|
|
[line col winnr]))}
|
|
:init (fn [self]
|
|
(set self.check-length 1)
|
|
(local data (or (navic.get_data) []))
|
|
(local data-len (length data))
|
|
(var children [])
|
|
(each [i d (ipairs data)]
|
|
(let [pos (self.enc d.scope.start.line
|
|
d.scope.start.character self.winnr)
|
|
child [{:provider d.icon :hl (. self.type-hl d.type)}
|
|
{:provider (truncate-string (string.gsub d.name
|
|
"%%"
|
|
"%%%%")
|
|
45 "")
|
|
:on_click {:name :heirline_navic
|
|
:minwid pos
|
|
:callback (fn [_ minwid]
|
|
(let [[line col winnr] (self.dec minwid)
|
|
id (vim.fn.win_getid winnr)]
|
|
(api.nvim_win_set_cursor id
|
|
[line
|
|
col])))}}]]
|
|
(when (and (> data-len 1) (< i data-len))
|
|
(table.insert child
|
|
{:provider self.separator
|
|
:hl {:fg colors.white}}))
|
|
(table.insert children child)))
|
|
(set self.child (self:new children 1)))
|
|
:update :CursorMoved
|
|
1 mod.space-if-length
|
|
2 {:provider #(: $1.child :eval) :hl {:fg colors.white}}})
|
|
;; Buffer Options
|
|
(set mod.buffer-options
|
|
{:static {:format {:dos "" :unix "" :mac ""}}
|
|
:hl {:fg colors.black :bg colors.orange}
|
|
1 mod.space
|
|
2 {:condition #(buffer-variable-exists? :nifoc_lsp_enabled)
|
|
:provider " "
|
|
:on_click {:name :heirline_buffer_options_lsp
|
|
:callback #(deferred_cmd {:cmd :LspInfo} 200)}}
|
|
3 {:condition #(formatting.active?) :provider " "}
|
|
4 {:condition #(nifoc-treesitter.active?) :provider " "}
|
|
5 {:condition #vim.wo.spell :provider ""}
|
|
6 {:provider (fn [self]
|
|
(let [f vim.bo.fileformat]
|
|
(.. (. self :format f) " ")))}})
|
|
;; Position
|
|
(set mod.position
|
|
{:init (fn [self]
|
|
(let [pos (api.nvim_win_get_cursor 0)]
|
|
(set self.position-line (tostring (. pos 1)))
|
|
(set self.position-column (tostring (. pos 2)))))
|
|
:provider #(string.format " %3s:%-3s " $1.position-line
|
|
$1.position-column)
|
|
:hl {:fg colors.black :bg colors.purple :bold true}})
|
|
;; Scrollbar
|
|
(set mod.scrollbar {:init (fn [self]
|
|
(set self.current-line (get-current-line))
|
|
(set self.total-lines (get-total-lines)))
|
|
:static {:scrollbar-icons-block ["▁"
|
|
"▂"
|
|
"▃"
|
|
"▄"
|
|
"▅"
|
|
"▆"
|
|
"▇"
|
|
"█"]
|
|
:scrollbar-icons-line ["🭶"
|
|
"🭷"
|
|
"🭸"
|
|
"🭹"
|
|
"🭺"
|
|
"🭻"]}
|
|
:provider (fn [self]
|
|
(let [scrollbar-icons self.scrollbar-icons-block
|
|
i (+ (math.floor (* (/ (- self.current-line
|
|
1)
|
|
self.total-lines)
|
|
(length scrollbar-icons)))
|
|
1)
|
|
new-scrollbar (. scrollbar-icons i)]
|
|
(string.rep new-scrollbar 2)))
|
|
:hl {:fg colors.purple}})
|
|
;; Search count
|
|
(set mod.search-count
|
|
{:condition #(> vim.v.hlsearch 0)
|
|
:init #(set $1.count (vim.fn.searchcount {:timeout 5}))
|
|
:provider #(string.format "[%s/%s]" $1.count.current $1.count.total)
|
|
:hl {:fg colors.black :bg colors.purple}})
|
|
;; Command
|
|
(set mod.command
|
|
{:condition (fn [self]
|
|
(let [mode (. (api.nvim_get_mode) :mode)]
|
|
(vim.tbl_contains self.enabled-modes mode)))
|
|
:update {1 :ModeChanged :pattern "*:*"}
|
|
:static {:enabled-modes [:no
|
|
:nov
|
|
:noV
|
|
"no\022"
|
|
:v
|
|
:vs
|
|
:V
|
|
:Vs
|
|
"\022"
|
|
"\022s"]}
|
|
:provider "[%S]"
|
|
:hl {:fg colors.black :bg colors.purple}})
|
|
;; Custom Mode
|
|
|
|
(fn mod.custom-mode [str fg bg]
|
|
{:provider (.. " " str " ")
|
|
:hl {:fg (. colors fg) :bg (. colors bg) :bold true}})
|
|
|
|
(fn mod.shell-mode [fg bg]
|
|
{:provider #(.. " " vim.b.nifoc_shell_mode " ")
|
|
:hl {:fg (. colors fg) :bg (. colors bg) :bold true}})
|
|
|
|
mod)
|