This commit is contained in:
Barrett Ruth 2026-02-11 10:42:58 -05:00
parent 177d3ca47c
commit ef1df7358d
Signed by: barrett
GPG key ID: A6C96C9349D2FC81
10 changed files with 253 additions and 649 deletions

View file

@ -1,2 +0,0 @@
#!/bin/sh
exec kitten icat --clear --stdin no --transfer-mode memory </dev/null >/dev/tty

View file

@ -1,250 +0,0 @@
_G.lf = _G.lf or {}
function _G.lf.setup()
vim.opt.swapfile = false
vim.opt.backup = false
vim.opt.writebackup = false
vim.opt.termguicolors = true
vim.pack.add({
{
src = "https://github.com/nvim-treesitter/nvim-treesitter.git",
name = "nvim-treesitter",
},
{
src = "https://github.com/barrettruth/midnight.nvim.git",
name = "midnight.nvim",
},
})
vim.cmd('silent TSInstall all')
vim.api.nvim_create_autocmd("OptionSet", {
pattern = "background",
callback = function()
vim.cmd.colorscheme(vim.o.background == "dark" and "midnight" or "daylight")
end,
group = vim.api.nvim_create_augroup("Midnight", { clear = true }),
})
end
local hl_cache = {}
local reset = "\27[0m"
---@param name string
---@return string
local function get_fg_ansi(name)
if hl_cache[name] then
return hl_cache[name]
end
local hl = vim.api.nvim_get_hl(0, { name = name, link = false })
if not hl.fg then
hl_cache[name] = ""
return ""
end
local r = bit.rshift(bit.band(hl.fg, 0xff0000), 16)
local g = bit.rshift(bit.band(hl.fg, 0x00ff00), 8)
local b = bit.band(hl.fg, 0x0000ff)
local ansi = string.format("\27[38;2;%d;%d;%dm", r, g, b)
hl_cache[name] = ansi
return ansi
end
---@param lines string[]
---@return boolean
local function render_with_vim_syntax(lines)
local ok = pcall(vim.cmd.syntax, "enable")
if not ok then
return false
end
for lnum, text in ipairs(lines) do
if #text == 0 then
io.write("\n")
else
local rendered = {}
local current_group = nil
local chunk_start = 1
for col = 1, #text do
local syn_id = vim.fn.synID(lnum, col, 1)
local group = vim.fn.synIDattr(syn_id, "name")
if group ~= current_group then
if current_group then
local chunk = text:sub(chunk_start, col - 1)
local ansi = get_fg_ansi(current_group)
if ansi ~= "" then
table.insert(rendered, ansi)
table.insert(rendered, chunk)
table.insert(rendered, reset)
else
table.insert(rendered, chunk)
end
end
current_group = group
chunk_start = col
end
end
if current_group then
local chunk = text:sub(chunk_start)
local ansi = get_fg_ansi(current_group)
if ansi ~= "" then
table.insert(rendered, ansi)
table.insert(rendered, chunk)
table.insert(rendered, reset)
else
table.insert(rendered, chunk)
end
end
local line = table.concat(rendered)
io.write(line .. "\n")
end
end
io.flush()
return true
end
---@param lines string[]
local function render_plain(lines)
for _, line in ipairs(lines) do
io.write(line .. "\n")
end
io.flush()
end
---@param buf number
---@param lines string[]
---@param filetype string
---@param preview_line_count number
---@return table<number, table<number, {[1]: number, [2]: number, [3]: string}>>
local function collect_treesitter_highlights(buf, lines, filetype, preview_line_count)
local parser = vim.treesitter.get_parser(buf)
local trees = parser:parse()
if not trees or #trees == 0 then
return {}
end
local root = trees[1]:root()
local query = vim.treesitter.query.get(filetype, "highlights")
if not query then
return {}
end
---@type table<number, table<number, {[1]: number, [2]: number, [3]: string}>>
local line_highlights = {}
for id, node in query:iter_captures(root, buf, 0, preview_line_count) do
local name = query.captures[id]
local start_row, start_col, end_row, end_col = node:range()
for row = start_row, end_row do
line_highlights[row] = line_highlights[row] or {}
local s_col = row == start_row and start_col or 0
local e_col = row == end_row and end_col or #lines[row + 1]
table.insert(line_highlights[row], { s_col, e_col, name })
end
end
for _, highlights in pairs(line_highlights) do
table.sort(highlights, function(a, b)
if a[1] == b[1] then
return a[2] > b[2]
end
return a[1] < b[1]
end)
end
return line_highlights
end
---@param lines string[]
---@param line_highlights table<number, table<number, {[1]: number, [2]: number, [3]: string}>>
---@param filetype string
local function render_with_treesitter(lines, line_highlights, filetype)
for i, text in ipairs(lines) do
local row = i - 1
local highlights = line_highlights[row] or {}
if #highlights == 0 then
io.write(text .. "\n")
else
local rendered = {}
local pos = 0
---@type {[1]: number, [2]: number}[]
local used_ranges = {}
for _, hl in ipairs(highlights) do
local s_col, e_col, name = hl[1], hl[2], hl[3]
local skip = false
for _, used in ipairs(used_ranges) do
if s_col >= used[1] and s_col < used[2] then
skip = true
break
end
end
if not skip then
if pos < s_col then
table.insert(rendered, text:sub(pos + 1, s_col))
end
local chunk = text:sub(s_col + 1, e_col)
local ansi = get_fg_ansi("@" .. name .. "." .. filetype)
if ansi == "" then
ansi = get_fg_ansi("@" .. name)
end
if ansi ~= "" then
table.insert(rendered, ansi)
table.insert(rendered, chunk)
table.insert(rendered, reset)
else
table.insert(rendered, chunk)
end
table.insert(used_ranges, { s_col, e_col })
pos = e_col
end
end
if pos < #text then
table.insert(rendered, text:sub(pos + 1))
end
io.write(table.concat(rendered) .. "\n")
end
end
io.flush()
end
---@param filepath string
---@param preview_line_count number
function _G.lf.preview(filepath, preview_line_count)
vim.cmd.edit(filepath)
vim.cmd.colorscheme(vim.env.THEME)
local buf = vim.api.nvim_get_current_buf()
local lines = vim.api.nvim_buf_get_lines(buf, 0, preview_line_count, false)
local ft = vim.filetype.match({ buf = buf, filename = filepath })
local tsok, result = pcall(collect_treesitter_highlights, buf, lines, ft, preview_line_count)
if tsok and next(result) ~= nil then
render_with_treesitter(lines, result, ft)
elseif render_with_vim_syntax(lines) then
return
else
render_plain(lines)
end
end

View file

@ -1,72 +0,0 @@
#!/bin/sh
FILE_PATH="$1"
w="$2"
h="$3"
x="$4"
y="$5"
CACHE_DIR="$HOME/.cache/lf/thumbnail"
mkdir -p "$CACHE_DIR"
CACHE_BASE="$CACHE_DIR/$(stat --printf '%n\0%i\0%F\0%s\0%W\0%Y' -- "$(readlink -f "$FILE_PATH")" | sha256sum | awk '{print $1}')"
get_cell_size() {
size_info=$(kitten @ get-window-size --self)
cell_w=$(echo "$size_info" | awk 'BEGIN{RS="[{} ,]"} /"xpixels"/{gsub(/"/,"",$0); split($0,a,":"); x=a[2]} /"cols"/{gsub(/"/,"",$0); split($0,a,":"); c=a[2]} END{if(c) print int(x/c); else print 8}')
cell_h=$(echo "$size_info" | awk 'BEGIN{RS="[{} ,]"} /"ypixels"/{gsub(/"/,"",$0); split($0,a,":"); y=a[2]} /"rows"/{gsub(/"/,"",$0); split($0,a,":"); r=a[2]} END{if(r) print int(y/r); else print 16}')
}
draw() {
kitten icat --stdin no --transfer-mode memory --place "${w}x${h}@${x}x${y}" "$1" </dev/null >/dev/tty
exit 1
}
get_cell_size
preview_px_w=$((w * ${cell_w:-8} - 16))
preview_px_h=$((h * ${cell_h:-16} - 16))
PREVIEW_LINE_COUNT=200
mime_type=$(file -Lb --mime-type "$FILE_PATH")
case "$mime_type" in
image/gif | video/*)
if [ "$(stat -c %Y "$FILE_PATH" 2>/dev/null || echo 0)" -gt "$(stat -c %Y "${CACHE_BASE}.jpg" 2>/dev/null || echo 0)" ]; then
ffmpeg -y -i "$FILE_PATH" -vf "select=eq(n\,0),scale=${preview_px_w}:-1" -vframes 1 "${CACHE_BASE}.jpg"
fi
draw "${CACHE_BASE}.jpg"
;;
image/svg+xml | image/svg)
if [ "$(stat -c %Y "$FILE_PATH")" -gt "$(stat -c %Y "${CACHE_BASE}.png" 2>/dev/null || echo 0)" ]; then
rsvg-convert --keep-aspect-ratio --width "$preview_px_w" --format=png "$FILE_PATH" -o "${CACHE_BASE}.png"
fi
draw "${CACHE_BASE}.png"
;;
image/*)
draw "$FILE_PATH"
;;
application/pdf)
if [ "$(stat -c %Y "$FILE_PATH")" -gt "$(stat -c %Y "${CACHE_BASE}.jpg" 2>/dev/null || echo 0)" ]; then
pdftoppm -f 1 -l 1 -scale-to-x "$preview_px_w" -scale-to-y -1 -singlefile -jpeg -- "$FILE_PATH" "${CACHE_BASE}"
fi
draw "${CACHE_BASE}.jpg"
;;
application/epub+zip | application/x-mobipocket-ebook)
if [ "$(stat -c %Y "$FILE_PATH")" -gt "$(stat -c %Y "${CACHE_BASE}.png" 2>/dev/null || echo 0)" ]; then
gnome-epub-thumbnailer -s "$preview_px_w" "$FILE_PATH" "${CACHE_BASE}.png" 2>/dev/null || convert -size "${preview_px_w}x${preview_px_w}" xc:gray "${CACHE_BASE}.png"
fi
[ -f "${CACHE_BASE}.png" ] && draw "${CACHE_BASE}.png"
;;
audio/*)
if [ "$(stat -c %Y "$FILE_PATH")" -gt "$(stat -c %Y "${CACHE_BASE}.jpg" 2>/dev/null || echo 0)" ]; then
ffmpeg -y -i "$FILE_PATH" -an -vcodec copy "${CACHE_BASE}.jpg" 2>/dev/null || convert -size "${preview_px_w}x${preview_px_w}" xc:gray "${CACHE_BASE}.jpg"
fi
draw "${CACHE_BASE}.jpg"
;;
*)
nvim --headless -u NONE \
-c "luafile $XDG_CONFIG_HOME/lf/lf.lua" \
-c "lua lf.setup()" \
-c "lua lf.preview([[${FILE_PATH}]], ${PREVIEW_LINE_COUNT})" \
-c "quitall!"
;;
esac

View file

@ -1,53 +0,0 @@
#!/usr/bin/env python
import os
import sys
def categorize_and_sort(directory: str) -> list[str]:
try:
entries = os.listdir(directory)
except (PermissionError, FileNotFoundError):
return []
folders: list[str] = []
files: list[str] = []
dotfolders: list[str] = []
dotfiles: list[str] = []
for entry in entries:
full_path = os.path.join(directory, entry)
is_hidden = entry.startswith(".")
is_dir = os.path.isdir(full_path)
if not is_hidden and is_dir:
folders.append(entry)
elif not is_hidden and not is_dir:
files.append(entry)
elif is_hidden and is_dir:
dotfolders.append(entry)
else:
dotfiles.append(entry)
folders.sort(key=str.lower)
files.sort(key=str.lower)
dotfolders.sort(key=str.lower)
dotfiles.sort(key=str.lower)
return folders + files + dotfolders + dotfiles
def main() -> None:
if len(sys.argv) < 2:
directory = os.getcwd()
else:
directory = sys.argv[1]
sorted_entries = categorize_and_sort(directory)
for entry in sorted_entries:
print(entry)
if __name__ == "__main__":
main()

View file

@ -1,7 +1,7 @@
return {
'nvimdev/guard.nvim',
dependencies = {
{ 'nvimdev/guard-collection' },
{ dir = '~/dev/guard-collection' },
},
init = function()
vim.g.guard_config = {

View file

@ -0,0 +1,146 @@
/*******************************************************************************
* ROFI Color theme
* User: Sergio Morales
* Copyright: Sergio Morales
*******************************************************************************/
* {
selected-normal-foreground: rgba ( 255, 255, 255, 100 % );
foreground: rgba ( 82, 93, 118, 100 % );
normal-foreground: @foreground;
alternate-normal-background: rgba ( 245, 245, 245, 100 % );
red: rgba ( 220, 50, 47, 100 % );
selected-urgent-foreground: rgba ( 220, 50, 47, 100 % );
blue: rgba ( 38, 139, 210, 100 % );
urgent-foreground: rgba ( 220, 50, 47, 100 % );
alternate-urgent-background: rgba ( 245, 245, 245, 100 % );
active-foreground: rgba ( 194, 202, 208, 100 % );
lightbg: rgba ( 238, 232, 213, 100 % );
selected-active-foreground: rgba ( 194, 202, 208, 100 % );
alternate-active-background: rgba ( 245, 245, 245, 100 % );
background: rgba ( 255, 255, 255, 100 % );
bordercolor: rgba ( 245, 245, 245, 100 % );
alternate-normal-foreground: @foreground;
normal-background: rgba ( 255, 255, 255, 100 % );
lightfg: rgba ( 88, 104, 117, 100 % );
selected-normal-background: rgba ( 82, 148, 226, 100 % );
border-color: @foreground;
spacing: 2;
separatorcolor: @foreground;
urgent-background: rgba ( 255, 255, 255, 100 % );
selected-urgent-background: rgba ( 82, 148, 226, 100 % );
alternate-urgent-foreground: @urgent-foreground;
background-color: rgba ( 0, 0, 0, 0 % );
alternate-active-foreground: @active-foreground;
active-background: rgba ( 255, 255, 255, 100 % );
selected-active-background: rgba ( 82, 148, 226, 100 % );
}
window {
background-color: @background;
border: 1;
padding: 5;
}
mainbox {
border: 0;
padding: 0;
}
message {
border: 2px 0px 0px ;
border-color: @separatorcolor;
padding: 1px ;
}
textbox {
text-color: @foreground;
}
listview {
fixed-height: 0;
border: 2px 0px 0px ;
border-color: @separatorcolor;
spacing: 2px ;
scrollbar: true;
padding: 2px 0px 0px ;
}
element {
border: 0;
padding: 1px ;
}
element-text {
background-color: inherit;
text-color: inherit;
}
element.normal.normal {
background-color: @normal-background;
text-color: @normal-foreground;
}
element.normal.urgent {
background-color: @urgent-background;
text-color: @urgent-foreground;
}
element.normal.active {
background-color: @active-background;
text-color: @active-foreground;
}
element.selected.normal {
background-color: @selected-normal-background;
text-color: @selected-normal-foreground;
}
element.selected.urgent {
background-color: @selected-urgent-background;
text-color: @selected-urgent-foreground;
}
element.selected.active {
background-color: @selected-active-background;
text-color: @selected-active-foreground;
}
element.alternate.normal {
background-color: @alternate-normal-background;
text-color: @alternate-normal-foreground;
}
element.alternate.urgent {
background-color: @alternate-urgent-background;
text-color: @alternate-urgent-foreground;
}
element.alternate.active {
background-color: @alternate-active-background;
text-color: @alternate-active-foreground;
}
scrollbar {
width: 4px ;
border: 0;
handle-width: 8px ;
padding: 0;
}
mode-switcher {
border: 2px 0px 0px ;
border-color: @separatorcolor;
}
button.selected {
background-color: @selected-normal-background;
text-color: @selected-normal-foreground;
}
inputbar {
spacing: 0;
text-color: @normal-foreground;
padding: 1px ;
}
case-indicator {
spacing: 0;
text-color: @normal-foreground;
}
entry {
spacing: 0;
text-color: @normal-foreground;
}
prompt {
spacing: 0;
text-color: @normal-foreground;
}
inputbar {
children: [ prompt,textbox-prompt-colon,entry,case-indicator ];
}
textbox-prompt-colon {
expand: false;
str: ":";
margin: 0px 0.3em 0em 0em ;
text-color: @normal-foreground;
}

View file

@ -0,0 +1,11 @@
set -g status-bg '#f5f5f5'
set -g status-fg '#1a1a1a'
set -g window-status-style fg='#1a1a1a'
set -g window-status-current-style fg='#1a1a1a'
set -g window-status-bell-style fg='#c7254e',bg='#f5f5f5',bold
set -g window-status-activity-style fg='#3b5bdb',bg='#f5f5f5',bold
set -g pane-border-style fg='#e8e8e8'
set -g pane-active-border-style fg='#1a1a1a'
set -g copy-mode-selection-style fg='#f5f5f5',bg='yellow'
set -g copy-mode-current-match-style fg='#f5f5f5',bg='yellow'
set -g copy-mode-match-style 'reverse'

View file

@ -0,0 +1,11 @@
set -g status-bg '#121212'
set -g status-fg '#e0e0e0'
set -g window-status-style fg='#e0e0e0'
set -g window-status-current-style fg='#e0e0e0'
set -g window-status-bell-style fg='#ff6b6b',bg='#121212',bold
set -g window-status-activity-style fg='#7aa2f7',bg='#121212',bold
set -g pane-border-style fg='#3d3d3d'
set -g pane-active-border-style fg='#e0e0e0'
set -g copy-mode-selection-style fg='#121212',bg='yellow'
set -g copy-mode-current-match-style fg='#121212',bg='yellow'
set -g copy-mode-match-style 'reverse'