Compare commits

...

3 commits

Author SHA1 Message Date
5f93ecba7c
lua: Format with stylua 2023-06-15 10:12:30 +02:00
e434c191c9
nvim: Switch away from depredcated nvim_exec function
Use nvim_exec2 instead, which is weirdly named.
2023-06-15 10:00:20 +02:00
2dbd94dda4
nvim: Remove copyright abbreviation
I never used it once.
2023-06-15 09:59:45 +02:00
34 changed files with 4063 additions and 3415 deletions

View file

@ -21,47 +21,85 @@ audio=yes
MAXENTRIES = 5000 MAXENTRIES = 5000
local msg = require 'mp.msg' local msg = require("mp.msg")
local options = require 'mp.options' local options = require("mp.options")
local utils = require 'mp.utils' local utils = require("mp.utils")
o = { o = {
disabled = false, disabled = false,
images = true, images = true,
videos = true, videos = true,
audio = true audio = true,
} }
options.read_options(o) options.read_options(o)
function Set (t) function Set(t)
local set = {} local set = {}
for _, v in pairs(t) do set[v] = true end for _, v in pairs(t) do
set[v] = true
end
return set return set
end end
function SetUnion (a,b) function SetUnion(a, b)
local res = {} local res = {}
for k in pairs(a) do res[k] = true end for k in pairs(a) do
for k in pairs(b) do res[k] = true end res[k] = true
end
for k in pairs(b) do
res[k] = true
end
return res return res
end end
EXTENSIONS_VIDEO = Set { EXTENSIONS_VIDEO = Set({
'mkv', 'avi', 'mp4', 'ogv', 'webm', 'rmvb', 'flv', 'wmv', 'mpeg', 'mpg', 'm4v', '3gp' "mkv",
} "avi",
"mp4",
"ogv",
"webm",
"rmvb",
"flv",
"wmv",
"mpeg",
"mpg",
"m4v",
"3gp",
})
EXTENSIONS_AUDIO = Set { EXTENSIONS_AUDIO = Set({
'mp3', 'wav', 'ogm', 'flac', 'm4a', 'wma', 'ogg', 'opus' "mp3",
} "wav",
"ogm",
"flac",
"m4a",
"wma",
"ogg",
"opus",
})
EXTENSIONS_IMAGES = Set { EXTENSIONS_IMAGES = Set({
'jpg', 'jpeg', 'png', 'tif', 'tiff', 'gif', 'webp', 'svg', 'bmp' "jpg",
} "jpeg",
"png",
"tif",
"tiff",
"gif",
"webp",
"svg",
"bmp",
})
EXTENSIONS = Set {} EXTENSIONS = Set({})
if o.videos then EXTENSIONS = SetUnion(EXTENSIONS, EXTENSIONS_VIDEO) end if o.videos then
if o.audio then EXTENSIONS = SetUnion(EXTENSIONS, EXTENSIONS_AUDIO) end EXTENSIONS = SetUnion(EXTENSIONS, EXTENSIONS_VIDEO)
if o.images then EXTENSIONS = SetUnion(EXTENSIONS, EXTENSIONS_IMAGES) end end
if o.audio then
EXTENSIONS = SetUnion(EXTENSIONS, EXTENSIONS_AUDIO)
end
if o.images then
EXTENSIONS = SetUnion(EXTENSIONS, EXTENSIONS_IMAGES)
end
function add_files_at(index, files) function add_files_at(index, files)
index = index - 1 index = index - 1
@ -73,7 +111,7 @@ function add_files_at(index, files)
end end
function get_extension(path) function get_extension(path)
match = string.match(path, "%.([^%.]+)$" ) match = string.match(path, "%.([^%.]+)$")
if match == nil then if match == nil then
return "nomatch" return "nomatch"
else else
@ -97,14 +135,18 @@ end
function splitbynum(s) function splitbynum(s)
local result = {} local result = {}
for x, y in (s or ""):gmatch("(%d*)(%D*)") do for x, y in (s or ""):gmatch("(%d*)(%D*)") do
if x ~= "" then table.insert(result, tonumber(x)) end if x ~= "" then
if y ~= "" then table.insert(result, y) end table.insert(result, tonumber(x))
end
if y ~= "" then
table.insert(result, y)
end
end end
return result return result
end end
function clean_key(k) function clean_key(k)
k = (' '..k..' '):gsub("%s+", " "):sub(2, -2):lower() k = (" " .. k .. " "):gsub("%s+", " "):sub(2, -2):lower()
return splitbynum(k) return splitbynum(k)
end end
@ -113,9 +155,14 @@ function alnumcomp(x, y)
local xt, yt = clean_key(x), clean_key(y) local xt, yt = clean_key(x), clean_key(y)
for i = 1, math.min(#xt, #yt) do for i = 1, math.min(#xt, #yt) do
local xe, ye = xt[i], yt[i] local xe, ye = xt[i], yt[i]
if type(xe) == "string" then ye = tostring(ye) if type(xe) == "string" then
elseif type(ye) == "string" then xe = tostring(xe) end ye = tostring(ye)
if xe ~= ye then return xe < ye end elseif type(ye) == "string" then
xe = tostring(xe)
end
if xe ~= ye then
return xe < ye
end
end end
return #xt < #yt return #xt < #yt
end end
@ -136,8 +183,10 @@ function find_and_add_entries()
local pl_count = mp.get_property_number("playlist-count", 1) local pl_count = mp.get_property_number("playlist-count", 1)
-- check if this is a manually made playlist -- check if this is a manually made playlist
if (pl_count > 1 and autoloaded == nil) or if
(pl_count == 1 and EXTENSIONS[string.lower(get_extension(filename))] == nil) then (pl_count > 1 and autoloaded == nil)
or (pl_count == 1 and EXTENSIONS[string.lower(get_extension(filename))] == nil)
then
msg.verbose("stopping: manually made playlist") msg.verbose("stopping: manually made playlist")
return return
else else
@ -146,15 +195,14 @@ function find_and_add_entries()
local pl = mp.get_property_native("playlist", {}) local pl = mp.get_property_native("playlist", {})
local pl_current = mp.get_property_number("playlist-pos-1", 1) local pl_current = mp.get_property_number("playlist-pos-1", 1)
msg.trace(("playlist-pos-1: %s, playlist: %s"):format(pl_current, msg.trace(("playlist-pos-1: %s, playlist: %s"):format(pl_current, utils.to_string(pl)))
utils.to_string(pl)))
local files = utils.readdir(dir, "files") local files = utils.readdir(dir, "files")
if files == nil then if files == nil then
msg.verbose("no other files in directory") msg.verbose("no other files in directory")
return return
end end
table.filter(files, function (v, k) table.filter(files, function(v, k)
if string.match(v, "^%.") then if string.match(v, "^%.") then
return false return false
end end
@ -181,9 +229,9 @@ function find_and_add_entries()
if current == nil then if current == nil then
return return
end end
msg.trace("current file position in files: "..current) msg.trace("current file position in files: " .. current)
local append = {[-1] = {}, [1] = {}} local append = { [-1] = {}, [1] = {} }
for direction = -1, 1, 2 do -- 2 iterations, with direction = -1 and +1 for direction = -1, 1, 2 do -- 2 iterations, with direction = -1 and +1
for i = 1, MAXENTRIES do for i = 1, MAXENTRIES do
local file = files[current + i * direction] local file = files[current + i * direction]
@ -195,7 +243,7 @@ function find_and_add_entries()
local filepath = dir .. file local filepath = dir .. file
if pl_e then if pl_e then
-- If there's a playlist entry, and it's the same file, stop. -- If there's a playlist entry, and it's the same file, stop.
msg.trace(pl_e.filename.." == "..filepath.." ?") msg.trace(pl_e.filename .. " == " .. filepath .. " ?")
if pl_e.filename == filepath then if pl_e.filename == filepath then
break break
end end

View file

@ -1,5 +1,5 @@
-- If the laptop is on battery, the profile 'lq' will be loaded; otherwise 'hq' is used -- If the laptop is on battery, the profile 'lq' will be loaded; otherwise 'hq' is used
local mp = require 'mp' local mp = require("mp")
local SHOULD_ADJUST = false local SHOULD_ADJUST = false
@ -8,14 +8,18 @@ local hqprofile = "highquality"
local function powerstate() local function powerstate()
local f = io.open("/sys/class/power_supply/AC/online") local f = io.open("/sys/class/power_supply/AC/online")
if f == nil then return end if f == nil then
return
end
local t = f:read("*n") local t = f:read("*n")
f:close() f:close()
return t return t
end end
local function adjust() local function adjust()
if not SHOULD_ADJUST then return end if not SHOULD_ADJUST then
return
end
local state = powerstate() local state = powerstate()
-- this actually overrides automatically applied profiles -- this actually overrides automatically applied profiles

View file

@ -1,5 +1,5 @@
local mp = require 'mp' local mp = require("mp")
require 'mp.msg' require("mp.msg")
-- Copy the current time of the video to clipboard. -- Copy the current time of the video to clipboard.
@ -8,7 +8,7 @@ UNIX = 3
KEY_BIND = "y" KEY_BIND = "y"
local function platform_type() local function platform_type()
local utils = require 'mp.utils' local utils = require("mp.utils")
local workdir = utils.to_string(mp.get_property_native("working-directory")) local workdir = utils.to_string(mp.get_property_native("working-directory"))
if string.find(workdir, "\\") then if string.find(workdir, "\\") then
return WINDOWS return WINDOWS
@ -18,8 +18,10 @@ local function platform_type()
end end
local function command_exists(cmd) local function command_exists(cmd)
local pipe = io.popen("type " .. cmd .. " > /dev/null 2> /dev/null; printf \"$?\"", "r") local pipe = io.popen("type " .. cmd .. ' > /dev/null 2> /dev/null; printf "$?"', "r")
if not pipe then return end if not pipe then
return
end
local exists = pipe:read() == "0" local exists = pipe:read() == "0"
pipe:close() pipe:close()
return exists return exists
@ -46,9 +48,11 @@ local function set_clipboard(text)
if platform == WINDOWS then if platform == WINDOWS then
mp.commandv("run", "powershell", "set-clipboard", text) mp.commandv("run", "powershell", "set-clipboard", text)
return true return true
elseif (platform == UNIX and clipboard_cmd) then elseif platform == UNIX and clipboard_cmd then
local pipe = io.popen(clipboard_cmd, "w") local pipe = io.popen(clipboard_cmd, "w")
if not pipe then return end if not pipe then
return
end
pipe:write(text) pipe:write(text)
pipe:close() pipe:close()
return true return true
@ -72,7 +76,6 @@ local function copyTime()
end end
end end
platform = platform_type() platform = platform_type()
if platform == UNIX then if platform == UNIX then
clipboard_cmd = get_clipboard_cmd() clipboard_cmd = get_clipboard_cmd()

View file

@ -7,9 +7,9 @@
-- e.g. -- e.g.
-- `mpv gallery-dl://https://imgur.com/....` -- `mpv gallery-dl://https://imgur.com/....`
local mp = require 'mp' local mp = require("mp")
local utils = require 'mp.utils' local utils = require("mp.utils")
local msg = require 'mp.msg' local msg = require("mp.msg")
local function exec(args) local function exec(args)
local ret = utils.subprocess({ args = args }) local ret = utils.subprocess({ args = args })
@ -18,7 +18,7 @@ end
mp.add_hook("on_load", 15, function() mp.add_hook("on_load", 15, function()
local fn = mp.get_property("stream-open-filename", "") local fn = mp.get_property("stream-open-filename", "")
if (fn:find("gdl://") ~= 1) then if fn:find("gdl://") ~= 1 then
msg.debug("not a gdl:// url: " .. fn) msg.debug("not a gdl:// url: " .. fn)
return return
end end

View file

@ -154,12 +154,12 @@ local settings = {
-- what to show when playlist is truncated -- what to show when playlist is truncated
playlist_sliced_prefix = "...", playlist_sliced_prefix = "...",
playlist_sliced_suffix = "..." playlist_sliced_suffix = "...",
} }
local opts = require("mp.options") local opts = require("mp.options")
opts.read_options(settings, "playlistmanager", opts.read_options(settings, "playlistmanager", function(list)
function(list) update_opts(list) end) update_opts(list)
end)
local utils = require("mp.utils") local utils = require("mp.utils")
local msg = require("mp.msg") local msg = require("mp.msg")
@ -168,7 +168,7 @@ local assdraw = require("mp.assdraw")
-- check os -- check os
if settings.system == "auto" then if settings.system == "auto" then
local o = {} local o = {}
if mp.get_property_native('options/vo-mmcss-profile', o) ~= o then if mp.get_property_native("options/vo-mmcss-profile", o) ~= o then
settings.system = "windows" settings.system = "windows"
else else
settings.system = "linux" settings.system = "linux"
@ -194,13 +194,12 @@ local sort_watching = false
local filetype_lookup = {} local filetype_lookup = {}
function update_opts(changelog) function update_opts(changelog)
msg.verbose('updating options') msg.verbose("updating options")
-- parse filename json -- parse filename json
if changelog.filename_replace then if changelog.filename_replace then
if (settings.filename_replace ~= "") then if settings.filename_replace ~= "" then
settings.filename_replace = utils.parse_json( settings.filename_replace = utils.parse_json(settings.filename_replace)
settings.filename_replace)
else else
settings.filename_replace = false settings.filename_replace = false
end end
@ -208,8 +207,7 @@ function update_opts(changelog)
-- parse loadfiles json -- parse loadfiles json
if changelog.loadfiles_filetypes then if changelog.loadfiles_filetypes then
settings.loadfiles_filetypes = utils.parse_json( settings.loadfiles_filetypes = utils.parse_json(settings.loadfiles_filetypes)
settings.loadfiles_filetypes)
filetype_lookup = {} filetype_lookup = {}
-- create loadfiles set -- create loadfiles set
@ -218,25 +216,28 @@ function update_opts(changelog)
end end
end end
if changelog.resolve_titles then resolve_titles() end if changelog.resolve_titles then
resolve_titles()
end
if changelog.playlist_display_timeout then if changelog.playlist_display_timeout then
keybindstimer = mp.add_periodic_timer(settings.playlist_display_timeout, keybindstimer = mp.add_periodic_timer(settings.playlist_display_timeout, remove_keybinds)
remove_keybinds)
keybindstimer:kill() keybindstimer:kill()
end end
if playlist_visible then showplaylist() end if playlist_visible then
showplaylist()
end
end end
update_opts({filename_replace = true, loadfiles_filetypes = true}) update_opts({ filename_replace = true, loadfiles_filetypes = true })
function on_loaded() function on_loaded()
filename = mp.get_property("filename") filename = mp.get_property("filename")
path = mp.get_property('path') path = mp.get_property("path")
-- if not a url then join path with working directory -- if not a url then join path with working directory
if not path:match("^%a%a+:%/%/") then if not path:match("^%a%a+:%/%/") then
path = utils.join_path(mp.get_property('working-directory'), path) path = utils.join_path(mp.get_property("working-directory"), path)
directory = utils.split_path(path) directory = utils.split_path(path)
else else
directory = nil directory = nil
@ -246,23 +247,24 @@ function on_loaded()
if settings.sync_cursor_on_load then if settings.sync_cursor_on_load then
cursor = pos cursor = pos
-- refresh playlist if cursor moved -- refresh playlist if cursor moved
if playlist_visible then draw_playlist() end if playlist_visible then
draw_playlist()
end
end end
local media_title = mp.get_property("media-title") local media_title = mp.get_property("media-title")
if path:match('^https?://') and not url_table[path] and path ~= media_title then if path:match("^https?://") and not url_table[path] and path ~= media_title then
url_table[path] = media_title url_table[path] = media_title
end end
strippedname = stripfilename(mp.get_property('media-title')) strippedname = stripfilename(mp.get_property("media-title"))
if settings.show_playlist_on_fileload == 2 then if settings.show_playlist_on_fileload == 2 then
showplaylist() showplaylist()
elseif settings.show_playlist_on_fileload == 1 then elseif settings.show_playlist_on_fileload == 1 then
mp.commandv('show-text', strippedname) mp.commandv("show-text", strippedname)
end end
if settings.set_title_stripped then if settings.set_title_stripped then
mp.set_property("title", settings.title_prefix .. strippedname .. mp.set_property("title", settings.title_prefix .. strippedname .. settings.title_suffix)
settings.title_suffix)
end end
local didload = false local didload = false
@ -288,7 +290,7 @@ function on_loaded()
promised_sort_watch = false promised_sort_watch = false
sort_watching = true sort_watching = true
msg.info("Added files will be automatically sorted") msg.info("Added files will be automatically sorted")
mp.observe_property('playlist-count', "number", autosort) mp.observe_property("playlist-count", "number", autosort)
end end
end end
@ -297,33 +299,38 @@ function on_closed()
path = nil path = nil
directory = nil directory = nil
filename = nil filename = nil
if playlist_visible then showplaylist() end if playlist_visible then
showplaylist()
end
end end
function refresh_globals() function refresh_globals()
pos = mp.get_property_number('playlist-pos', 0) pos = mp.get_property_number("playlist-pos", 0)
plen = mp.get_property_number('playlist-count', 0) plen = mp.get_property_number("playlist-count", 0)
end end
function escapepath(dir, escapechar) function escapepath(dir, escapechar)
return string.gsub(dir, escapechar, '\\' .. escapechar) return string.gsub(dir, escapechar, "\\" .. escapechar)
end end
-- strip a filename based on its extension or protocol according to rules in settings -- strip a filename based on its extension or protocol according to rules in settings
function stripfilename(pathfile, media_title) function stripfilename(pathfile, media_title)
if pathfile == nil then return '' end if pathfile == nil then
return ""
end
local ext = pathfile:match("^.+%.(.+)$") local ext = pathfile:match("^.+%.(.+)$")
local protocol = pathfile:match("^(%a%a+)://") local protocol = pathfile:match("^(%a%a+)://")
if not ext then ext = "" end if not ext then
ext = ""
end
local tmp = pathfile local tmp = pathfile
if settings.filename_replace and not media_title then if settings.filename_replace and not media_title then
for k, v in ipairs(settings.filename_replace) do for k, v in ipairs(settings.filename_replace) do
if (v['ext'] and if
(v['ext'][ext] or (ext and not protocol and v['ext']['all']))) or (v["ext"] and (v["ext"][ext] or (ext and not protocol and v["ext"]["all"])))
(v['protocol'] and or (v["protocol"] and (v["protocol"][protocol] or (protocol and not ext and v["protocol"]["all"])))
(v['protocol'][protocol] or then
(protocol and not ext and v['protocol']['all']))) then for ruleindex, indexrules in ipairs(v["rules"]) do
for ruleindex, indexrules in ipairs(v['rules']) do
for rule, override in pairs(indexrules) do for rule, override in pairs(indexrules) do
tmp = tmp:gsub(rule, override) tmp = tmp:gsub(rule, override)
end end
@ -331,8 +338,7 @@ function stripfilename(pathfile, media_title)
end end
end end
end end
if settings.slice_longfilenames and tmp:len() > if settings.slice_longfilenames and tmp:len() > settings.slice_longfilenames_amount + 5 then
settings.slice_longfilenames_amount + 5 then
tmp = tmp:sub(1, settings.slice_longfilenames_amount) .. " ..." tmp = tmp:sub(1, settings.slice_longfilenames_amount) .. " ..."
end end
return tmp return tmp
@ -342,21 +348,22 @@ end
function get_name_from_index(i, notitle) function get_name_from_index(i, notitle)
refresh_globals() refresh_globals()
if plen <= i then if plen <= i then
msg.error("no index in playlist", i, "length", plen); msg.error("no index in playlist", i, "length", plen)
return nil return nil
end end
local _, name = nil local _, name = nil
local title = mp.get_property('playlist/' .. i .. '/title') local title = mp.get_property("playlist/" .. i .. "/title")
local name = mp.get_property('playlist/' .. i .. '/filename') local name = mp.get_property("playlist/" .. i .. "/filename")
local should_use_title = settings.prefer_titles == 'all' or local should_use_title = settings.prefer_titles == "all"
name:match('^https?://') and or name:match("^https?://") and settings.prefer_titles == "url"
settings.prefer_titles == 'url'
-- check if file has a media title stored or as property -- check if file has a media title stored or as property
if not title and should_use_title then if not title and should_use_title then
local mtitle = mp.get_property('media-title') local mtitle = mp.get_property("media-title")
if i == pos and mp.get_property('filename') ~= mtitle then if i == pos and mp.get_property("filename") ~= mtitle then
if not url_table[name] then url_table[name] = mtitle end if not url_table[name] then
url_table[name] = mtitle
end
title = mtitle title = mtitle
elseif url_table[name] then elseif url_table[name] then
title = url_table[name] title = url_table[name]
@ -369,30 +376,31 @@ function get_name_from_index(i, notitle)
end end
-- remove paths if they exist, keeping protocols for stripping -- remove paths if they exist, keeping protocols for stripping
if string.sub(name, 1, 1) == '/' or name:match("^%a:[/\\]") then if string.sub(name, 1, 1) == "/" or name:match("^%a:[/\\]") then
_, name = utils.split_path(name) _, name = utils.split_path(name)
end end
return stripfilename(name) return stripfilename(name)
end end
function parse_header(string) function parse_header(string)
local esc_title = stripfilename(mp.get_property("media-title"), true):gsub( local esc_title = stripfilename(mp.get_property("media-title"), true):gsub("%%", "%%%%")
"%%", "%%%%") local esc_file = stripfilename(mp.get_property("filename")):gsub("%%", "%%%%")
local esc_file = stripfilename(mp.get_property("filename")):gsub("%%", return string
"%%%%") :gsub("%%N", "\\N")
return string:gsub("%%N", "\\N"):gsub("%%pos", mp.get_property_number( :gsub("%%pos", mp.get_property_number("playlist-pos", 0) + 1)
"playlist-pos", 0) + 1):gsub( :gsub("%%plen", mp.get_property("playlist-count"))
"%%plen", mp.get_property("playlist-count")):gsub("%%cursor", :gsub("%%cursor", cursor + 1)
cursor + 1) :gsub("%%mediatitle", esc_title)
:gsub("%%mediatitle", esc_title):gsub("%%filename", esc_file) -- undo name escape :gsub("%%filename", esc_file) -- undo name escape
:gsub("%%%%", "%%") :gsub("%%%%", "%%")
end end
function parse_filename(string, name, index) function parse_filename(string, name, index)
local base = tostring(plen):len() local base = tostring(plen):len()
local esc_name = stripfilename(name):gsub("%%", "%%%%") local esc_name = stripfilename(name):gsub("%%", "%%%%")
return string:gsub("%%N", "\\N"):gsub("%%pos", string.format( return string
"%0" .. base .. "d", index + 1)) :gsub("%%N", "\\N")
:gsub("%%pos", string.format("%0" .. base .. "d", index + 1))
:gsub("%%name", esc_name) -- undo name escape :gsub("%%name", esc_name) -- undo name escape
:gsub("%%%%", "%%") :gsub("%%%%", "%%")
end end
@ -400,7 +408,7 @@ end
function parse_filename_by_index(index) function parse_filename_by_index(index)
local template = settings.normal_file local template = settings.normal_file
local is_idle = mp.get_property_native('idle-active') local is_idle = mp.get_property_native("idle-active")
local position = is_idle and -1 or pos local position = is_idle and -1 or pos
if index == position then if index == position then
@ -437,7 +445,9 @@ function draw_playlist()
local start = cursor - math.floor(settings.showamount / 2) local start = cursor - math.floor(settings.showamount / 2)
local showall = false local showall = false
local showrest = false local showrest = false
if start < 0 then start = 0 end if start < 0 then
start = 0
end
if plen <= settings.showamount then if plen <= settings.showamount then
start = 0 start = 0
showall = true showall = true
@ -450,14 +460,19 @@ function draw_playlist()
ass:append(settings.playlist_sliced_prefix .. "\\N") ass:append(settings.playlist_sliced_prefix .. "\\N")
end end
for index = start, start + settings.showamount - 1, 1 do for index = start, start + settings.showamount - 1, 1 do
if index == plen then break end if index == plen then
break
end
ass:append(parse_filename_by_index(index) .. "\\N") ass:append(parse_filename_by_index(index) .. "\\N")
if index == start + settings.showamount - 1 and not showall and if index == start + settings.showamount - 1 and not showall and not showrest then
not showrest then ass:append(settings.playlist_sliced_suffix) end ass:append(settings.playlist_sliced_suffix)
end
end end
local w, h = mp.get_osd_size() local w, h = mp.get_osd_size()
if settings.scale_playlist_by_window then w, h = 0, 0 end if settings.scale_playlist_by_window then
w, h = 0, 0
end
mp.set_osd_ass(w, h, ass.text) mp.set_osd_ass(w, h, ass.text)
end end
@ -473,7 +488,9 @@ end
function showplaylist(duration) function showplaylist(duration)
refresh_globals() refresh_globals()
if plen == 0 then return end if plen == 0 then
return
end
playlist_visible = true playlist_visible = true
add_keybinds() add_keybinds()
@ -489,7 +506,9 @@ end
selection = nil selection = nil
function selectfile() function selectfile()
refresh_globals() refresh_globals()
if plen == 0 then return end if plen == 0 then
return
end
if not selection then if not selection then
selection = cursor selection = cursor
else else
@ -505,27 +524,34 @@ end
function removefile() function removefile()
refresh_globals() refresh_globals()
if plen == 0 then return end if plen == 0 then
return
end
selection = nil selection = nil
if cursor == pos then if cursor == pos then
mp.command( mp.command('script-message unseenplaylist mark true "playlistmanager avoid conflict when removing file"')
"script-message unseenplaylist mark true \"playlistmanager avoid conflict when removing file\"")
end end
mp.commandv("playlist-remove", cursor) mp.commandv("playlist-remove", cursor)
if cursor == plen - 1 then cursor = cursor - 1 end if cursor == plen - 1 then
cursor = cursor - 1
end
showplaylist() showplaylist()
end end
function moveup() function moveup()
refresh_globals() refresh_globals()
if plen == 0 then return end if plen == 0 then
return
end
if cursor ~= 0 then if cursor ~= 0 then
if selection then if selection then
mp.commandv("playlist-move", cursor, cursor - 1) mp.commandv("playlist-move", cursor, cursor - 1)
end end
cursor = cursor - 1 cursor = cursor - 1
elseif settings.loop_cursor then elseif settings.loop_cursor then
if selection then mp.commandv("playlist-move", cursor, plen) end if selection then
mp.commandv("playlist-move", cursor, plen)
end
cursor = plen - 1 cursor = plen - 1
end end
showplaylist() showplaylist()
@ -533,14 +559,18 @@ end
function movedown() function movedown()
refresh_globals() refresh_globals()
if plen == 0 then return end if plen == 0 then
return
end
if cursor ~= plen - 1 then if cursor ~= plen - 1 then
if selection then if selection then
mp.commandv("playlist-move", cursor, cursor + 2) mp.commandv("playlist-move", cursor, cursor + 2)
end end
cursor = cursor + 1 cursor = cursor + 1
elseif settings.loop_cursor then elseif settings.loop_cursor then
if selection then mp.commandv("playlist-move", cursor, 0) end if selection then
mp.commandv("playlist-move", cursor, 0)
end
cursor = 0 cursor = 0
end end
showplaylist() showplaylist()
@ -554,27 +584,38 @@ end
function playfile() function playfile()
refresh_globals() refresh_globals()
if plen == 0 then return end if plen == 0 then
return
end
selection = nil selection = nil
local is_idle = mp.get_property_native('idle-active') local is_idle = mp.get_property_native("idle-active")
if cursor ~= pos or is_idle then if cursor ~= pos or is_idle then
mp.set_property("playlist-pos", cursor) mp.set_property("playlist-pos", cursor)
else else
if cursor ~= plen - 1 then cursor = cursor + 1 end if cursor ~= plen - 1 then
cursor = cursor + 1
end
Watch_later() Watch_later()
mp.commandv("playlist-next", "weak") mp.commandv("playlist-next", "weak")
end end
if settings.show_playlist_on_fileload ~= 2 then remove_keybinds() end if settings.show_playlist_on_fileload ~= 2 then
remove_keybinds()
end
end end
function get_files_windows(dir) function get_files_windows(dir)
local args = { local args = {
'powershell', '-NoProfile', '-Command', [[& { "powershell",
"-NoProfile",
"-Command",
[[& {
Trap { Trap {
Write-Error -ErrorRecord $_ Write-Error -ErrorRecord $_
Exit 1 Exit 1
} }
$path = "]] .. dir .. [[" $path = "]]
.. dir
.. [["
$escapedPath = [WildcardPattern]::Escape($path) $escapedPath = [WildcardPattern]::Escape($path)
cd $escapedPath cd $escapedPath
@ -582,16 +623,16 @@ function get_files_windows(dir)
$string = ($list -join "/") $string = ($list -join "/")
$u8list = [System.Text.Encoding]::UTF8.GetBytes($string) $u8list = [System.Text.Encoding]::UTF8.GetBytes($string)
[Console]::OpenStandardOutput().Write($u8list, 0, $u8list.Length) [Console]::OpenStandardOutput().Write($u8list, 0, $u8list.Length)
}]] }]],
} }
local process = utils.subprocess({args = args, cancellable = false}) local process = utils.subprocess({ args = args, cancellable = false })
return parse_files(process, '%/') return parse_files(process, "%/")
end end
function get_files_linux(dir) function get_files_linux(dir)
local args = {'ls', '-1pv', dir} local args = { "ls", "-1pv", dir }
local process = utils.subprocess({args = args, cancellable = false}) local process = utils.subprocess({ args = args, cancellable = false })
return parse_files(process, '\n') return parse_files(process, "\n")
end end
function parse_files(res, delimiter) function parse_files(res, delimiter)
@ -613,15 +654,19 @@ end
-- For exaple, Folder has 12 files, you open the 5th file and run this, the remaining 7 are added behind the 5th file and prior 4 files before it -- For exaple, Folder has 12 files, you open the 5th file and run this, the remaining 7 are added behind the 5th file and prior 4 files before it
function playlist(force_dir) function playlist(force_dir)
refresh_globals() refresh_globals()
if not directory and plen > 0 then return end if not directory and plen > 0 then
return
end
local hasfile = true local hasfile = true
if plen == 0 then if plen == 0 then
hasfile = false hasfile = false
dir = mp.get_property('working-directory') dir = mp.get_property("working-directory")
else else
dir = directory dir = directory
end end
if force_dir then dir = force_dir end if force_dir then
dir = force_dir
end
local files, error local files, error
if settings.system == "linux" then if settings.system == "linux" then
@ -648,8 +693,7 @@ function playlist(force_dir)
elseif file ~= filename then elseif file ~= filename then
mp.commandv("loadfile", utils.join_path(dir, file), appendstr) mp.commandv("loadfile", utils.join_path(dir, file), appendstr)
msg.info("Prepended to playlist: " .. file) msg.info("Prepended to playlist: " .. file)
mp.commandv("playlist-move", mp.commandv("playlist-move", mp.get_property_number("playlist-count", 1) - 1, c)
mp.get_property_number("playlist-count", 1) - 1, c)
c = c + 1 c = c + 1
else else
cur = true cur = true
@ -660,7 +704,7 @@ function playlist(force_dir)
else else
mp.osd_message("No additional files found") mp.osd_message("No additional files found")
end end
cursor = mp.get_property_number('playlist-pos', 1) cursor = mp.get_property_number("playlist-pos", 1)
else else
msg.error("Could not scan for files: " .. (error or "")) msg.error("Could not scan for files: " .. (error or ""))
end end
@ -669,12 +713,16 @@ function playlist(force_dir)
sortplaylist() sortplaylist()
end end
refresh_globals() refresh_globals()
if playlist_visible then showplaylist() end if playlist_visible then
showplaylist()
end
return c + c2 return c + c2
end end
function parse_home(path) function parse_home(path)
if not path:find("^~") then return path end if not path:find("^~") then
return path
end
local home_dir = os.getenv("HOME") or os.getenv("USERPROFILE") local home_dir = os.getenv("HOME") or os.getenv("USERPROFILE")
if not home_dir then if not home_dir then
local drive = os.getenv("HOMEDRIVE") local drive = os.getenv("HOMEDRIVE")
@ -692,60 +740,69 @@ end
-- saves the current playlist into a m3u file -- saves the current playlist into a m3u file
function save_playlist() function save_playlist()
local length = mp.get_property_number('playlist-count', 0) local length = mp.get_property_number("playlist-count", 0)
if length == 0 then return end if length == 0 then
return
end
-- get playlist save path -- get playlist save path
local savepath local savepath
if settings.playlist_savepath == nil or settings.playlist_savepath == "" then if settings.playlist_savepath == nil or settings.playlist_savepath == "" then
savepath = mp.command_native({"expand-path", "~~home/"}) .. "/playlists" savepath = mp.command_native({ "expand-path", "~~home/" }) .. "/playlists"
else else
savepath = parse_home(settings.playlist_savepath) savepath = parse_home(settings.playlist_savepath)
if savepath == nil then return end if savepath == nil then
return
end
end end
-- create savepath if it doesn't exist -- create savepath if it doesn't exist
if utils.readdir(savepath) == nil then if utils.readdir(savepath) == nil then
local windows_args = { local windows_args = {
'powershell', '-NoProfile', '-Command', 'mkdir', savepath "powershell",
"-NoProfile",
"-Command",
"mkdir",
savepath,
} }
local unix_args = {'mkdir', savepath} local unix_args = { "mkdir", savepath }
local args = settings.system == 'windows' and windows_args or unix_args local args = settings.system == "windows" and windows_args or unix_args
local res = utils.subprocess({args = args, cancellable = false}) local res = utils.subprocess({ args = args, cancellable = false })
if res.status ~= 0 then if res.status ~= 0 then
msg.error("Failed to create playlist save directory " .. savepath .. msg.error(
". Error: " .. (res.error or "unknown")) "Failed to create playlist save directory " .. savepath .. ". Error: " .. (res.error or "unknown")
)
return return
end end
end end
local date = os.date("*t") local date = os.date("*t")
local datestring = ("%02d-%02d-%02d_%02d-%02d-%02d"):format(date.year, local datestring = ("%02d-%02d-%02d_%02d-%02d-%02d"):format(
date.year,
date.month, date.month,
date.day, date.day,
date.hour, date.hour,
date.min, date.min,
date.sec) date.sec
)
local savepath = utils.join_path(savepath, local savepath = utils.join_path(savepath, datestring .. "_playlist-size_" .. length .. ".m3u")
datestring .. "_playlist-size_" .. length ..
".m3u")
local file, err = io.open(savepath, "w") local file, err = io.open(savepath, "w")
if not file then if not file then
msg.error( msg.error("Error in creating playlist file, check permissions. Error: " .. (err or "unknown"))
"Error in creating playlist file, check permissions. Error: " ..
(err or "unknown"))
else else
local i = 0 local i = 0
while i < length do while i < length do
local pwd = mp.get_property("working-directory") local pwd = mp.get_property("working-directory")
local filename = mp.get_property('playlist/' .. i .. '/filename') local filename = mp.get_property("playlist/" .. i .. "/filename")
local fullpath = filename local fullpath = filename
if not filename:match("^%a%a+:%/%/") then if not filename:match("^%a%a+:%/%/") then
fullpath = utils.join_path(pwd, filename) fullpath = utils.join_path(pwd, filename)
end end
local title = mp.get_property('playlist/' .. i .. '/title') local title = mp.get_property("playlist/" .. i .. "/title")
if title then file:write("#EXTINF:," .. title .. "\n") end if title then
file:write("#EXTINF:," .. title .. "\n")
end
file:write(fullpath, "\n") file:write(fullpath, "\n")
i = i + 1 i = i + 1
end end
@ -757,11 +814,10 @@ end
function alphanumsort(a, b) function alphanumsort(a, b)
local function padnum(d) local function padnum(d)
local dec, n = string.match(d, "(%.?)0*(.+)") local dec, n = string.match(d, "(%.?)0*(.+)")
return #dec > 0 and ("%.12f"):format(d) or return #dec > 0 and ("%.12f"):format(d) or ("%s%03d%s"):format(dec, #n, n)
("%s%03d%s"):format(dec, #n, n)
end end
return tostring(a):lower():gsub("%.?%d+", padnum) .. ("%3d"):format(#b) < return tostring(a):lower():gsub("%.?%d+", padnum) .. ("%3d"):format(#b)
tostring(b):lower():gsub("%.?%d+", padnum) .. ("%3d"):format(#a) < tostring(b):lower():gsub("%.?%d+", padnum) .. ("%3d"):format(#a)
end end
function dosort(a, b) function dosort(a, b)
@ -773,8 +829,10 @@ function dosort(a, b)
end end
function sortplaylist(startover) function sortplaylist(startover)
local length = mp.get_property_number('playlist-count', 0) local length = mp.get_property_number("playlist-count", 0)
if length < 2 then return end if length < 2 then
return
end
-- use insertion sort on playlist to make it easy to order files with playlist-move -- use insertion sort on playlist to make it easy to order files with playlist-move
for outer = 1, length - 1, 1 do for outer = 1, length - 1, 1 do
local outerfile = get_name_from_index(outer, true) local outerfile = get_name_from_index(outer, true)
@ -783,15 +841,23 @@ function sortplaylist(startover)
inner = inner - 1 inner = inner - 1
end end
inner = inner + 1 inner = inner + 1
if outer ~= inner then mp.commandv('playlist-move', outer, inner) end if outer ~= inner then
mp.commandv("playlist-move", outer, inner)
end
end
cursor = mp.get_property_number("playlist-pos", 0)
if startover then
mp.set_property("playlist-pos", 0)
end
if playlist_visible then
showplaylist()
end end
cursor = mp.get_property_number('playlist-pos', 0)
if startover then mp.set_property('playlist-pos', 0) end
if playlist_visible then showplaylist() end
end end
function autosort(name, param) function autosort(name, param)
if param == 0 then return end if param == 0 then
return
end
if plen < param then if plen < param then
msg.info("Playlistmanager autosorting playlist") msg.info("Playlistmanager autosorting playlist")
refresh_globals() refresh_globals()
@ -800,21 +866,31 @@ function autosort(name, param)
end end
function reverseplaylist() function reverseplaylist()
local length = mp.get_property_number('playlist-count', 0) local length = mp.get_property_number("playlist-count", 0)
if length < 2 then return end if length < 2 then
for outer = 1, length - 1, 1 do mp.commandv('playlist-move', outer, 0) end return
if playlist_visible then showplaylist() end end
for outer = 1, length - 1, 1 do
mp.commandv("playlist-move", outer, 0)
end
if playlist_visible then
showplaylist()
end
end end
function shuffleplaylist() function shuffleplaylist()
refresh_globals() refresh_globals()
if plen < 2 then return end if plen < 2 then
return
end
mp.command("playlist-shuffle") mp.command("playlist-shuffle")
math.randomseed(os.time()) math.randomseed(os.time())
mp.commandv("playlist-move", pos, math.random(0, plen - 1)) mp.commandv("playlist-move", pos, math.random(0, plen - 1))
mp.set_property('playlist-pos', 0) mp.set_property("playlist-pos", 0)
refresh_globals() refresh_globals()
if playlist_visible then showplaylist() end if playlist_visible then
showplaylist()
end
end end
function bind_keys(keys, name, func, opts) function bind_keys(keys, name, func, opts)
@ -824,7 +900,7 @@ function bind_keys(keys, name, func, opts)
end end
local i = 1 local i = 1
for key in keys:gmatch("[^%s]+") do for key in keys:gmatch("[^%s]+") do
local prefix = i == 1 and '' or i local prefix = i == 1 and "" or i
mp.add_forced_key_binding(key, name .. prefix, func, opts) mp.add_forced_key_binding(key, name .. prefix, func, opts)
i = i + 1 i = i + 1
end end
@ -837,103 +913,118 @@ function unbind_keys(keys, name)
end end
local i = 1 local i = 1
for key in keys:gmatch("[^%s]+") do for key in keys:gmatch("[^%s]+") do
local prefix = i == 1 and '' or i local prefix = i == 1 and "" or i
mp.remove_key_binding(name .. prefix) mp.remove_key_binding(name .. prefix)
i = i + 1 i = i + 1
end end
end end
function add_keybinds() function add_keybinds()
bind_keys(settings.key_moveup, 'moveup', moveup, "repeatable") bind_keys(settings.key_moveup, "moveup", moveup, "repeatable")
bind_keys(settings.key_movedown, 'movedown', movedown, "repeatable") bind_keys(settings.key_movedown, "movedown", movedown, "repeatable")
bind_keys(settings.key_selectfile, 'selectfile', selectfile) bind_keys(settings.key_selectfile, "selectfile", selectfile)
bind_keys(settings.key_unselectfile, 'unselectfile', unselectfile) bind_keys(settings.key_unselectfile, "unselectfile", unselectfile)
bind_keys(settings.key_playfile, 'playfile', playfile) bind_keys(settings.key_playfile, "playfile", playfile)
bind_keys(settings.key_removefile, 'removefile', removefile, "repeatable") bind_keys(settings.key_removefile, "removefile", removefile, "repeatable")
bind_keys(settings.key_closeplaylist, 'closeplaylist', remove_keybinds) bind_keys(settings.key_closeplaylist, "closeplaylist", remove_keybinds)
end end
function remove_keybinds() function remove_keybinds()
keybindstimer:kill() keybindstimer:kill()
keybindstimer = mp.add_periodic_timer(settings.playlist_display_timeout, keybindstimer = mp.add_periodic_timer(settings.playlist_display_timeout, remove_keybinds)
remove_keybinds)
keybindstimer:kill() keybindstimer:kill()
mp.set_osd_ass(0, 0, "") mp.set_osd_ass(0, 0, "")
playlist_visible = false playlist_visible = false
if settings.dynamic_binds then if settings.dynamic_binds then
unbind_keys(settings.key_moveup, 'moveup') unbind_keys(settings.key_moveup, "moveup")
unbind_keys(settings.key_movedown, 'movedown') unbind_keys(settings.key_movedown, "movedown")
unbind_keys(settings.key_selectfile, 'selectfile') unbind_keys(settings.key_selectfile, "selectfile")
unbind_keys(settings.key_unselectfile, 'unselectfile') unbind_keys(settings.key_unselectfile, "unselectfile")
unbind_keys(settings.key_playfile, 'playfile') unbind_keys(settings.key_playfile, "playfile")
unbind_keys(settings.key_removefile, 'removefile') unbind_keys(settings.key_removefile, "removefile")
unbind_keys(settings.key_closeplaylist, 'closeplaylist') unbind_keys(settings.key_closeplaylist, "closeplaylist")
end end
end end
keybindstimer = mp.add_periodic_timer(settings.playlist_display_timeout, keybindstimer = mp.add_periodic_timer(settings.playlist_display_timeout, remove_keybinds)
remove_keybinds)
keybindstimer:kill() keybindstimer:kill()
if not settings.dynamic_binds then add_keybinds() end if not settings.dynamic_binds then
add_keybinds()
end
if settings.loadfiles_on_start and mp.get_property_number('playlist-count', 0) == if settings.loadfiles_on_start and mp.get_property_number("playlist-count", 0) == 0 then
0 then playlist() end playlist()
end
promised_sort_watch = false promised_sort_watch = false
if settings.sortplaylist_on_file_add then promised_sort_watch = true end if settings.sortplaylist_on_file_add then
promised_sort_watch = true
end
promised_sort = false promised_sort = false
if settings.sortplaylist_on_start then promised_sort = true end if settings.sortplaylist_on_start then
promised_sort = true
end
mp.observe_property('playlist-count', "number", function() mp.observe_property("playlist-count", "number", function()
if playlist_visible then showplaylist() end if playlist_visible then
if settings.prefer_titles == 'none' then return end showplaylist()
end
if settings.prefer_titles == "none" then
return
end
-- resolve titles -- resolve titles
resolve_titles() resolve_titles()
end) end)
-- resolves url titles by calling youtube-dl -- resolves url titles by calling youtube-dl
function resolve_titles() function resolve_titles()
if not settings.resolve_titles then return end if not settings.resolve_titles then
local length = mp.get_property_number('playlist-count', 0) return
if length < 2 then return end end
local length = mp.get_property_number("playlist-count", 0)
if length < 2 then
return
end
local i = 0 local i = 0
-- loop all items in playlist because we can't predict how it has changed -- loop all items in playlist because we can't predict how it has changed
while i < length do while i < length do
local filename = mp.get_property('playlist/' .. i .. '/filename') local filename = mp.get_property("playlist/" .. i .. "/filename")
local title = mp.get_property('playlist/' .. i .. '/title') local title = mp.get_property("playlist/" .. i .. "/title")
if i ~= pos and filename and filename:match('^https?://') and not title and if
not url_table[filename] and not requested_urls[filename] then i ~= pos
and filename
and filename:match("^https?://")
and not title
and not url_table[filename]
and not requested_urls[filename]
then
requested_urls[filename] = true requested_urls[filename] = true
local args = { local args = {
'youtube-dl', '--no-playlist', '--flat-playlist', '-sJ', "youtube-dl",
filename "--no-playlist",
"--flat-playlist",
"-sJ",
filename,
} }
local req = mp.command_native_async( local req = mp.command_native_async({
{
name = "subprocess", name = "subprocess",
args = args, args = args,
playback_only = false, playback_only = false,
capture_stdout = true capture_stdout = true,
}, function(success, res) }, function(success, res)
if res.killed_by_us then if res.killed_by_us then
msg.verbose( msg.verbose("Request to resolve url title " .. filename .. " timed out")
'Request to resolve url title ' .. filename ..
' timed out')
return return
end end
if res.status == 0 then if res.status == 0 then
local json, err = utils.parse_json(res.stdout) local json, err = utils.parse_json(res.stdout)
if not err then if not err then
local is_playlist = local is_playlist = json["_type"] and json["_type"] == "playlist"
json['_type'] and json['_type'] == 'playlist' local title = (is_playlist and "[playlist]: " or "") .. json["title"]
local title = msg.verbose(filename .. " resolved to '" .. title .. "'")
(is_playlist and '[playlist]: ' or '') ..
json['title']
msg.verbose(filename .. " resolved to '" .. title ..
"'")
url_table[filename] = title url_table[filename] = title
refresh_globals() refresh_globals()
if playlist_visible then if playlist_visible then
@ -941,17 +1032,16 @@ function resolve_titles()
end end
return return
else else
msg.error("Failed parsing json, reason: " .. msg.error("Failed parsing json, reason: " .. (err or "unknown"))
(err or "unknown"))
end end
else else
msg.error("Failed to resolve url title " .. filename .. msg.error("Failed to resolve url title " .. filename .. " Error: " .. (res.error or "unknown"))
" Error: " .. (res.error or "unknown"))
end end
end) end)
mp.add_timeout(5, function() mp.abort_async_command(req) end) mp.add_timeout(5, function()
mp.abort_async_command(req)
end)
end end
i = i + 1 i = i + 1
end end
@ -969,31 +1059,31 @@ function handlemessage(msg, value, value2)
end end
end end
if msg == "show" and value == "filename" and strippedname and value2 then if msg == "show" and value == "filename" and strippedname and value2 then
mp.commandv('show-text', strippedname, tonumber(value2) * 1000); mp.commandv("show-text", strippedname, tonumber(value2) * 1000)
return return
end end
if msg == "show" and value == "filename" and strippedname then if msg == "show" and value == "filename" and strippedname then
mp.commandv('show-text', strippedname); mp.commandv("show-text", strippedname)
return return
end end
if msg == "sort" then if msg == "sort" then
sortplaylist(value); sortplaylist(value)
return return
end end
if msg == "shuffle" then if msg == "shuffle" then
shuffleplaylist(); shuffleplaylist()
return return
end end
if msg == "reverse" then if msg == "reverse" then
reverseplaylist(); reverseplaylist()
return return
end end
if msg == "loadfiles" then if msg == "loadfiles" then
playlist(value); playlist(value)
return return
end end
if msg == "save" then if msg == "save" then
save_playlist(); save_playlist()
return return
end end
end end

View file

@ -5,25 +5,31 @@
-- --
-- original from https://codeberg.org/jouni/mpv_sponsorblock_minimal -- original from https://codeberg.org/jouni/mpv_sponsorblock_minimal
-- adapted for local playback skipping and some refactoring by me -- adapted for local playback skipping and some refactoring by me
local mp = require 'mp' local mp = require("mp")
local options = { local options = {
API = "https://sponsor.ajay.app/api/skipSegments", API = "https://sponsor.ajay.app/api/skipSegments",
-- Categories to fetch and skip -- Categories to fetch and skip
categories = '"sponsor","intro","outro","interaction","selfpromo"' categories = '"sponsor","intro","outro","interaction","selfpromo"',
} }
local function getranges() local function getranges()
local args = { local args = {
"curl", "-s", "-d", "videoID=" .. Youtube_id, "-d", "curl",
"categories=[" .. options.categories .. "]", "-G", options.API "-s",
"-d",
"videoID=" .. Youtube_id,
"-d",
"categories=[" .. options.categories .. "]",
"-G",
options.API,
} }
local sponsors = mp.command_native({ local sponsors = mp.command_native({
name = "subprocess", name = "subprocess",
capture_stdout = true, capture_stdout = true,
playback_only = false, playback_only = false,
args = args args = args,
}) })
if string.match(sponsors.stdout, "%[(.-)%]") then if string.match(sponsors.stdout, "%[(.-)%]") then
@ -41,10 +47,9 @@ local function skip_ads(_, pos)
if tonumber(k) <= pos and tonumber(v) > pos then if tonumber(k) <= pos and tonumber(v) > pos then
-- this message may sometimes be wrong -- this message may sometimes be wrong
-- it only seems to be a visual thing though -- it only seems to be a visual thing though
mp.osd_message("[sponsorblock] skipping forward " .. mp.osd_message(
math.floor( "[sponsorblock] skipping forward " .. math.floor(tonumber(v) - mp.get_property("time-pos")) .. "s"
tonumber(v) - mp.get_property("time-pos")) .. )
"s")
-- need to do the +0.01 otherwise mpv will start spamming skip sometimes -- need to do the +0.01 otherwise mpv will start spamming skip sometimes
-- example: https://www.youtube.com/watch?v=4ypMJzeNooo -- example: https://www.youtube.com/watch?v=4ypMJzeNooo
mp.set_property("time-pos", tonumber(v) + 0.01) mp.set_property("time-pos", tonumber(v) + 0.01)
@ -56,17 +61,15 @@ end
local function file_loaded() local function file_loaded()
local video_path = mp.get_property("path") local video_path = mp.get_property("path")
local youtube_id1 = string.match(video_path, local youtube_id1 = string.match(video_path, "https?://youtu%.be/([%w-_]+).*")
"https?://youtu%.be/([%w-_]+).*") local youtube_id2 = string.match(video_path, "https?://w?w?w?%.?youtube%.com/v/([%w-_]+).*")
local youtube_id2 = string.match(video_path,
"https?://w?w?w?%.?youtube%.com/v/([%w-_]+).*")
local youtube_id3 = string.match(video_path, "/watch.*[?&]v=([%w-_]+).*") local youtube_id3 = string.match(video_path, "/watch.*[?&]v=([%w-_]+).*")
local youtube_id4 = string.match(video_path, "/embed/([%w-_]+).*") local youtube_id4 = string.match(video_path, "/embed/([%w-_]+).*")
local localytfile = string.match(video_path, local localytfile = string.match(video_path, "-([%a%d%-_]+)%.[mw][kpe][v4b][m]?$")
"-([%a%d%-_]+)%.[mw][kpe][v4b][m]?$") Youtube_id = youtube_id1 or youtube_id2 or youtube_id3 or youtube_id4 or localytfile
Youtube_id = youtube_id1 or youtube_id2 or youtube_id3 or youtube_id4 or if not Youtube_id or string.len(Youtube_id) < 11 then
localytfile return
if not Youtube_id or string.len(Youtube_id) < 11 then return end end
Youtube_id = string.sub(Youtube_id, 1, 11) Youtube_id = string.sub(Youtube_id, 1, 11)
getranges() getranges()

View file

@ -41,12 +41,12 @@ local options = {
direct_io = false, direct_io = false,
-- Custom path to the mpv executable -- Custom path to the mpv executable
mpv_path = "mpv" mpv_path = "mpv",
} }
local mp = require "mp" local mp = require("mp")
mp.utils = require "mp.utils" mp.utils = require("mp.utils")
mp.options = require "mp.options" mp.options = require("mp.options")
mp.options.read_options(options, "thumbfast") mp.options.read_options(options, "thumbfast")
local properties = {} local properties = {}
@ -54,8 +54,7 @@ local pre_0_30_0 = mp.command_native_async == nil
local pre_0_33_0 = true local pre_0_33_0 = true
function subprocess(args, async, callback) function subprocess(args, async, callback)
callback = callback or function() callback = callback or function() end
end
if not pre_0_30_0 then if not pre_0_30_0 then
if async then if async then
@ -98,13 +97,13 @@ if options.direct_io then
-- cache flags used in run() to avoid bor() call -- cache flags used in run() to avoid bor() call
winapi._createfile_pipe_flags = winapi.bit.bor(winapi.FILE_FLAG_WRITE_THROUGH, winapi.FILE_FLAG_NO_BUFFERING) winapi._createfile_pipe_flags = winapi.bit.bor(winapi.FILE_FLAG_WRITE_THROUGH, winapi.FILE_FLAG_NO_BUFFERING)
ffi.cdef [[ ffi.cdef([[
void* __stdcall CreateFileW(const wchar_t *lpFileName, unsigned long dwDesiredAccess, unsigned long dwShareMode, void *lpSecurityAttributes, unsigned long dwCreationDisposition, unsigned long dwFlagsAndAttributes, void *hTemplateFile); void* __stdcall CreateFileW(const wchar_t *lpFileName, unsigned long dwDesiredAccess, unsigned long dwShareMode, void *lpSecurityAttributes, unsigned long dwCreationDisposition, unsigned long dwFlagsAndAttributes, void *hTemplateFile);
bool __stdcall WriteFile(void *hFile, const void *lpBuffer, unsigned long nNumberOfBytesToWrite, unsigned long *lpNumberOfBytesWritten, void *lpOverlapped); bool __stdcall WriteFile(void *hFile, const void *lpBuffer, unsigned long nNumberOfBytesToWrite, unsigned long *lpNumberOfBytesWritten, void *lpOverlapped);
bool __stdcall CloseHandle(void *hObject); bool __stdcall CloseHandle(void *hObject);
bool __stdcall SetNamedPipeHandleState(void *hNamedPipe, unsigned long *lpMode, unsigned long *lpMaxCollectionCount, unsigned long *lpCollectDataTimeout); bool __stdcall SetNamedPipeHandleState(void *hNamedPipe, unsigned long *lpMode, unsigned long *lpMaxCollectionCount, unsigned long *lpCollectDataTimeout);
int __stdcall MultiByteToWideChar(unsigned int CodePage, unsigned long dwFlags, const char *lpMultiByteStr, int cbMultiByte, wchar_t *lpWideCharStr, int cchWideChar); int __stdcall MultiByteToWideChar(unsigned int CodePage, unsigned long dwFlags, const char *lpMultiByteStr, int cbMultiByte, wchar_t *lpWideCharStr, int cchWideChar);
]] ]])
winapi.MultiByteToWideChar = function(MultiByteStr) winapi.MultiByteToWideChar = function(MultiByteStr)
if MultiByteStr then if MultiByteStr then
@ -163,7 +162,7 @@ local tone_mappings = {
["gamma"] = true, ["gamma"] = true,
["reinhard"] = true, ["reinhard"] = true,
["hable"] = true, ["hable"] = true,
["mobius"] = true ["mobius"] = true,
} }
local last_tone_mapping = nil local last_tone_mapping = nil
@ -222,7 +221,7 @@ local function get_os()
["^cygwin"] = "windows", ["^cygwin"] = "windows",
["bsd$"] = "darwin", ["bsd$"] = "darwin",
["sunos"] = "darwin" ["sunos"] = "darwin",
} }
-- Default to linux -- Default to linux
@ -287,10 +286,12 @@ if mpv_path == "mpv" and os_name == "darwin" and unique then
local mpv_app = mp.utils.file_info("/Applications/mpv.app/Contents/MacOS/mpv") local mpv_app = mp.utils.file_info("/Applications/mpv.app/Contents/MacOS/mpv")
if mpv_app and mpv_app.is_file then if mpv_app and mpv_app.is_file then
mp.msg.warn( mp.msg.warn(
"symlink mpv to fix Dock icons: `sudo ln -s /Applications/mpv.app/Contents/MacOS/mpv /usr/local/mpv`") "symlink mpv to fix Dock icons: `sudo ln -s /Applications/mpv.app/Contents/MacOS/mpv /usr/local/mpv`"
)
else else
mp.msg.warn( mp.msg.warn(
"drag to your Applications folder and symlink mpv to fix Dock icons: `sudo ln -s /Applications/mpv.app/Contents/MacOS/mpv /usr/local/mpv`") "drag to your Applications folder and symlink mpv to fix Dock icons: `sudo ln -s /Applications/mpv.app/Contents/MacOS/mpv /usr/local/mpv`"
)
end end
end end
end end
@ -349,10 +350,17 @@ local function vf_string(filters, full)
end end
if full then if full then
vf = vf .. vf = vf
"scale=w=" .. .. "scale=w="
effective_w .. ":h=" .. effective_h .. par .. .. effective_w
",pad=w=" .. effective_w .. ":h=" .. effective_h .. ":x=-1:y=-1,format=bgra" .. ":h="
.. effective_h
.. par
.. ",pad=w="
.. effective_w
.. ":h="
.. effective_h
.. ":x=-1:y=-1,format=bgra"
end end
return vf return vf
@ -361,7 +369,9 @@ end
local function calc_dimensions() local function calc_dimensions()
local width = properties["video-out-params"] and properties["video-out-params"]["dw"] local width = properties["video-out-params"] and properties["video-out-params"]["dw"]
local height = properties["video-out-params"] and properties["video-out-params"]["dh"] local height = properties["video-out-params"] and properties["video-out-params"]["dh"]
if not width or not height then return end if not width or not height then
return
end
local scale = properties["display-hidpi-scale"] or 1 local scale = properties["display-hidpi-scale"] or 1
@ -385,22 +395,26 @@ local info_timer = nil
local function info(w, h) local function info(w, h)
local rotate = properties["video-params"] and properties["video-params"]["rotate"] local rotate = properties["video-params"] and properties["video-params"]["rotate"]
local image = properties["current-tracks"] and properties["current-tracks"]["video"] and local image = properties["current-tracks"]
properties["current-tracks"]["video"]["image"] and properties["current-tracks"]["video"]
and properties["current-tracks"]["video"]["image"]
local albumart = image and properties["current-tracks"]["video"]["albumart"] local albumart = image and properties["current-tracks"]["video"]["albumart"]
disabled = (w or 0) == 0 or (h or 0) == 0 or disabled = (w or 0) == 0
has_vid == 0 or or (h or 0) == 0
(properties["demuxer-via-network"] and not options.network) or or has_vid == 0
(albumart and not options.audio) or or (properties["demuxer-via-network"] and not options.network)
(image and not albumart) or or (albumart and not options.audio)
force_disabled or (image and not albumart)
or force_disabled
if info_timer then if info_timer then
info_timer:kill() info_timer:kill()
info_timer = nil info_timer = nil
elseif has_vid == 0 or (rotate == nil and not disabled) then elseif has_vid == 0 or (rotate == nil and not disabled) then
info_timer = mp.add_timeout(0.05, function() info(w, h) end) info_timer = mp.add_timeout(0.05, function()
info(w, h)
end)
end end
local json, _ = mp.utils.format_json({ local json, _ = mp.utils.format_json({
@ -410,13 +424,12 @@ local function info(w, h)
available = true, available = true,
socket = options.socket, socket = options.socket,
thumbnail = options.thumbnail, thumbnail = options.thumbnail,
overlay_id = options.overlay_id overlay_id = options.overlay_id,
}) })
if pre_0_30_0 then if pre_0_30_0 then
mp.command_native({ "script-message", "thumbfast-info", json }) mp.command_native({ "script-message", "thumbfast-info", json })
else else
mp.command_native_async({ "script-message", "thumbfast-info", json }, function() mp.command_native_async({ "script-message", "thumbfast-info", json }, function() end)
end)
end end
end end
@ -433,10 +446,14 @@ end
local activity_timer local activity_timer
local function spawn(time) local function spawn(time)
if disabled then return end if disabled then
return
end
local path = properties["path"] local path = properties["path"]
if path == nil then return end if path == nil then
return
end
if options.quit_after_inactivity > 0 then if options.quit_after_inactivity > 0 then
if show_thumbnail or activity_timer:is_enabled() then if show_thumbnail or activity_timer:is_enabled() then
@ -457,19 +474,41 @@ local function spawn(time)
has_vid = vid or 0 has_vid = vid or 0
local args = { local args = {
mpv_path, "--no-config", "--msg-level=all=no", "--idle", "--pause", "--keep-open=always", "--really-quiet", mpv_path,
"--no-config",
"--msg-level=all=no",
"--idle",
"--pause",
"--keep-open=always",
"--really-quiet",
"--no-terminal", "--no-terminal",
"--load-scripts=no", "--osc=no", "--ytdl=no", "--load-stats-overlay=no", "--load-osd-console=no", "--load-scripts=no",
"--osc=no",
"--ytdl=no",
"--load-stats-overlay=no",
"--load-osd-console=no",
"--load-auto-profiles=no", "--load-auto-profiles=no",
"--edition=" .. (properties["edition"] or "auto"), "--vid=" .. (vid or "auto"), "--no-sub", "--no-audio", "--edition=" .. (properties["edition"] or "auto"),
"--start=" .. time, allow_fast_seek and "--hr-seek=no" or "--hr-seek=yes", "--vid=" .. (vid or "auto"),
"--ytdl-format=worst", "--demuxer-readahead-secs=0", "--demuxer-max-bytes=128KiB", "--no-sub",
"--vd-lavc-skiploopfilter=all", "--vd-lavc-software-fallback=1", "--vd-lavc-fast", "--vd-lavc-threads=2", "--no-audio",
"--start=" .. time,
allow_fast_seek and "--hr-seek=no" or "--hr-seek=yes",
"--ytdl-format=worst",
"--demuxer-readahead-secs=0",
"--demuxer-max-bytes=128KiB",
"--vd-lavc-skiploopfilter=all",
"--vd-lavc-software-fallback=1",
"--vd-lavc-fast",
"--vd-lavc-threads=2",
"--hwdec=" .. (options.hwdec and "auto" or "no"), "--hwdec=" .. (options.hwdec and "auto" or "no"),
"--vf=" .. vf_string(filters_all, true), "--vf=" .. vf_string(filters_all, true),
"--sws-scaler=fast-bilinear", "--sws-scaler=fast-bilinear",
"--video-rotate=" .. last_rotate, "--video-rotate=" .. last_rotate,
"--ovc=rawvideo", "--of=image2", "--ofopts=update=1", "--o=" .. options.thumbnail "--ovc=rawvideo",
"--of=image2",
"--ofopts=update=1",
"--o=" .. options.thumbnail,
} }
if not pre_0_30_0 then if not pre_0_30_0 then
@ -506,8 +545,7 @@ local function spawn(time)
spawned = true spawned = true
spawn_waiting = true spawn_waiting = true
subprocess(args, true, subprocess(args, true, function(success, result)
function(success, result)
if spawn_waiting and (success == false or (result.status ~= 0 and result.status ~= -2)) then if spawn_waiting and (success == false or (result.status ~= 0 and result.status ~= -2)) then
spawned = false spawned = false
spawn_waiting = false spawn_waiting = false
@ -525,49 +563,96 @@ local function spawn(time)
info(real_w or effective_w, real_h or effective_h) info(real_w or effective_w, real_h or effective_h)
end end
mp.commandv("show-text", "thumbfast: ERROR! cannot create mpv subprocess", 5000) mp.commandv("show-text", "thumbfast: ERROR! cannot create mpv subprocess", 5000)
mp.commandv("script-message-to", "implay", "show-message", "thumbfast initial setup", mp.commandv(
"Set mpv_path=PATH_TO_ImPlay in thumbfast config:\n" .. "script-message-to",
string.gsub(mp.command_native({ "expand-path", "~~/script-opts/thumbfast.conf" }), "implay",
"[/\\]", path_separator) .. "\nand restart ImPlay") "show-message",
"thumbfast initial setup",
"Set mpv_path=PATH_TO_ImPlay in thumbfast config:\n"
.. string.gsub(
mp.command_native({ "expand-path", "~~/script-opts/thumbfast.conf" }),
"[/\\]",
path_separator
)
.. "\nand restart ImPlay"
)
end end
else else
mp.commandv("show-text", "thumbfast: ERROR! cannot create mpv subprocess", 5000) mp.commandv("show-text", "thumbfast: ERROR! cannot create mpv subprocess", 5000)
if os_name == "windows" then if os_name == "windows" then
mp.commandv("script-message-to", "mpvnet", "show-text", mp.commandv(
"thumbfast: ERROR! install standalone mpv, see README", 5000, 20) "script-message-to",
mp.commandv("script-message", "mpv.net", "show-text", "mpvnet",
"thumbfast: ERROR! install standalone mpv, see README", 5000, 20) "show-text",
"thumbfast: ERROR! install standalone mpv, see README",
5000,
20
)
mp.commandv(
"script-message",
"mpv.net",
"show-text",
"thumbfast: ERROR! install standalone mpv, see README",
5000,
20
)
end end
end end
else else
mp.commandv("show-text", "thumbfast: ERROR! cannot create mpv subprocess", 5000) mp.commandv("show-text", "thumbfast: ERROR! cannot create mpv subprocess", 5000)
-- found ImPlay but not defined in config -- found ImPlay but not defined in config
mp.commandv("script-message-to", "implay", "show-message", "thumbfast", mp.commandv(
"Set mpv_path=PATH_TO_ImPlay in thumbfast config:\n" .. "script-message-to",
string.gsub(mp.command_native({ "expand-path", "~~/script-opts/thumbfast.conf" }), "[/\\]", "implay",
path_separator) .. "\nand restart ImPlay") "show-message",
"thumbfast",
"Set mpv_path=PATH_TO_ImPlay in thumbfast config:\n"
.. string.gsub(
mp.command_native({ "expand-path", "~~/script-opts/thumbfast.conf" }),
"[/\\]",
path_separator
)
.. "\nand restart ImPlay"
)
end end
end end
elseif success == true and (result.status == 0 or result.status == -2) then elseif success == true and (result.status == 0 or result.status == -2) then
if not spawn_working and properties["current-vo"] == "libmpv" and options.mpv_path ~= mpv_path then if not spawn_working and properties["current-vo"] == "libmpv" and options.mpv_path ~= mpv_path then
mp.commandv("script-message-to", "implay", "show-message", "thumbfast initial setup", mp.commandv(
"Set mpv_path=ImPlay in thumbfast config:\n" .. "script-message-to",
string.gsub(mp.command_native({ "expand-path", "~~/script-opts/thumbfast.conf" }), "[/\\]", "implay",
path_separator) .. "\nand restart ImPlay") "show-message",
"thumbfast initial setup",
"Set mpv_path=ImPlay in thumbfast config:\n"
.. string.gsub(
mp.command_native({ "expand-path", "~~/script-opts/thumbfast.conf" }),
"[/\\]",
path_separator
)
.. "\nand restart ImPlay"
)
end end
spawn_working = true spawn_working = true
spawn_waiting = false spawn_waiting = false
end end
end end)
)
end end
local function run(command) local function run(command)
if not spawned then return end if not spawned then
return
end
if options.direct_io then if options.direct_io then
local hPipe = winapi.C.CreateFileW(winapi.socket_wc, winapi.GENERIC_WRITE, 0, nil, winapi.OPEN_EXISTING, local hPipe = winapi.C.CreateFileW(
winapi._createfile_pipe_flags, nil) winapi.socket_wc,
winapi.GENERIC_WRITE,
0,
nil,
winapi.OPEN_EXISTING,
winapi._createfile_pipe_flags,
nil
)
if hPipe ~= winapi.INVALID_HANDLE_VALUE then if hPipe ~= winapi.INVALID_HANDLE_VALUE then
local buf = command .. "\n" local buf = command .. "\n"
winapi.C.SetNamedPipeHandleState(hPipe, winapi.PIPE_NOWAIT, nil, nil) winapi.C.SetNamedPipeHandleState(hPipe, winapi.PIPE_NOWAIT, nil, nil)
@ -603,16 +688,28 @@ local function run(command)
end end
local function draw(w, h, script) local function draw(w, h, script)
if not w or not show_thumbnail then return end if not w or not show_thumbnail then
return
end
if x ~= nil then if x ~= nil then
if pre_0_30_0 then if pre_0_30_0 then
mp.command_native({ "overlay-add", options.overlay_id, x, y, options.thumbnail .. ".bgra", 0, "bgra", w, h, mp.command_native({
(4 * w) }) "overlay-add",
options.overlay_id,
x,
y,
options.thumbnail .. ".bgra",
0,
"bgra",
w,
h,
(4 * w),
})
else else
mp.command_native_async( mp.command_native_async(
{ "overlay-add", options.overlay_id, x, y, options.thumbnail .. ".bgra", 0, "bgra", w, h, (4 * w) }, { "overlay-add", options.overlay_id, x, y, options.thumbnail .. ".bgra", 0, "bgra", w, h, (4 * w) },
function() function() end
end) )
end end
elseif script then elseif script then
local json, _ = mp.utils.format_json({ local json, _ = mp.utils.format_json({
@ -622,7 +719,7 @@ local function draw(w, h, script)
y = y, y = y,
socket = options.socket, socket = options.socket,
thumbnail = options.thumbnail, thumbnail = options.thumbnail,
overlay_id = options.overlay_id overlay_id = options.overlay_id,
}) })
mp.commandv("script-message-to", script, "thumbfast-render", json) mp.commandv("script-message-to", script, "thumbfast-render", json)
end end
@ -648,7 +745,11 @@ local function real_res(req_w, req_h, filesize)
if count % a == 0 then if count % a == 0 then
local b = count / a local b = count / a
if long_side - b < threshold then if long_side - b < threshold then
if req_h < req_w then return b, a else return a, b end if req_h < req_w then
return b, a
else
return a, b
end
end end
end end
end end
@ -708,7 +809,9 @@ local function check_new_thumb()
local tmp = options.thumbnail .. ".tmp" local tmp = options.thumbnail .. ".tmp"
move_file(options.thumbnail, tmp) move_file(options.thumbnail, tmp)
local finfo = mp.utils.file_info(tmp) local finfo = mp.utils.file_info(tmp)
if not finfo then return false end if not finfo then
return false
end
spawn_waiting = false spawn_waiting = false
local w, h = real_res(effective_w, effective_h, finfo.size) local w, h = real_res(effective_w, effective_h, finfo.size)
if w then -- only accept valid thumbnails if w then -- only accept valid thumbnails
@ -748,12 +851,13 @@ local function clear()
show_thumbnail = false show_thumbnail = false
last_x = nil last_x = nil
last_y = nil last_y = nil
if script_name then return end if script_name then
return
end
if pre_0_30_0 then if pre_0_30_0 then
mp.command_native({ "overlay-remove", options.overlay_id }) mp.command_native({ "overlay-remove", options.overlay_id })
else else
mp.command_native_async({ "overlay-remove", options.overlay_id }, function() mp.command_native_async({ "overlay-remove", options.overlay_id }, function() end)
end)
end end
end end
@ -773,10 +877,14 @@ activity_timer = mp.add_timeout(options.quit_after_inactivity, quit)
activity_timer:kill() activity_timer:kill()
local function thumb(time, r_x, r_y, script) local function thumb(time, r_x, r_y, script)
if disabled then return end if disabled then
return
end
time = tonumber(time) time = tonumber(time)
if time == nil then return end if time == nil then
return
end
if r_x == "" or r_y == "" then if r_x == "" or r_y == "" then
x, y = nil, nil x, y = nil, nil
@ -799,15 +907,23 @@ local function thumb(time, r_x, r_y, script)
activity_timer:resume() activity_timer:resume()
end end
if time == last_seek_time then return end if time == last_seek_time then
return
end
last_seek_time = time last_seek_time = time
if not spawned then spawn(time) end if not spawned then
spawn(time)
end
request_seek() request_seek()
if not file_timer:is_enabled() then file_timer:resume() end if not file_timer:is_enabled() then
file_timer:resume()
end
end end
local function watch_changes() local function watch_changes()
if not dirty or not properties["video-out-params"] then return end if not dirty or not properties["video-out-params"] then
return
end
dirty = false dirty = false
local old_w = effective_w local old_w = effective_w
@ -818,11 +934,11 @@ local function watch_changes()
local vf_reset = vf_string(filters_reset) local vf_reset = vf_string(filters_reset)
local rotate = properties["video-rotate"] or 0 local rotate = properties["video-rotate"] or 0
local resized = old_w ~= effective_w or local resized = old_w ~= effective_w
old_h ~= effective_h or or old_h ~= effective_h
last_vf_reset ~= vf_reset or or last_vf_reset ~= vf_reset
(last_rotate % 180) ~= (rotate % 180) or or (last_rotate % 180) ~= (rotate % 180)
par ~= last_par or par ~= last_par
if resized then if resized then
last_rotate = rotate last_rotate = rotate
@ -890,7 +1006,9 @@ end
local function sync_changes(prop, val) local function sync_changes(prop, val)
update_property(prop, val) update_property(prop, val)
if val == nil then return end if val == nil then
return
end
if type(val) == "boolean" then if type(val) == "boolean" then
if prop == "vid" then if prop == "vid" then
@ -907,7 +1025,9 @@ local function sync_changes(prop, val)
has_vid = 1 has_vid = 1
end end
if not spawned then return end if not spawned then
return
end
run("set " .. prop .. " " .. val) run("set " .. prop .. " " .. val)
dirty = true dirty = true

File diff suppressed because it is too large Load diff

View file

@ -11,5 +11,4 @@ iabbrev projcets projects
" Text expansion " Text expansion
iabbrev mo@ marty.oehme@gmail.com iabbrev mo@ marty.oehme@gmail.com
iabbrev mo.me@ <https://martyoeh.me/> iabbrev mome@ <https://martyoeh.me/>
iabbrev mcc@ Copyright 2020 Marty Oehme, all rights reserved.

View file

@ -1,5 +1,5 @@
local ns = vim.api.nvim_create_namespace('gitcommit') local ns = vim.api.nvim_create_namespace("gitcommit")
vim.api.nvim_set_hl(ns, 'ColorColumn', { bg = '#a33a3a', blend = 90 }) vim.api.nvim_set_hl(ns, "ColorColumn", { bg = "#a33a3a", blend = 90 })
vim.api.nvim_win_set_hl_ns(0, ns) vim.api.nvim_win_set_hl_ns(0, ns)
vim.bo.textwidth = 72 vim.bo.textwidth = 72
vim.wo.colorcolumn = '+0' vim.wo.colorcolumn = "+0"

View file

@ -1,7 +1,9 @@
-- Start quarto session -- Start quarto session
local startsession = function(file, args) local startsession = function(file, args)
file = file or "/tmp/jupyter-magma-session.json" file = file or "/tmp/jupyter-magma-session.json"
if args then file = args[0] end if args then
file = args[0]
end
vim.fn.jobstart({ "jupyter", "console", "-f", file }, { vim.fn.jobstart({ "jupyter", "console", "-f", file }, {
on_stdout = function(_) on_stdout = function(_)
vim.cmd("MagmaInit " .. file) vim.cmd("MagmaInit " .. file)
@ -10,81 +12,80 @@ local startsession = function(file, args)
on_exit = function(_) on_exit = function(_)
vim.notify(string.format("jupyter kernel stopped: %s", file), vim.log.levels.INFO) vim.notify(string.format("jupyter kernel stopped: %s", file), vim.log.levels.INFO)
end, end,
stdin = nil stdin = nil,
}) })
end end
vim.api.nvim_create_user_command("JupyterStart", function() startsession() end, vim.api.nvim_create_user_command("JupyterStart", function()
{}) startsession()
end, {})
local map = vim.keymap.set local map = vim.keymap.set
-- filetype mappings -- filetype mappings
-- PLUGIN: magma-nvim -- PLUGIN: magma-nvim
-- Operate jupyter notebooks from within vim -- Operate jupyter notebooks from within vim
map('n', '<localleader>cc', ':MagmaEvaluateLine<cr>', { silent = true }) map("n", "<localleader>cc", ":MagmaEvaluateLine<cr>", { silent = true })
map('n', '<localleader>C', '?^```{<cr>jV/```<cr>k:<C-u>MagmaEvaluateVisual<cr>', map(
{ silent = true, desc = 'Evaluate current code cell' }) "n",
map('x', '<localleader>c', ':<C-u>MagmaEvaluateVisual<cr>', { silent = true }) "<localleader>C",
map('n', '<localleader>c', "nvim_exec('MagmaEvaluateOperator', v:true)", "?^```{<cr>jV/```<cr>k:<C-u>MagmaEvaluateVisual<cr>",
{ expr = true, silent = true, desc = '+code-evaluation' }) { silent = true, desc = "Evaluate current code cell" }
map('n', '<localleader>cr', ':MagmaReevaluateCell<cr>', { silent = true }) )
map('n', '<localleader>cu', ':MagmaShowOutput<cr>', { silent = true }) map("x", "<localleader>c", ":<C-u>MagmaEvaluateVisual<cr>", { silent = true })
map('n', '<localleader>cU', ':noautocmd :MagmaEnterOutput<cr>', map(
{ silent = true, desc = 'MagmaEnterOutput' }) "n",
map('n', '<localleader>cd', ':MagmaDelete<cr>', { silent = true }) "<localleader>c",
map('n', '<localleader>cs', ':MagmaInterrupt<cr>') "nvim_exec('MagmaEvaluateOperator', v:true)",
map('n', '<localleader>ci', ':MagmaInit ') { expr = true, silent = true, desc = "+code-evaluation" }
map('n', '<localleader>cD', ':MagmaDeinit<cr>') )
map('n', '<localleader>cR', ':MagmaRestart<cr>') map("n", "<localleader>cr", ":MagmaReevaluateCell<cr>", { silent = true })
map("n", "<localleader>cu", ":MagmaShowOutput<cr>", { silent = true })
map("n", "<localleader>cU", ":noautocmd :MagmaEnterOutput<cr>", { silent = true, desc = "MagmaEnterOutput" })
map("n", "<localleader>cd", ":MagmaDelete<cr>", { silent = true })
map("n", "<localleader>cs", ":MagmaInterrupt<cr>")
map("n", "<localleader>ci", ":MagmaInit ")
map("n", "<localleader>cD", ":MagmaDeinit<cr>")
map("n", "<localleader>cR", ":MagmaRestart<cr>")
-- jump to beginning of previous/ next cell code -- jump to beginning of previous/ next cell code
map('n', ']c', '/^```{<cr>}:nohl<cr>', { desc = 'Next quarto cell' }) map("n", "]c", "/^```{<cr>}:nohl<cr>", { desc = "Next quarto cell" })
map('n', '[c', '?^```<cr>n}:nohl<cr>', { desc = 'Previous quarto cell' }) map("n", "[c", "?^```<cr>n}:nohl<cr>", { desc = "Previous quarto cell" })
-- insert cell header above/below -- insert cell header above/below
map('n', '<localleader>co', 'o```{python}<cr><cr>```<esc>k', map("n", "<localleader>co", "o```{python}<cr><cr>```<esc>k", { desc = "Insert quarto cell below" })
{ desc = 'Insert quarto cell below' }) map("n", "<localleader>cO", "O```{python}<cr><cr>```<esc>k", { desc = "Insert quarto cell above" })
map('n', '<localleader>cO', 'O```{python}<cr><cr>```<esc>k',
{ desc = 'Insert quarto cell above' })
local bufnr = 0 local bufnr = 0
map('n', '[d', '<cmd>lua vim.diagnostic.goto_prev()<cr>', map("n", "[d", "<cmd>lua vim.diagnostic.goto_prev()<cr>", { buffer = bufnr, desc = "Previous diagnostic" })
{ buffer = bufnr, desc = 'Previous diagnostic' }) map("n", "]d", "<cmd>lua vim.diagnostic.goto_next()<cr>", { buffer = bufnr, desc = "Next diagnostic" })
map('n', ']d', '<cmd>lua vim.diagnostic.goto_next()<cr>', map(
{ buffer = bufnr, desc = 'Next diagnostic' }) "n",
map('n', '[e', "[e",
'<cmd>lua vim.diagnostic.goto_prev({severity = vim.diagnostic.severity.ERROR})<cr>', "<cmd>lua vim.diagnostic.goto_prev({severity = vim.diagnostic.severity.ERROR})<cr>",
{ buffer = bufnr, desc = 'Previous error' }) { buffer = bufnr, desc = "Previous error" }
map('n', ']e', )
'<cmd>lua vim.diagnostic.goto_next({severity = vim.diagnostic.severity.ERROR})<cr>', map(
{ buffer = bufnr, desc = 'Next error' }) "n",
"]e",
"<cmd>lua vim.diagnostic.goto_next({severity = vim.diagnostic.severity.ERROR})<cr>",
{ buffer = bufnr, desc = "Next error" }
)
-- TODO find better way to enable lsp key mappings for quarto buffers -- TODO find better way to enable lsp key mappings for quarto buffers
local prefix = require('which-key').register local prefix = require("which-key").register
prefix({ ['<localleader>l'] = { name = "+lsp" } }) prefix({ ["<localleader>l"] = { name = "+lsp" } })
map('n', '<localleader>li', '<cmd>LspInfo<cr>', map("n", "<localleader>li", "<cmd>LspInfo<cr>", { buffer = bufnr, desc = "Lsp Info" })
{ buffer = bufnr, desc = 'Lsp Info' }) map("n", "<localleader>ld", "<cmd>lua vim.diagnostic.open_float()<cr>", { buffer = bufnr, desc = "Line diagnostics" })
map('n', '<localleader>ld', '<cmd>lua vim.diagnostic.open_float()<cr>', map("n", "<localleader>la", "<cmd>lua vim.lsp.buf.code_action()<cr>", { buffer = bufnr, desc = "Codeactions" })
{ buffer = bufnr, desc = 'Line diagnostics' }) map("n", "<localleader>ln", "<cmd>lua vim.lsp.buf.rename()<cr>", { buffer = bufnr, desc = "Rename element" })
map('n', '<localleader>la', '<cmd>lua vim.lsp.buf.code_action()<cr>', map("n", "<localleader>lr", "<cmd>lua vim.lsp.buf.references()<cr>", { buffer = bufnr, desc = "References" })
{ buffer = bufnr, desc = 'Codeactions' })
map('n', '<localleader>ln', '<cmd>lua vim.lsp.buf.rename()<cr>',
{ buffer = bufnr, desc = 'Rename element' })
map('n', '<localleader>lr', '<cmd>lua vim.lsp.buf.references()<cr>',
{ buffer = bufnr, desc = 'References' })
map('n', 'K', '<cmd>lua vim.lsp.buf.hover()<cr>', map("n", "K", "<cmd>lua vim.lsp.buf.hover()<cr>", { buffer = bufnr, desc = "Hover definition" })
{ buffer = bufnr, desc = 'Hover definition' }) map("n", "gd", "<cmd>lua vim.lsp.buf.definition()<cr>", { buffer = bufnr, desc = "Definition" })
map('n', 'gd', '<cmd>lua vim.lsp.buf.definition()<cr>', map("n", "gD", "<cmd>lua vim.lsp.buf.declaration()<cr>", { buffer = bufnr, desc = "Declaration" })
{ buffer = bufnr, desc = 'Definition' }) map("n", "gs", "<cmd>lua vim.lsp.buf.signature_help()<cr>", { buffer = bufnr, desc = "Signature help" })
map('n', 'gD', '<cmd>lua vim.lsp.buf.declaration()<cr>', map("n", "gI", "<cmd>lua vim.lsp.buf.implementation()<cr>", { buffer = bufnr, desc = "Implementation" })
{ buffer = bufnr, desc = 'Declaration' }) map("n", "gt", "<cmd>lua vim.lsp.buf.type_definition()<cr>", { buffer = bufnr, desc = "Type definition" })
map('n', 'gs', '<cmd>lua vim.lsp.buf.signature_help()<cr>',
{ buffer = bufnr, desc = 'Signature help' })
map('n', 'gI', '<cmd>lua vim.lsp.buf.implementation()<cr>',
{ buffer = bufnr, desc = 'Implementation' })
map('n', 'gt', '<cmd>lua vim.lsp.buf.type_definition()<cr>',
{ buffer = bufnr, desc = 'Type definition' })
if vim.b['sessionfile'] == nil then if vim.b["sessionfile"] == nil then
vim.b['sessionfile'] = vim.fn.tempname() .. '.json' vim.b["sessionfile"] = vim.fn.tempname() .. ".json"
startsession(vim.b['sessionfile']) startsession(vim.b["sessionfile"])
end end

View file

@ -2,14 +2,17 @@
-- https://github.com/elianiva/dotfiles/ - with much gratitude -- https://github.com/elianiva/dotfiles/ - with much gratitude
local api = vim.api local api = vim.api
api.nvim_exec('runtime abbrev.vim', false) api.nvim_exec2("runtime abbrev.vim", {})
local lazypath = vim.fn.stdpath("data") .. "/lazy/lazy.nvim" local lazypath = vim.fn.stdpath("data") .. "/lazy/lazy.nvim"
if not vim.loop.fs_stat(lazypath) then if not vim.loop.fs_stat(lazypath) then
vim.fn.system({ vim.fn.system({
"git", "clone", "--filter=blob:none", "git",
"https://github.com/folke/lazy.nvim.git", "--branch=stable", -- latest stable release "clone",
lazypath "--filter=blob:none",
"https://github.com/folke/lazy.nvim.git",
"--branch=stable", -- latest stable release
lazypath,
}) })
end end
vim.opt.rtp:prepend(lazypath) vim.opt.rtp:prepend(lazypath)
@ -18,14 +21,14 @@ vim.opt.rtp:prepend(lazypath)
-- needs to be set before lazy.nvim is loaded -- needs to be set before lazy.nvim is loaded
vim.g.mapleader = " " vim.g.mapleader = " "
require('settings') require("settings")
require('autocmds') require("autocmds")
require("lazy").setup("plugins", { require("lazy").setup("plugins", {
defaults = { version = "*" }, defaults = { version = "*" },
performance = { rtp = { disabled_plugins = { "netrw", "netrwPlugin" } } } performance = { rtp = { disabled_plugins = { "netrw", "netrwPlugin" } } },
}) })
require('look') require("look")
require('maps') require("maps")
-- to include e.g. the spell dictionaries for vim -- to include e.g. the spell dictionaries for vim
vim.opt.rtp:append(vim.fn.stdpath("data") .. "/site") vim.opt.rtp:append(vim.fn.stdpath("data") .. "/site")

View file

@ -2,32 +2,36 @@
vim.api.nvim_create_autocmd({ "TextYankPost" }, { vim.api.nvim_create_autocmd({ "TextYankPost" }, {
command = 'silent! lua require"vim.highlight".on_yank{timeout=500}', command = 'silent! lua require"vim.highlight".on_yank{timeout=500}',
desc = "Highlight yanked text whenevery yanking something", desc = "Highlight yanked text whenevery yanking something",
group = vim.api.nvim_create_augroup('highlightyanks', { clear = true }) group = vim.api.nvim_create_augroup("highlightyanks", { clear = true }),
}) })
-- Special setting for editing gopass files - make sure nothing leaks outside the directories it is supposed to -- Special setting for editing gopass files - make sure nothing leaks outside the directories it is supposed to
vim.api.nvim_create_autocmd({ "BufNewFile", "BufRead" }, { vim.api.nvim_create_autocmd({ "BufNewFile", "BufRead" }, {
pattern = { pattern = {
"/dev/shm/gopass.*", "/dev/shm/pass.?*/?*.txt", "/dev/shm/gopass.*",
"$TMPDIR/pass.?*/?*.txt", "/tmp/pass.?*/?*.txt" "/dev/shm/pass.?*/?*.txt",
"$TMPDIR/pass.?*/?*.txt",
"/tmp/pass.?*/?*.txt",
}, },
command = 'setlocal noswapfile nobackup noundofile nowritebackup viminfo=', command = "setlocal noswapfile nobackup noundofile nowritebackup viminfo=",
desc = "Don't leak any information when editing potential password files", desc = "Don't leak any information when editing potential password files",
group = vim.api.nvim_create_augroup('passnoleak', { clear = true }) group = vim.api.nvim_create_augroup("passnoleak", { clear = true }),
}) })
-- fixing neovim opening up at same moment as alacritty (see https://github.com/neovim/neovim/issues/11330) -- fixing neovim opening up at same moment as alacritty (see https://github.com/neovim/neovim/issues/11330)
vim.api.nvim_create_autocmd({ "VimEnter" }, { vim.api.nvim_create_autocmd({ "VimEnter" }, {
callback = function() callback = function()
local pid, WINCH = vim.fn.getpid(), vim.loop.constants.SIGWINCH local pid, WINCH = vim.fn.getpid(), vim.loop.constants.SIGWINCH
vim.defer_fn(function() vim.loop.kill(pid, WINCH) end, 20) vim.defer_fn(function()
vim.loop.kill(pid, WINCH)
end, 20)
end, end,
desc = "Fix neovim sizing issues if opening same time as alacritty", desc = "Fix neovim sizing issues if opening same time as alacritty",
group = vim.api.nvim_create_augroup('alacritty_fixsize', { clear = true }) group = vim.api.nvim_create_augroup("alacritty_fixsize", { clear = true }),
}) })
-- remove line numbers from terminal buffers -- remove line numbers from terminal buffers
vim.api.nvim_create_autocmd({ "TermOpen" }, { vim.api.nvim_create_autocmd({ "TermOpen" }, {
pattern = '*', pattern = "*",
command = 'setlocal nonumber norelativenumber' command = "setlocal nonumber norelativenumber",
}) })

View file

@ -1,4 +1,4 @@
local colorsfile = vim.fn.stdpath('state') .. '/colorscheme.lua' local colorsfile = vim.fn.stdpath("state") .. "/colorscheme.lua"
local function source_colors() local function source_colors()
if vim.fn.filereadable(colorsfile) == 1 then if vim.fn.filereadable(colorsfile) == 1 then
vim.cmd("source " .. colorsfile) vim.cmd("source " .. colorsfile)
@ -9,7 +9,9 @@ end
source_colors() source_colors()
-- continuously watch colors file for changes -- continuously watch colors file for changes
local fwatch = require('fwatch') local fwatch = require("fwatch")
fwatch.watch(colorsfile, { fwatch.watch(colorsfile, {
on_event = vim.schedule_wrap(function() source_colors() end) on_event = vim.schedule_wrap(function()
source_colors()
end),
}) })

View file

@ -1,5 +1,5 @@
local map = vim.keymap.set local map = vim.keymap.set
local prefix = require('which-key').register local prefix = require("which-key").register
-- The general ideas behind these mappings: -- The general ideas behind these mappings:
-- --
@ -10,46 +10,50 @@ local prefix = require('which-key').register
-- In other words mostly filetype specific mappings -- In other words mostly filetype specific mappings
-- backspace to switch to alternate (last) buffer -- backspace to switch to alternate (last) buffer
map('n', '<BS>', '<C-^>') map("n", "<BS>", "<C-^>")
-- since u undoes, would it not make sense that U redoes? -- since u undoes, would it not make sense that U redoes?
map('n', 'U', '<C-r>') map("n", "U", "<C-r>")
-- d-motion puts the last 'deleted' thing into the default register to paste; -- d-motion puts the last 'deleted' thing into the default register to paste;
-- use D-motion to truly delete something into nothingness and keep whatever -- use D-motion to truly delete something into nothingness and keep whatever
-- you want in your register, ready to paste -- you want in your register, ready to paste
map('n', 'D', '"_d') map("n", "D", '"_d')
-- I don't particularly need ex mode (at least, yet) but faster macro access is nice -- I don't particularly need ex mode (at least, yet) but faster macro access is nice
map('n', 'Q', '@') map("n", "Q", "@")
-- stronger versions of left,right - move all the way to beginning/end of line -- stronger versions of left,right - move all the way to beginning/end of line
map('n', 'H', '^') map("n", "H", "^")
map('n', 'L', '$') map("n", "L", "$")
-- when in softwrapped files, allow moving through the visible lines with j/k -- when in softwrapped files, allow moving through the visible lines with j/k
-- but when prepending a number jump *exactly* as many lines, wrapped or not -- but when prepending a number jump *exactly* as many lines, wrapped or not
-- This makes relative linenumbers much more useful in prose docs since they -- This makes relative linenumbers much more useful in prose docs since they
-- are always exactly correct -- are always exactly correct
local function wrap_up() local function wrap_up()
if vim.v.count == 0 then return 'gk' end if vim.v.count == 0 then
return 'k' return "gk"
end
return "k"
end end
local function wrap_down() local function wrap_down()
if vim.v.count == 0 then return 'gj' end if vim.v.count == 0 then
return 'j' return "gj"
end
return "j"
end end
map('n', 'k', wrap_up, { expr = true }) map("n", "k", wrap_up, { expr = true })
map('n', 'j', wrap_down, { expr = true }) map("n", "j", wrap_down, { expr = true })
-- move around between matching brackets with tab -- move around between matching brackets with tab
map('n', '<Tab>', '%') map("n", "<Tab>", "%")
-- when in insertion mode, C-u uppercases the current word, C-l lowercases it, -- when in insertion mode, C-u uppercases the current word, C-l lowercases it,
map('i', '<C-u>', '<esc>gUiw`]a') map("i", "<C-u>", "<esc>gUiw`]a")
map('i', '<C-y>', '<esc>guiw`]a') map("i", "<C-y>", "<esc>guiw`]a")
-- Add undo break-points at punctuations for plaintext editing -- Add undo break-points at punctuations for plaintext editing
for _, char in pairs({ ",", ".", ";", "?", "!" }) do for _, char in pairs({ ",", ".", ";", "?", "!" }) do
@ -57,26 +61,26 @@ for _, char in pairs({ ",", ".", ";", "?", "!" }) do
end end
-- yank current filename/filepath to f buffer -- yank current filename/filepath to f buffer
map('n', 'yp', ':let @p = expand("%")<Cr>', { desc = 'yank filename' }) map("n", "yp", ':let @p = expand("%")<Cr>', { desc = "yank filename" })
map('n', 'yP', ':let @p = expand("%:p")<Cr>', { desc = 'yank filepath' }) map("n", "yP", ':let @p = expand("%:p")<Cr>', { desc = "yank filepath" })
-- repeat the last substitute command with all its flags preserved -- repeat the last substitute command with all its flags preserved
map('n', '&', ':&&<cr>') map("n", "&", ":&&<cr>")
-- bracket pairings to go to the next/previous of: -- bracket pairings to go to the next/previous of:
-- (works with count prefixes) -- (works with count prefixes)
-- Argument list -- Argument list
map('n', '[a', ':previous<cr>') map("n", "[a", ":previous<cr>")
map('n', ']a', ':next<cr>') map("n", "]a", ":next<cr>")
-- Buffers -- Buffers
map('n', '[b', ':bprevious<cr>') map("n", "[b", ":bprevious<cr>")
map('n', ']b', ':bnext<cr>') map("n", "]b", ":bnext<cr>")
-- Quickfix list -- Quickfix list
map('n', '[q', ':cprevious<cr>') map("n", "[q", ":cprevious<cr>")
map('n', ']q', ':cnext<cr>') map("n", "]q", ":cnext<cr>")
-- Location list -- Location list
map('n', '[l', ':lprevious<cr>') map("n", "[l", ":lprevious<cr>")
map('n', ']l', ':lnext<cr>') map("n", "]l", ":lnext<cr>")
-- maps the leader for buffer local mappings -- maps the leader for buffer local mappings
-- since we are (atm) using sneak to go fwd/bwd in fFtT searches, comma does -- since we are (atm) using sneak to go fwd/bwd in fFtT searches, comma does
@ -86,198 +90,193 @@ vim.g.maplocalleader = ","
-- If we mapped localleader to comma, we can still get to its original function -- If we mapped localleader to comma, we can still get to its original function
-- by douple-tapping it. -- by douple-tapping it.
-- FIXME does this work still (and is it necessary)? -- FIXME does this work still (and is it necessary)?
if vim.g.maplocalleader == ',' then if vim.g.maplocalleader == "," then
map('', ',,', ',') map("", ",,", ",")
vim.keymap.del('', ',,', { silent = true }) vim.keymap.del("", ",,", { silent = true })
end end
-- remove search highlights by pressing space+/ -- remove search highlights by pressing space+/
map('n', '<leader>/', ':noh<cr>', { desc = 'remove highlights' }) map("n", "<leader>/", ":noh<cr>", { desc = "remove highlights" })
-- split buffers vertically/horizontally with the leader \ or - (mirrors my -- split buffers vertically/horizontally with the leader \ or - (mirrors my
-- tmux setup) -- tmux setup)
map('n', '<leader>-', ':sp<cr>', { desc = 'open horiz split' }) map("n", "<leader>-", ":sp<cr>", { desc = "open horiz split" })
map('n', '<leader>\\', ':vsp<cr>', { desc = 'open vert split' }) map("n", "<leader>\\", ":vsp<cr>", { desc = "open vert split" })
-- 'open new buffer' with leader-t (opens new buffer containing current dir and switches to it) -- 'open new buffer' with leader-t (opens new buffer containing current dir and switches to it)
map('n', '<leader>t', ':vsp | Vifm<cr>', { desc = 'open buffer' }) map("n", "<leader>t", ":vsp | Vifm<cr>", { desc = "open buffer" })
-- open actual new tab with leader-T -- open actual new tab with leader-T
map('n', '<leader>T', ':tabedit | Vifm<cr>', { desc = 'open tab' }) map("n", "<leader>T", ":tabedit | Vifm<cr>", { desc = "open tab" })
-- select the whole buffer with <leader>-a -- select the whole buffer with <leader>-a
map('n', '<leader>a', 'ggVG', { desc = 'select all' }) map("n", "<leader>a", "ggVG", { desc = "select all" })
-- PLUGIN: Navigator.nvim -- PLUGIN: Navigator.nvim
map('n', '<c-w>h', '<CMD>lua require("Navigator").left()<cr>', { silent = true }) map("n", "<c-w>h", '<CMD>lua require("Navigator").left()<cr>', { silent = true })
map('n', '<c-w>k', '<CMD>lua require("Navigator").up()<cr>', { silent = true }) map("n", "<c-w>k", '<CMD>lua require("Navigator").up()<cr>', { silent = true })
map('n', '<c-w>l', '<CMD>lua require("Navigator").right()<cr>', { silent = true }) map("n", "<c-w>l", '<CMD>lua require("Navigator").right()<cr>', { silent = true })
map('n', '<c-w>j', '<CMD>lua require("Navigator").down()<cr>', { silent = true }) map("n", "<c-w>j", '<CMD>lua require("Navigator").down()<cr>', { silent = true })
map('n', '<c-w>p', '<CMD>lua require("Navigator").previous()<cr>', map("n", "<c-w>p", '<CMD>lua require("Navigator").previous()<cr>', { silent = true })
{ silent = true })
-- PLUGIN: Vifm.vim -- PLUGIN: Vifm.vim
-- open/close file tree with leader-e -- open/close file tree with leader-e
map('n', '<leader>e', ':Vifm<cr>', { desc = 'browse files' }) map("n", "<leader>e", ":Vifm<cr>", { desc = "browse files" })
-- open current file tree with current file directory -- open current file tree with current file directory
map('n', '<leader>E', ':Vifm getcwd()<cr>', { desc = 'browse project' }) map("n", "<leader>E", ":Vifm getcwd()<cr>", { desc = "browse project" })
-- set 'v'im-related options -- set 'v'im-related options
prefix({ ['<leader>v'] = { name = "+vim" } }) prefix({ ["<leader>v"] = { name = "+vim" } })
map('n', '<leader>vc', ':Vifm ' .. vim.fn.stdpath('config') .. '/lua<cr>', map("n", "<leader>vc", ":Vifm " .. vim.fn.stdpath("config") .. "/lua<cr>", { desc = "open config" })
{ desc = 'open config' }) map("n", "<leader>vh", ":lua require 'telescope.builtin'.help_tags()<cr>", { desc = "help tags" })
map('n', '<leader>vh', ":lua require 'telescope.builtin'.help_tags()<cr>", map("n", "<leader>vH", ":lua require 'telescope.builtin'.man_pages()<cr>", { desc = "man pages" })
{ desc = 'help tags' }) map(
map('n', '<leader>vH', ":lua require 'telescope.builtin'.man_pages()<cr>", "n",
{ desc = 'man pages' }) "<leader>vC",
map('n', '<leader>vC',
":lua require 'telescope.builtin'.colorscheme(require 'telescope.themes'.get_ivy())<cr>", ":lua require 'telescope.builtin'.colorscheme(require 'telescope.themes'.get_ivy())<cr>",
{ desc = 'colorschemes' }) { desc = "colorschemes" }
map('n', '<leader>vl', ":Lazy<cr>", { desc = 'Lazy' }) )
map('n', '<leader>vm', ":Mason<cr>", { desc = 'Mason' }) map("n", "<leader>vl", ":Lazy<cr>", { desc = "Lazy" })
map("n", "<leader>vm", ":Mason<cr>", { desc = "Mason" })
-- Set vim to distraction free prose mode with F11 -- Set vim to distraction free prose mode with F11
map('n', '<leader>vz', ':ZenMode<cr>', { silent = true }) map("n", "<leader>vz", ":ZenMode<cr>", { silent = true })
-- PLUGIN: Telescope GLOBAL FUZZY FINDING -- PLUGIN: Telescope GLOBAL FUZZY FINDING
-- buffers and files in current workdir -- buffers and files in current workdir
prefix({ ['<leader>f'] = { name = '+find' } }) prefix({ ["<leader>f"] = { name = "+find" } })
map('n', '<leader>fb', map(
"n",
"<leader>fb",
":lua require 'telescope.builtin'.buffers(require 'telescope.themes'.get_ivy())<cr>", ":lua require 'telescope.builtin'.buffers(require 'telescope.themes'.get_ivy())<cr>",
{ desc = 'list buffers' }) { desc = "list buffers" }
)
-- most recently used / MRU, bound to S since it is essentially a larger -- most recently used / MRU, bound to S since it is essentially a larger
-- go-back intention than just buffers -- go-back intention than just buffers
map('n', '<leader>fo', map(
"n",
"<leader>fo",
":lua require 'telescope.builtin'.oldfiles(require 'telescope.themes'.get_ivy())<cr>", ":lua require 'telescope.builtin'.oldfiles(require 'telescope.themes'.get_ivy())<cr>",
{ desc = 'list old files' }) { desc = "list old files" }
)
-- fuzzy find files in cwd -- fuzzy find files in cwd
map('n', '<leader>ff', ":lua require 'telescope.builtin'.find_files()<cr>", map("n", "<leader>ff", ":lua require 'telescope.builtin'.find_files()<cr>", { desc = "find files" })
{ desc = 'find files' })
-- fuzzy find hidden files in cwd -- fuzzy find hidden files in cwd
map('n', '<leader>fh', map("n", "<leader>fh", ":lua require 'telescope.builtin'.find_files({hidden=true})<cr>", { desc = "find hidden files" })
":lua require 'telescope.builtin'.find_files({hidden=true})<cr>",
{ desc = 'find hidden files' })
-- general full-text search in cwd with rg -- general full-text search in cwd with rg
map('n', '<leader>fw', ":lua require 'telescope.builtin'.live_grep()<cr>", map("n", "<leader>fw", ":lua require 'telescope.builtin'.live_grep()<cr>", { desc = "grep search" })
{ desc = 'grep search' })
-- git status -- git status
map('n', '<leader>fg', ":lua require 'telescope.builtin'.git_status()<cr>", map("n", "<leader>fg", ":lua require 'telescope.builtin'.git_status()<cr>", { desc = "git status" })
{ desc = 'git status' })
-- git buffercommits -- git buffercommits
map('n', '<leader>fc', ":lua require 'telescope.builtin'.git_bcommits()<cr>", map("n", "<leader>fc", ":lua require 'telescope.builtin'.git_bcommits()<cr>", { desc = "git buffer commits" })
{ desc = 'git buffer commits' })
-- git commitlog -- git commitlog
map('n', '<leader>fl', ":lua require 'telescope.builtin'.git_commits()<cr>", map("n", "<leader>fl", ":lua require 'telescope.builtin'.git_commits()<cr>", { desc = "git commit log" })
{ desc = 'git commit log' })
-- spell suggestions -- spell suggestions
map('n', 'z=', map("n", "z=", ":lua require 'telescope.builtin'.spell_suggest(require 'telescope.themes'.get_ivy())<cr>")
":lua require 'telescope.builtin'.spell_suggest(require 'telescope.themes'.get_ivy())<cr>")
-- Format current Paragraph (esp useful in prose writing) -- Format current Paragraph (esp useful in prose writing)
map('n', '<localleader>q', 'gqap', map("n", "<localleader>q", "gqap", { silent = true, desc = "Format current paragraph" })
{ silent = true, desc = 'Format current paragraph' }) map("x", "<localleader>q", "gq", { silent = true, desc = "Format {motion}" })
map('x', '<localleader>q', 'gq', { silent = true, desc = 'Format {motion}' }) map("n", "<localleader>Q", "vapJgqap", { silent = true, desc = "Unformat then format paragraph" })
map('n', '<localleader>Q', 'vapJgqap',
{ silent = true, desc = 'Unformat then format paragraph' })
map('n', '<localleader>mp', '<Plug>MarkdownPreviewToggle', map("n", "<localleader>mp", "<Plug>MarkdownPreviewToggle", { desc = "Toggle md preview" })
{ desc = 'Toggle md preview' })
-- FORMAT code with -- FORMAT code with
-- PLUGIN: formatter.nvim -- PLUGIN: formatter.nvim
map('n', '<localleader>f', ':FormatLock<cr>') map("n", "<localleader>f", ":FormatLock<cr>")
map('n', '<localleader>F', ':FormatWriteLock<cr>') map("n", "<localleader>F", ":FormatWriteLock<cr>")
-- SPELL CHECKING -- SPELL CHECKING
-- Move to the prev/next spelling error with [S ]S -- Move to the prev/next spelling error with [S ]S
-- Move to the prev/next spelling error or suggestion with [s ]s -- Move to the prev/next spelling error or suggestion with [s ]s
prefix({ ['<localleader>Z'] = { name = '+Spelling' } }) prefix({ ["<localleader>Z"] = { name = "+Spelling" } })
map('n', '<localleader>ZZ', ':setlocal spell! spelllang=en_us,de_de<cr>', map("n", "<localleader>ZZ", ":setlocal spell! spelllang=en_us,de_de<cr>", { desc = "Toggle spellcheck" })
{ desc = 'Toggle spellcheck' }) map("n", "<localleader>ZE", ":setlocal spell! spelllang=en_us<cr>", { desc = "Toggle EN spellcheck" })
map('n', '<localleader>ZE', ':setlocal spell! spelllang=en_us<cr>', map("n", "<localleader>ZG", ":setlocal spell! spelllang=de_de<cr>", { desc = "Toggle DE spellcheck" })
{ desc = 'Toggle EN spellcheck' })
map('n', '<localleader>ZG', ':setlocal spell! spelllang=de_de<cr>',
{ desc = 'Toggle DE spellcheck' })
-- undo last spelling mistake from insert and normal mode -- undo last spelling mistake from insert and normal mode
map('i', '<c-z>', '<C-G>u<Esc>[s1z=`]a<C-G>u') map("i", "<c-z>", "<C-G>u<Esc>[s1z=`]a<C-G>u")
map('n', '<localleader>z', 'ms[s1z=`s', { desc = 'Fix last spell error' }) map("n", "<localleader>z", "ms[s1z=`s", { desc = "Fix last spell error" })
-- PLUGIN: mini.nvim -- PLUGIN: mini.nvim
prefix({ ['<leader>s'] = { name = '+show' } }) prefix({ ["<leader>s"] = { name = "+show" } })
map('n', '<leader>sm', ':lua MiniMap.toggle()<cr>', map("n", "<leader>sm", ":lua MiniMap.toggle()<cr>", { silent = true, desc = "toggle minimap" })
{ silent = true, desc = 'toggle minimap' }) map("n", "<leader>ss", ":lua MiniStarter.open()<cr>", { desc = "show startpage" })
map('n', '<leader>ss', ":lua MiniStarter.open()<cr>", { desc = 'show startpage' })
-- PLUGIN: symbols-outline.nvim -- PLUGIN: symbols-outline.nvim
map('n', '<leader>so', '<cmd>SymbolsOutline<cr>', map("n", "<leader>so", "<cmd>SymbolsOutline<cr>", { silent = true, desc = "toggle symbol outline" })
{ silent = true, desc = 'toggle symbol outline' })
-- PLUGIN: nvim-tree -- PLUGIN: nvim-tree
map('n', '<leader>se', '<cmd>NvimTreeToggle<cr>', map("n", "<leader>se", "<cmd>NvimTreeToggle<cr>", { silent = true, desc = "toggle filetree" })
{ silent = true, desc = 'toggle filetree' })
-- PLUGIN: easy-align -- PLUGIN: easy-align
-- Start interactive EasyAlign in visual mode (e.g. vipga) -- Start interactive EasyAlign in visual mode (e.g. vipga)
map('x', 'ga', '<Plug>(EasyAlign)') map("x", "ga", "<Plug>(EasyAlign)")
-- Start interactive EasyAlign for a motion/text object (e.g. gaip) -- Start interactive EasyAlign for a motion/text object (e.g. gaip)
map('n', 'ga', '<Plug>(EasyAlign)') map("n", "ga", "<Plug>(EasyAlign)")
-- trim trailing whitespaces with mini.nvim trailspace -- trim trailing whitespaces with mini.nvim trailspace
map("n", "<localleader>w", function() require("mini.trailspace").trim() end, map("n", "<localleader>w", function()
{ noremap = true }) require("mini.trailspace").trim()
end, { noremap = true })
-- PLUGIN: dial-increment -- PLUGIN: dial-increment
map("n", "<C-a>", '<Plug>(dial-increment)') map("n", "<C-a>", "<Plug>(dial-increment)")
map("n", "<C-x>", '<Plug>(dial-decrement)') map("n", "<C-x>", "<Plug>(dial-decrement)")
map("v", "<C-a>", '<Plug>(dial-increment)') map("v", "<C-a>", "<Plug>(dial-increment)")
map("v", "<C-x>", '<Plug>(dial-increment)') map("v", "<C-x>", "<Plug>(dial-increment)")
map("v", "g<C-a>", 'g<Plug>(dial-increment)') map("v", "g<C-a>", "g<Plug>(dial-increment)")
map("v", "g<C-x>", 'g<Plug>(dial-increment)') map("v", "g<C-x>", "g<Plug>(dial-increment)")
-- PLUGIN: zettelkasten.nvim -- PLUGIN: zettelkasten.nvim
map('n', '<cr>', [[:silent lua require 'zettelkasten'.link_follow()<cr>]]) map("n", "<cr>", [[:silent lua require 'zettelkasten'.link_follow()<cr>]])
map('v', '<cr>', [[:lua require 'zettelkasten'.link_follow(true)<cr>]]) map("v", "<cr>", [[:lua require 'zettelkasten'.link_follow(true)<cr>]])
prefix({ ['<leader>n'] = { name = '+notes' } }) prefix({ ["<leader>n"] = { name = "+notes" } })
map('n', '<leader>ni', [[:lua require 'zettelkasten'.index_open()<cr> ]], map("n", "<leader>ni", [[:lua require 'zettelkasten'.index_open()<cr> ]], { desc = "index page" })
{ desc = "index page" })
-- PLUGIN: zk -- PLUGIN: zk
map('n', '<leader>nn', "<cmd>ZkNotes { sort = { 'modified' } }<cr>", map("n", "<leader>nn", "<cmd>ZkNotes { sort = { 'modified' } }<cr>", { desc = "note list" })
{ desc = "note list" }) map(
map("n", "<leader>nf", "<Cmd>ZkNotes { sort = { 'modified' }, match = { vim.fn.input('Search: ') } }<CR>", "n",
{ desc = "note search" }) "<leader>nf",
map('n', '<leader>nt', "<cmd>ZkTags<cr>", "<Cmd>ZkNotes { sort = { 'modified' }, match = { vim.fn.input('Search: ') } }<CR>",
{ desc = "note tags" }) { desc = "note search" }
map('n', '<leader>nc', "<cmd>ZkCd<cr>", )
{ desc = "notes directory" }) map("n", "<leader>nt", "<cmd>ZkTags<cr>", { desc = "note tags" })
prefix({ ['<localleader>n'] = { name = '+note' } }) map("n", "<leader>nc", "<cmd>ZkCd<cr>", { desc = "notes directory" })
map('n', '<localleader>nl', "<cmd>ZkLinks<cr>", prefix({ ["<localleader>n"] = { name = "+note" } })
{ desc = "note links" }) map("n", "<localleader>nl", "<cmd>ZkLinks<cr>", { desc = "note links" })
map('n', '<localleader>nb', "<cmd>ZkLinks<cr>", map("n", "<localleader>nb", "<cmd>ZkLinks<cr>", { desc = "note backlinks" })
{ desc = "note backlinks" }) map("n", "<localleader>nn", "<cmd>ZkNew { title = vim.fn.input('Title: ') }<cr>", { desc = "new note" })
map('n', '<localleader>nn', "<cmd>ZkNew { title = vim.fn.input('Title: ') }<cr>", prefix({ ["<localleader>n"] = { name = "+note", mode = "v" } })
{ desc = "new note" }) map("v", "<localleader>nn", ":ZkNewFromTitleSelection<cr>", { desc = "title from selection" })
prefix({ ['<localleader>n'] = { name = '+note', mode = "v" } }) map("v", "<localleader>nN", ":ZkNewFromContentSelection<cr>", { desc = "content from selection" })
map('v', '<localleader>nn', ":ZkNewFromTitleSelection<cr>", map("v", "<localleader>nf", ":ZkMatch<cr>", { desc = "find note from selection" })
{ desc = "title from selection" })
map('v', '<localleader>nN', ":ZkNewFromContentSelection<cr>",
{ desc = "content from selection" })
map('v', '<localleader>nf', ":ZkMatch<cr>",
{ desc = "find note from selection" })
-- PLUGIN: toggleterm.nvim -- PLUGIN: toggleterm.nvim
-- create a lazygit window, set up in toggleterm settings -- create a lazygit window, set up in toggleterm settings
map('n', '<leader>G', ':Lazygit<cr>') map("n", "<leader>G", ":Lazygit<cr>")
prefix({ ['<localleader>s'] = { name = '+set' } }) prefix({ ["<localleader>s"] = { name = "+set" } })
-- PLUGIN: wrapping.nvim -- PLUGIN: wrapping.nvim
map('n', '<localleader>sw', [[:lua require('wrapping').toggle_wrap_mode()<cr> ]], map(
{ silent = true, desc = 'toggle wrap mode' }) "n",
"<localleader>sw",
[[:lua require('wrapping').toggle_wrap_mode()<cr> ]],
{ silent = true, desc = "toggle wrap mode" }
)
-- PLUGIN: easyread.nvim -- PLUGIN: easyread.nvim
map('n', '<localleader>ss', ':EasyreadToggle<cr>', { silent = true, desc = 'toggle speedreading' }) map("n", "<localleader>ss", ":EasyreadToggle<cr>", { silent = true, desc = "toggle speedreading" })
-- PLUGIN: nabla.nvim -- PLUGIN: nabla.nvim
map('n', '<localleader>sv', '<cmd>lua require("nabla").popup()<cr>', { silent = true, desc = 'latex formula popup' }) map("n", "<localleader>sv", '<cmd>lua require("nabla").popup()<cr>', { silent = true, desc = "latex formula popup" })
map('n', '<localleader>sV', '<cmd>lua require("nabla").toggle_virt({autogen = true, silent = true})<cr>', map(
{ silent = true, desc = 'toggle formula notation' }) "n",
"<localleader>sV",
'<cmd>lua require("nabla").toggle_virt({autogen = true, silent = true})<cr>',
{ silent = true, desc = "toggle formula notation" }
)
-- PLUGIN: nvim-colorizer -- PLUGIN: nvim-colorizer
map('n', '<localleader>sc', '<cmd>ColorizerToggle<cr>', { silent = true, desc = 'toggle colorizer' }) map("n", "<localleader>sc", "<cmd>ColorizerToggle<cr>", { silent = true, desc = "toggle colorizer" })
map('n', '<localleader>sC', '<cmd>lua require("colorizer").attach_to_buffer(0, {mode = "background"} )<cr>', map(
{ silent = true, desc = 'colorize background' }) "n",
"<localleader>sC",
'<cmd>lua require("colorizer").attach_to_buffer(0, {mode = "background"} )<cr>',
{ silent = true, desc = "colorize background" }
)

View file

@ -2,11 +2,10 @@ local M = {}
function M.getCompletionItems(prefix) function M.getCompletionItems(prefix)
-- define your total completion items -- define your total completion items
local items = vim.api.nvim_call_function('pandoc#completion#Complete', local items = vim.api.nvim_call_function("pandoc#completion#Complete", { 0, prefix })
{0, prefix})
return items return items
end end
M.complete_item = {item = M.getCompletionItems} M.complete_item = { item = M.getCompletionItems }
return M return M

View file

@ -9,11 +9,14 @@ window, otherwise opens a new split.
The buffer, by default is set to the pandoc filetype. The buffer, by default is set to the pandoc filetype.
This can be changed by setting the `g:scratchpad_ft` variable or the `b:scratchpad_ft` This can be changed by setting the `g:scratchpad_ft` variable or the `b:scratchpad_ft`
variable to the intended filetype. variable to the intended filetype.
]] -- ]]
--
local api = vim.api local api = vim.api
local M = {} local M = {}
local function isempty(s) return s == nil or s == '' end local function isempty(s)
return s == nil or s == ""
end
function M.create(split, ft) function M.create(split, ft)
-- should we create a new split or switch out the current buffer? -- should we create a new split or switch out the current buffer?
@ -28,13 +31,17 @@ function M.create(split, ft)
end end
local buf = api.nvim_create_buf(false, true) local buf = api.nvim_create_buf(false, true)
if buf == 0 then print("Error opening scratch buffer.") end if buf == 0 then
print("Error opening scratch buffer.")
end
api.nvim_buf_set_option(buf, "bufhidden", "hide") api.nvim_buf_set_option(buf, "bufhidden", "hide")
api.nvim_buf_set_option(buf, "buftype", "nofile") api.nvim_buf_set_option(buf, "buftype", "nofile")
api.nvim_buf_set_option(buf, "swapfile", false) api.nvim_buf_set_option(buf, "swapfile", false)
api.nvim_buf_set_option(buf, "filetype", ft) api.nvim_buf_set_option(buf, "filetype", ft)
if split then api.nvim_command('vsplit new') end -- i think this is the only way to interact with the buffers creating a new split if split then
api.nvim_command("vsplit new")
end -- i think this is the only way to interact with the buffers creating a new split
-- switch to scratchpad -- switch to scratchpad
api.nvim_win_set_buf(0, buf) api.nvim_win_set_buf(0, buf)
end end

View file

@ -1,4 +1,4 @@
require('gitsigns').setup { require("gitsigns").setup({
numhl = true, numhl = true,
signcolumn = false, signcolumn = false,
on_attach = function(bufnr) on_attach = function(bufnr)
@ -11,34 +11,46 @@ require('gitsigns').setup {
end end
-- Navigation -- Navigation
map('n', ']h', function() map("n", "]h", function()
if vim.wo.diff then return ']h' end if vim.wo.diff then
vim.schedule(function() gs.next_hunk() end) return "]h"
return '<Ignore>' end
vim.schedule(function()
gs.next_hunk()
end)
return "<Ignore>"
end, { expr = true }) end, { expr = true })
map('n', '[h', function() map("n", "[h", function()
if vim.wo.diff then return '[h' end if vim.wo.diff then
vim.schedule(function() gs.prev_hunk() end) return "[h"
return '<Ignore>' end
vim.schedule(function()
gs.prev_hunk()
end)
return "<Ignore>"
end, { expr = true }) end, { expr = true })
-- Actions -- Actions
require('which-key').register({ ['<localleader>h'] = { name = '+git' } }) require("which-key").register({ ["<localleader>h"] = { name = "+git" } })
map({ 'n', 'v' }, '<localleader>hs', ':Gitsigns stage_hunk<CR>', { desc = 'stage hunk' }) map({ "n", "v" }, "<localleader>hs", ":Gitsigns stage_hunk<CR>", { desc = "stage hunk" })
map({ 'n', 'v' }, '<localleader>hr', ':Gitsigns reset_hunk<CR>', { desc = 'reset hunk' }) map({ "n", "v" }, "<localleader>hr", ":Gitsigns reset_hunk<CR>", { desc = "reset hunk" })
map('n', '<localleader>hS', gs.stage_buffer, { desc = 'stage buffer' }) map("n", "<localleader>hS", gs.stage_buffer, { desc = "stage buffer" })
map('n', '<localleader>hu', gs.undo_stage_hunk, { desc = 'undo stage hunk' }) map("n", "<localleader>hu", gs.undo_stage_hunk, { desc = "undo stage hunk" })
map('n', '<localleader>hR', gs.reset_buffer, { desc = 'reset buffer' }) map("n", "<localleader>hR", gs.reset_buffer, { desc = "reset buffer" })
map('n', '<localleader>hp', gs.preview_hunk, { desc = 'preview hunk' }) map("n", "<localleader>hp", gs.preview_hunk, { desc = "preview hunk" })
map('n', '<localleader>hb', function() gs.blame_line { full = true } end, { desc = 'blame line' }) map("n", "<localleader>hb", function()
map('n', '<localleader>hB', gs.toggle_current_line_blame, { desc = 'toggle blame' }) gs.blame_line({ full = true })
map('n', '<localleader>hd', gs.diffthis, { desc = 'diffthis' }) end, { desc = "blame line" })
map('n', '<localleader>hD', function() gs.diffthis('~') end, { desc = 'diffbase' }) map("n", "<localleader>hB", gs.toggle_current_line_blame, { desc = "toggle blame" })
map('n', '<localleader>ht', gs.toggle_deleted, { desc = 'toggle deleted' }) map("n", "<localleader>hd", gs.diffthis, { desc = "diffthis" })
map("n", "<localleader>hD", function()
gs.diffthis("~")
end, { desc = "diffbase" })
map("n", "<localleader>ht", gs.toggle_deleted, { desc = "toggle deleted" })
-- Text object -- Text object
map({ 'o', 'x' }, 'ih', ':<C-U>Gitsigns select_hunk<CR>') map({ "o", "x" }, "ih", ":<C-U>Gitsigns select_hunk<CR>")
map({ 'o', 'x' }, 'ah', ':<C-U>Gitsigns select_hunk<CR>') map({ "o", "x" }, "ah", ":<C-U>Gitsigns select_hunk<CR>")
end end,
} })

View file

@ -1,28 +1,28 @@
require('lualine').setup { require("lualine").setup({
options = { options = {
icons_enabled = true, icons_enabled = true,
theme = 'auto', theme = "auto",
component_separators = {left = '', right = ''}, component_separators = { left = "", right = "" },
section_separators = {left = '', right = ''}, section_separators = { left = "", right = "" },
disabled_filetypes = {}, disabled_filetypes = {},
always_divide_middle = true always_divide_middle = true,
}, },
sections = { sections = {
lualine_a = {'mode'}, lualine_a = { "mode" },
lualine_b = {'branch', 'diff', 'diagnostics'}, lualine_b = { "branch", "diff", "diagnostics" },
lualine_c = {'filename'}, lualine_c = { "filename" },
lualine_x = {'encoding', 'fileformat', 'filetype'}, lualine_x = { "encoding", "fileformat", "filetype" },
lualine_y = {'progress', 'location'}, lualine_y = { "progress", "location" },
lualine_z = {'hostname'} lualine_z = { "hostname" },
}, },
inactive_sections = { inactive_sections = {
lualine_a = {}, lualine_a = {},
lualine_b = {'branch', 'diff'}, lualine_b = { "branch", "diff" },
lualine_c = {'filename'}, lualine_c = { "filename" },
lualine_x = {}, lualine_x = {},
lualine_y = {'location'}, lualine_y = { "location" },
lualine_z = {} lualine_z = {},
}, },
tabline = {}, tabline = {},
extensions = {'quickfix', 'toggleterm'} extensions = { "quickfix", "toggleterm" },
} })

View file

@ -1,24 +1,24 @@
require('mini.ai').setup() require("mini.ai").setup()
require('mini.comment').setup({ require("mini.comment").setup({
hooks = { hooks = {
pre = function() pre = function()
require('ts_context_commentstring.internal').update_commentstring() require("ts_context_commentstring.internal").update_commentstring()
end end,
} },
}) })
require('mini.cursorword').setup({ delay = 500 }) require("mini.cursorword").setup({ delay = 500 })
require('mini.fuzzy').setup() require("mini.fuzzy").setup()
require('mini.indentscope').setup({ require("mini.indentscope").setup({
symbol = "", symbol = "",
draw = { animation = require('mini.indentscope').gen_animation.none() }, draw = { animation = require("mini.indentscope").gen_animation.none() },
options = { indent_at_cursor = false } options = { indent_at_cursor = false },
}) })
require('mini.map').setup() require("mini.map").setup()
-- require('mini.move').setup() -- has not hit stable yet -- require('mini.move').setup() -- has not hit stable yet
require('mini.pairs').setup() require("mini.pairs").setup()
require('mini.trailspace').setup() require("mini.trailspace").setup()
local starter = require('mini.starter') local starter = require("mini.starter")
starter.setup({ starter.setup({
evaluate_single = true, evaluate_single = true,
items = { items = {
@ -26,13 +26,13 @@ starter.setup({
starter.sections.recent_files(10, false), starter.sections.recent_files(10, false),
starter.sections.recent_files(10, true), starter.sections.recent_files(10, true),
-- Use this if you set up 'mini.sessions' -- Use this if you set up 'mini.sessions'
starter.sections.telescope() starter.sections.telescope(),
}, },
content_hooks = { content_hooks = {
starter.gen_hook.adding_bullet(), starter.gen_hook.adding_bullet(),
starter.gen_hook.padding(3, 2), starter.gen_hook.padding(3, 2),
starter.gen_hook.aligning('center', 'center') starter.gen_hook.aligning("center", "center"),
} },
}) })
vim.api.nvim_set_hl(0, 'MiniCursorword', { bold = true }) vim.api.nvim_set_hl(0, "MiniCursorword", { bold = true })

View file

@ -4,40 +4,61 @@
-- rg (ripgrep) for in-text searches -- rg (ripgrep) for in-text searches
-- fd for quicker directory structure searches -- fd for quicker directory structure searches
-- lsp for a variety of lsp queries -- lsp for a variety of lsp queries
require("telescope").setup { require("telescope").setup({
defaults = { defaults = {
vimgrep_arguments = { vimgrep_arguments = {
'rg', '--ignore-vcs', '--hidden', '--color=never', '--no-heading', "rg",
'--with-filename', '--line-number', '--column', '--smart-case' "--ignore-vcs",
"--hidden",
"--color=never",
"--no-heading",
"--with-filename",
"--line-number",
"--column",
"--smart-case",
}, },
generic_sorter = require('mini.fuzzy').get_telescope_sorter generic_sorter = require("mini.fuzzy").get_telescope_sorter,
}, },
defaults = { defaults = {
-- Appearance -- Appearance
prompt_prefix = '', prompt_prefix = "",
selection_caret = '󰳟 ', selection_caret = "󰳟 ",
color_devicons = true color_devicons = true,
}, },
pickers = { pickers = {
buffers = {theme = "ivy"}, buffers = { theme = "ivy" },
oldfiles = {theme = "ivy"}, oldfiles = { theme = "ivy" },
find_files = { find_files = {
theme = "dropdown", theme = "dropdown",
-- nice minimal picker design -- nice minimal picker design
borderchars = { borderchars = {
{'', '', '', '', '', '', '', ''}, { "", "", "", "", "", "", "", "" },
prompt = {"", "", " ", "", '', '', "", ""}, prompt = { "", "", " ", "", "", "", "", "" },
results = { results = {
"", "", "", "", "", "", "", "" "",
"",
"",
"",
"",
"",
"",
"",
}, },
preview = { preview = {
'', '', '', '', '', '', '', '' "",
} "",
"",
"",
"",
"",
"",
"",
},
}, },
width = 0.8, width = 0.8,
previewer = false, previewer = false,
prompt_title = false prompt_title = false,
} },
} },
} })
require("telescope").load_extension("fzf") require("telescope").load_extension("fzf")

View file

@ -1,16 +1,18 @@
require("toggleterm").setup { require("toggleterm").setup({
open_mapping = [[<leader>=]], open_mapping = [[<leader>=]],
insert_mappings = false -- don't map the key in insert mode insert_mappings = false, -- don't map the key in insert mode
} })
local Terminal = require('toggleterm.terminal').Terminal local Terminal = require("toggleterm.terminal").Terminal
-- create a lazygit window with the lazygit command -- create a lazygit window with the lazygit command
local lazygit = Terminal:new({ local lazygit = Terminal:new({
cmd = "lazygit", cmd = "lazygit",
hidden = true, hidden = true,
direction = 'float', direction = "float",
float_opts = { border = "curved" } float_opts = { border = "curved" },
}) })
function _Lazygit_toggle() lazygit:toggle() end function _Lazygit_toggle()
lazygit:toggle()
end
vim.cmd([[command! Lazygit :lua _Lazygit_toggle()<cr>]]) vim.cmd([[command! Lazygit :lua _Lazygit_toggle()<cr>]])

View file

@ -1,5 +1,5 @@
local rainbow = require('ts-rainbow') local rainbow = require("ts-rainbow")
require 'nvim-treesitter.configs'.setup { require("nvim-treesitter.configs").setup({
-- one of "all", "maintained" (parsers with maintainers), or a list of languages -- one of "all", "maintained" (parsers with maintainers), or a list of languages
ensure_installed = "all", ensure_installed = "all",
highlight = { enable = true }, highlight = { enable = true },
@ -10,12 +10,12 @@ require 'nvim-treesitter.configs'.setup {
-- enable rainbow brackets, needs p00f/nvim-ts-rainbow -- enable rainbow brackets, needs p00f/nvim-ts-rainbow
rainbow = { rainbow = {
enable = true, enable = true,
strategy = { rainbow.strategy.global } strategy = { rainbow.strategy.global },
}, },
-- for improved commentstrings, needs corresponding plugin -- for improved commentstrings, needs corresponding plugin
context_commentstring = { context_commentstring = {
enable = true, enable = true,
enable_autocmd = false -- since we run it as a hook from the mini.comment plugin enable_autocmd = false, -- since we run it as a hook from the mini.comment plugin
} },
} })

View file

@ -2,115 +2,138 @@ local writing_ft = { "quarto", "pandoc", "markdown", "text", "tex" }
return { return {
-- essential -- essential
{ 'numToStr/Navigator.nvim', branch = "master", config = true }, -- allow seamless navigation between vim buffers and tmux/wezterm splits { "numToStr/Navigator.nvim", branch = "master", config = true }, -- allow seamless navigation between vim buffers and tmux/wezterm splits
{ 'jeffkreeftmeijer/vim-numbertoggle', event = "BufEnter" }, -- toggles numbers to absolute for all buffers but the current which is relative { "jeffkreeftmeijer/vim-numbertoggle", event = "BufEnter" }, -- toggles numbers to absolute for all buffers but the current which is relative
{ 'ojroques/vim-oscyank', event = "VeryLazy" }, -- yank from *anywhere* (even ssh session) to clipboard, using :OSCYank { "ojroques/vim-oscyank", event = "VeryLazy" }, -- yank from *anywhere* (even ssh session) to clipboard, using :OSCYank
{ 'ggandor/lightspeed.nvim', event = "VeryLazy" }, -- jump between letters with improved fFtT quicksearch, mimics sneak { "ggandor/lightspeed.nvim", event = "VeryLazy" }, -- jump between letters with improved fFtT quicksearch, mimics sneak
{ {
'lewis6991/gitsigns.nvim', -- show vcs changes on left-hand gutter "lewis6991/gitsigns.nvim", -- show vcs changes on left-hand gutter
config = function() require('plug._gitsigns') end, config = function()
event = "BufRead" require("plug._gitsigns")
}, { "m4xshen/smartcolumn.nvim", config = true }, -- auto-hiding colorcolumn end,
event = "BufRead",
},
{ "m4xshen/smartcolumn.nvim", config = true }, -- auto-hiding colorcolumn
-- files -- files
{ 'vifm/vifm.vim' }, -- integrate file manager { "vifm/vifm.vim" }, -- integrate file manager
{ {
'nvim-tree/nvim-tree.lua', -- integrate file tree "nvim-tree/nvim-tree.lua", -- integrate file tree
config = true, config = true,
dependencies = { 'nvim-tree/nvim-web-devicons', config = true }, dependencies = { "nvim-tree/nvim-web-devicons", config = true },
cmd = "NvimTreeToggle" cmd = "NvimTreeToggle",
}, -- colors }, -- colors
{ {
'RRethy/nvim-base16', "RRethy/nvim-base16",
event = "BufWinEnter", event = "BufWinEnter",
dependencies = { 'rktjmp/fwatch.nvim' } dependencies = { "rktjmp/fwatch.nvim" },
}, { },
'NvChad/nvim-colorizer.lua', -- color hex, named colors in the correct preview scheme {
"NvChad/nvim-colorizer.lua", -- color hex, named colors in the correct preview scheme
config = function() config = function()
require('colorizer').setup({ require("colorizer").setup({
user_default_options = { mode = 'virtualtext' } user_default_options = { mode = "virtualtext" },
}) })
end, end,
event = "VeryLazy" event = "VeryLazy",
}, -- editing }, -- editing
{ 'kylechui/nvim-surround', version = '*', config = true, event = "VeryLazy" }, -- surround things with other things using ys/cs/ds { "kylechui/nvim-surround", version = "*", config = true, event = "VeryLazy" }, -- surround things with other things using ys/cs/ds
{ {
'monaqa/dial.nvim', -- extend the ^a / ^x possibilities to dates, hex, alphabets, markdown headers "monaqa/dial.nvim", -- extend the ^a / ^x possibilities to dates, hex, alphabets, markdown headers
config = function() config = function()
local augend = require("dial.augend") local augend = require("dial.augend")
require("dial.config").augends:register_group { require("dial.config").augends:register_group({
-- default augends used when no group name is specified -- default augends used when no group name is specified
default = { default = {
augend.integer.alias.decimal, augend.integer.alias.hex, augend.integer.alias.decimal,
augend.integer.alias.hex,
augend.date.alias["%Y/%m/%d"], augend.date.alias["%Y/%m/%d"],
augend.date.alias["%Y-%m-%d"], augend.date.alias["%m/%d"], augend.date.alias["%Y-%m-%d"],
augend.date.alias["%H:%M:%S"], augend.date.alias["%H:%M"], augend.date.alias["%m/%d"],
augend.date.alias["%H:%M:%S"],
augend.date.alias["%H:%M"],
augend.constant.alias.de_weekday_full, augend.constant.alias.de_weekday_full,
augend.constant.alias.de_weekday, augend.constant.alias.de_weekday,
augend.constant.alias.bool, augend.semver.alias.semver, augend.constant.alias.bool,
augend.constant.alias.Alpha, augend.constant.alias.alpha, augend.semver.alias.semver,
augend.hexcolor.new { case = "lower" }, augend.constant.new { augend.constant.alias.Alpha,
augend.constant.alias.alpha,
augend.hexcolor.new({ case = "lower" }),
augend.constant.new({
elements = { "and", "or" }, elements = { "and", "or" },
word = true, -- if false, "sand" is incremented into "sor", "doctor" into "doctand", etc. word = true, -- if false, "sand" is incremented into "sor", "doctor" into "doctand", etc.
cyclic = true -- "or" is incremented into "and". cyclic = true, -- "or" is incremented into "and".
}, }),
augend.constant augend.constant.new({
.new {
elements = { "&&", "||" }, elements = { "&&", "||" },
word = false, word = false,
cyclic = true cyclic = true,
} }),
} },
} })
end, end,
event = "VeryLazy" event = "VeryLazy",
}, { },
'tommcdo/vim-exchange', -- adds exchange operator with cx. common use: cxiw . on 2 words to switch
event = "VeryLazy"
}, {
'junegunn/vim-easy-align', -- Align tables and other alignable things
event = "VeryLazy"
}, { 'edKotinsky/Arduino.nvim', ft = 'arduino', config = true }, -- statusline
{ {
'nvim-lualine/lualine.nvim', "tommcdo/vim-exchange", -- adds exchange operator with cx. common use: cxiw . on 2 words to switch
requires = { 'nvim-tree/nvim-web-devicons', config = true }, event = "VeryLazy",
config = function() require('plug._lualine') end },
{
"junegunn/vim-easy-align", -- Align tables and other alignable things
event = "VeryLazy",
},
{ "edKotinsky/Arduino.nvim", ft = "arduino", config = true }, -- statusline
{
"nvim-lualine/lualine.nvim",
requires = { "nvim-tree/nvim-web-devicons", config = true },
config = function()
require("plug._lualine")
end,
}, -- writing }, -- writing
{ 'vim-pandoc/vim-criticmarkup', ft = writing_ft }, { { "vim-pandoc/vim-criticmarkup", ft = writing_ft },
'jbyuki/nabla.nvim', {
"jbyuki/nabla.nvim",
ft = writing_ft, ft = writing_ft,
config = function() config = function()
require('nabla').enable_virt({ autogen = true, silent = true }) require("nabla").enable_virt({ autogen = true, silent = true })
end end,
}, { },
'mickael-menu/zk-nvim', {
config = function() require('zk').setup({ picker = "telescope" }) end "mickael-menu/zk-nvim",
}, {
'andrewferrier/wrapping.nvim',
config = function() config = function()
require('wrapping').setup({ require("zk").setup({ picker = "telescope" })
end,
},
{
"andrewferrier/wrapping.nvim",
config = function()
require("wrapping").setup({
create_keymappings = false, create_keymappings = false,
notify_on_switch = false notify_on_switch = false,
}) })
end end,
}, { },
'quarto-dev/quarto-nvim', {
"quarto-dev/quarto-nvim",
dependencies = { dependencies = {
'jmbuhr/otter.nvim', 'neovim/nvim-lspconfig', "jmbuhr/otter.nvim",
'vim-pandoc/vim-pandoc-syntax', 'hrsh7th/nvim-cmp', "neovim/nvim-lspconfig",
'nvim-treesitter/nvim-treesitter' "vim-pandoc/vim-pandoc-syntax",
"hrsh7th/nvim-cmp",
"nvim-treesitter/nvim-treesitter",
}, },
config = function() config = function()
require 'quarto'.setup { require("quarto").setup({
lspFeatures = { lspFeatures = {
enabled = true, enabled = true,
languages = { 'r', 'python', 'julia' }, languages = { "r", "python", "julia" },
diagnostics = { enabled = true, triggers = { "BufWrite" } }, diagnostics = { enabled = true, triggers = { "BufWrite" } },
completion = { enabled = true } completion = { enabled = true },
} },
} })
end, end,
ft = "quarto" ft = "quarto",
}, { },
{
"lkhphuc/jupyter-kernel.nvim", "lkhphuc/jupyter-kernel.nvim",
config = true, config = true,
cmd = "JupyterAttach", cmd = "JupyterAttach",
@ -119,126 +142,163 @@ return {
{ {
"<localleader>ck", "<localleader>ck",
"<Cmd>JupyterInspect<CR>", "<Cmd>JupyterInspect<CR>",
desc = "Inspect object in kernel" desc = "Inspect object in kernel",
} },
} },
}, { 'micarmst/vim-spellsync', event = "VeryLazy" }, -- personal dict improvements for git sync },
{ 'folke/zen-mode.nvim', config = true, event = "VeryLazy" }, -- provide distraction free writing { "micarmst/vim-spellsync", event = "VeryLazy" }, -- personal dict improvements for git sync
{ 'folke/twilight.nvim', event = "VeryLazy" }, -- provide even distraction free-er writing (lowlight paragraphs) { "folke/zen-mode.nvim", config = true, event = "VeryLazy" }, -- provide distraction free writing
{ "folke/twilight.nvim", event = "VeryLazy" }, -- provide even distraction free-er writing (lowlight paragraphs)
{ {
'JellyApple102/easyread.nvim', "JellyApple102/easyread.nvim",
config = true, config = true,
ft = writing_ft, ft = writing_ft,
cmd = 'EasyreadToggle' cmd = "EasyreadToggle",
}, -- enable 'speed-reading' mode (bionic reading) }, -- enable 'speed-reading' mode (bionic reading)
{ 'marty-oehme/zettelkasten.nvim', ft = writing_ft, event = "VeryLazy" }, -- simple static markdown linking { "marty-oehme/zettelkasten.nvim", ft = writing_ft, event = "VeryLazy" }, -- simple static markdown linking
{ {
"iamcco/markdown-preview.nvim", -- generate an auto-updating html preview for md files "iamcco/markdown-preview.nvim", -- generate an auto-updating html preview for md files
build = function() vim.fn["mkdp#util#install"]() end, build = function()
ft = writing_ft vim.fn["mkdp#util#install"]()
end,
ft = writing_ft,
}, -- languages }, -- languages
{ 'euclidianAce/BetterLua.vim', ft = 'lua' }, -- better syntax highlighting for lua { "euclidianAce/BetterLua.vim", ft = "lua" }, -- better syntax highlighting for lua
{ 'aliou/bats.vim', ft = { "bash", "sh", "zsh", "bats" } }, -- enable syntax for bats shell-code testing library { "aliou/bats.vim", ft = { "bash", "sh", "zsh", "bats" } }, -- enable syntax for bats shell-code testing library
-- REPL work -- REPL work
{ {
'WhiteBlackGoose/magma-nvim-goose', "WhiteBlackGoose/magma-nvim-goose",
build = ":UpdateRemotePlugins", build = ":UpdateRemotePlugins",
config = function() config = function()
vim.g.magma_image_provider = "kitty" vim.g.magma_image_provider = "kitty"
vim.g.magma_automatically_open_output = false vim.g.magma_automatically_open_output = false
end end,
}, { },
'echasnovski/mini.nvim', {
version = '*', "echasnovski/mini.nvim",
config = function() require('plug._mini') end version = "*",
}, { config = function()
require("plug._mini")
end,
},
{
"akinsho/nvim-toggleterm.lua", -- simpler, programmable and multiple terminal toggling for nvim "akinsho/nvim-toggleterm.lua", -- simpler, programmable and multiple terminal toggling for nvim
config = function() require('plug._toggleterm') end config = function()
}, require("plug._toggleterm")
end,
},
{ {
"folke/which-key.nvim", "folke/which-key.nvim",
config = function() require("which-key").setup {} end config = function()
require("which-key").setup({})
end,
}, -- fuzzy matching }, -- fuzzy matching
{ "nvim-telescope/telescope-fzf-native.nvim", build = 'make' }, { { "nvim-telescope/telescope-fzf-native.nvim", build = "make" },
{
"nvim-telescope/telescope.nvim", "nvim-telescope/telescope.nvim",
dependencies = { "nvim-lua/popup.nvim", "nvim-lua/plenary.nvim" }, dependencies = { "nvim-lua/popup.nvim", "nvim-lua/plenary.nvim" },
config = function() require('plug._telescope') end config = function()
}, { require("plug._telescope")
end,
},
{
"dense-analysis/neural", "dense-analysis/neural",
dependencies = { "MunifTanjim/nui.nvim", "elpiloto/significant.nvim" }, dependencies = { "MunifTanjim/nui.nvim", "elpiloto/significant.nvim" },
config = function() config = function()
require('neural').setup({ require("neural").setup({
source = { openai = { api_key = vim.env.OPENAI_API_KEY } } source = { openai = { api_key = vim.env.OPENAI_API_KEY } },
}) })
end end,
}, -- treesitter }, -- treesitter
{ {
'nvim-treesitter/nvim-treesitter', "nvim-treesitter/nvim-treesitter",
build = ':TSUpdate', build = ":TSUpdate",
config = function() require('plug._treesitter') end, config = function()
require("plug._treesitter")
end,
event = "BufReadPre", event = "BufReadPre",
-- rainbow brackets using treesitter -- rainbow brackets using treesitter
-- show current cursor context at top of buffer -- show current cursor context at top of buffer
-- improves commenting plugin above by using ts -- improves commenting plugin above by using ts
dependencies = { dependencies = {
'https://gitlab.com/HiPhish/nvim-ts-rainbow2.git', "https://gitlab.com/HiPhish/nvim-ts-rainbow2.git",
{ 'romgrk/nvim-treesitter-context', config = true }, { "romgrk/nvim-treesitter-context", config = true },
'JoosepAlviste/nvim-ts-context-commentstring' "JoosepAlviste/nvim-ts-context-commentstring",
} },
}, { 'nvim-treesitter/playground', cmd = "TSPlaygroundToggle" }, -- interactively view and query the treesitter tree },
{ "nvim-treesitter/playground", cmd = "TSPlaygroundToggle" }, -- interactively view and query the treesitter tree
{ {
'RRethy/nvim-treesitter-textsubjects', -- allows using . and ; to target treesitter branches "RRethy/nvim-treesitter-textsubjects", -- allows using . and ; to target treesitter branches
config = function() config = function()
require 'nvim-treesitter.configs'.setup { require("nvim-treesitter.configs").setup({
textsubjects = { textsubjects = {
enable = true, enable = true,
keymaps = { keymaps = {
['.'] = 'textsubjects-smart', ["."] = "textsubjects-smart",
[';'] = 'textsubjects-container-outer' [";"] = "textsubjects-container-outer",
} },
} },
} })
end, end,
event = "BufReadPre" event = "BufReadPre",
}, { },
{
-- lsp -- lsp
"VonHeikemen/lsp-zero.nvim", "VonHeikemen/lsp-zero.nvim",
dependencies = { dependencies = {
{ "neovim/nvim-lspconfig", branch = "master" }, { "neovim/nvim-lspconfig", branch = "master" },
"williamboman/mason.nvim", "williamboman/mason-lspconfig.nvim", { "williamboman/mason.nvim",
"williamboman/mason-lspconfig.nvim",
{
"hrsh7th/nvim-cmp", "hrsh7th/nvim-cmp",
branch = "main", branch = "main",
dependencies = { dependencies = {
"andersevenrud/cmp-tmux", "cbarrete/completion-vcard", "andersevenrud/cmp-tmux",
"f3fora/cmp-spell", "hrsh7th/cmp-nvim-lsp", "cbarrete/completion-vcard",
"hrsh7th/cmp-path", "hrsh7th/cmp-buffer", "f3fora/cmp-spell",
"hrsh7th/cmp-calc", "hrsh7th/cmp-cmdline", "hrsh7th/cmp-nvim-lsp",
"hrsh7th/cmp-nvim-lua", "dmitmel/cmp-digraphs", "hrsh7th/cmp-path",
"hrsh7th/cmp-buffer",
"hrsh7th/cmp-calc",
"hrsh7th/cmp-cmdline",
"hrsh7th/cmp-nvim-lua",
"dmitmel/cmp-digraphs",
"jc-doyle/cmp-pandoc-references", "jc-doyle/cmp-pandoc-references",
"kdheepak/cmp-latex-symbols", "lukas-reineke/cmp-rg", "kdheepak/cmp-latex-symbols",
"crispgm/cmp-beancount", "ray-x/cmp-treesitter", "lukas-reineke/cmp-rg",
"saadparwaiz1/cmp_luasnip" "crispgm/cmp-beancount",
} "ray-x/cmp-treesitter",
}, "L3MON4D3/LuaSnip", "rafamadriz/friendly-snippets", "saadparwaiz1/cmp_luasnip",
},
},
"L3MON4D3/LuaSnip",
"rafamadriz/friendly-snippets",
-- { "lukas-reineke/lsp-format.nvim", config = true }, -- { "lukas-reineke/lsp-format.nvim", config = true },
{ "j-hui/fidget.nvim", config = true }, -- loading animations for some LSP { "j-hui/fidget.nvim", config = true }, -- loading animations for some LSP
{ {
"jay-babu/mason-null-ls.nvim", "jay-babu/mason-null-ls.nvim",
event = { "BufReadPre", "BufNewFile" }, event = { "BufReadPre", "BufNewFile" },
dependencies = { dependencies = {
"williamboman/mason.nvim", "jose-elias-alvarez/null-ls.nvim" "williamboman/mason.nvim",
"jose-elias-alvarez/null-ls.nvim",
}, },
}
}, },
config = function() require('plug._lsp') end, },
branch = "v2.x" config = function()
}, { 'simrat39/symbols-outline.nvim', config = true, event = "VeryLazy" }, -- vista-like outline view for code require("plug._lsp")
{ 'ray-x/lsp_signature.nvim', config = true }, -- UI improvements end,
{ 'stevearc/dressing.nvim', config = true }, { branch = "v2.x",
'rcarriga/nvim-notify', },
config = function() vim.notify = require("notify") end { "simrat39/symbols-outline.nvim", config = true, event = "VeryLazy" }, -- vista-like outline view for code
} { "ray-x/lsp_signature.nvim", config = true }, -- UI improvements
{ "stevearc/dressing.nvim", config = true },
{
"rcarriga/nvim-notify",
config = function()
vim.notify = require("notify")
end,
},
-- { -- REQUIRES custom `yay -S --asdeps lua51-lyaml invocation` AND is suuper slow -- { -- REQUIRES custom `yay -S --asdeps lua51-lyaml invocation` AND is suuper slow
-- "jghauser/papis.nvim", -- "jghauser/papis.nvim",
-- after = { "telescope.nvim", "nvim-cmp" }, -- after = { "telescope.nvim", "nvim-cmp" },

View file

@ -1,6 +1,8 @@
local default_builtins_disabled = { "netrw", "netrwPlugin" } local default_builtins_disabled = { "netrw", "netrwPlugin" }
local disable_builtins = function(builtins) local disable_builtins = function(builtins)
for _, plugin in pairs(builtins) do vim.g["loaded_" .. plugin] = 1 end for _, plugin in pairs(builtins) do
vim.g["loaded_" .. plugin] = 1
end
end end
local o = { local o = {
@ -15,7 +17,7 @@ local o = {
-- make jumplist behave more like browser, when jumping back -- make jumplist behave more like browser, when jumping back
-- and then adding a new jump discards all the previous -- and then adding a new jump discards all the previous
-- 'future-jump' tree, making more sense for wiki-like movement -- 'future-jump' tree, making more sense for wiki-like movement
jumpoptions = 'stack', jumpoptions = "stack",
-- set cursor line highlighting, esp useful when using with bracket -- set cursor line highlighting, esp useful when using with bracket
-- highlighting and you don't know which side of the brace the cursor is on -- highlighting and you don't know which side of the brace the cursor is on
cursorline = true, cursorline = true,
@ -24,7 +26,7 @@ local o = {
number = true, number = true,
relativenumber = true, relativenumber = true,
-- puts the numbers into the signcolumn so when git/lsp show signs there's no jump -- puts the numbers into the signcolumn so when git/lsp show signs there's no jump
signcolumn = 'number', signcolumn = "number",
-- keeps an undofile next to files so that you can even undo if vim is closed -- keeps an undofile next to files so that you can even undo if vim is closed
-- in between -- in between
undofile = true, undofile = true,
@ -35,7 +37,7 @@ local o = {
ignorecase = true, ignorecase = true,
smartcase = true, smartcase = true,
-- shows previews of what substitute command will do (and a couple others) -- shows previews of what substitute command will do (and a couple others)
inccommand = 'split', inccommand = "split",
-- disables showing us the current mode in the command line since airline takes -- disables showing us the current mode in the command line since airline takes
-- care of it -- care of it
showmode = false, showmode = false,
@ -46,9 +48,9 @@ local o = {
foldlevel = 2, foldlevel = 2,
conceallevel = 2, conceallevel = 2,
-- enable mouse, doesn't bug me and might come in useful at some point -- enable mouse, doesn't bug me and might come in useful at some point
mouse = 'a', mouse = "a",
-- pump all clippings into the system clipboard -- pump all clippings into the system clipboard
clipboard = 'unnamedplus', clipboard = "unnamedplus",
-- turn of automatic resizing of individual splits -- turn of automatic resizing of individual splits
equalalways = false, equalalways = false,
-- make sure there's always *some* context below cursor -- make sure there's always *some* context below cursor
@ -64,5 +66,5 @@ for k, v in pairs(o) do
vim.opt[k] = v vim.opt[k] = v
end end
vim.api.nvim_set_var('tex_flavor', 'latex') vim.api.nvim_set_var("tex_flavor", "latex")
disable_builtins(default_builtins_disabled) disable_builtins(default_builtins_disabled)

View file

@ -1,14 +1,14 @@
local util = require('lspconfig/util') local util = require("lspconfig/util")
local path = util.path local path = util.path
local T = {} local T = {}
local exepath = vim.fn.exepath local exepath = vim.fn.exepath
local path_sep = function() local path_sep = function()
local is_win = vim.loop.os_uname().sysname:find('Windows') local is_win = vim.loop.os_uname().sysname:find("Windows")
if is_win then if is_win then
return '\\' return "\\"
else else
return '/' return "/"
end end
end end
@ -16,30 +16,27 @@ end
T.get_path = function(workspace) T.get_path = function(workspace)
-- Use activated virtualenv. -- Use activated virtualenv.
if vim.env.VIRTUAL_ENV then if vim.env.VIRTUAL_ENV then
return path.join(vim.env.VIRTUAL_ENV, 'bin', 'python'), 'virtual env' return path.join(vim.env.VIRTUAL_ENV, "bin", "python"), "virtual env"
end end
-- Find and use virtualenv in workspace directory. -- Find and use virtualenv in workspace directory.
for _, pattern in ipairs({ '*', '.*' }) do for _, pattern in ipairs({ "*", ".*" }) do
local match = vim.fn.glob(path.join(workspace, pattern, 'pyvenv.cfg')) local match = vim.fn.glob(path.join(workspace, pattern, "pyvenv.cfg"))
local sep = path_sep() local sep = path_sep()
local py = 'bin' .. sep .. 'python' local py = "bin" .. sep .. "python"
if match ~= '' then if match ~= "" then
match = string.gsub(match, 'pyvenv.cfg', py) match = string.gsub(match, "pyvenv.cfg", py)
return match, string.format('venv base folder: %s', match) return match, string.format("venv base folder: %s", match)
end end
match = vim.fn.glob(path.join(workspace, pattern, 'poetry.lock')) match = vim.fn.glob(path.join(workspace, pattern, "poetry.lock"))
if match ~= '' then if match ~= "" then
local venv_base_folder = vim.fn.trim(vim.fn.system( local venv_base_folder = vim.fn.trim(vim.fn.system("poetry env info -p"))
'poetry env info -p')) return path.join(venv_base_folder, "bin", "python"), string.format("venv base folder: %s", venv_base_folder)
return path.join(venv_base_folder, 'bin', 'python'),
string.format('venv base folder: %s', venv_base_folder)
end end
end end
-- Fallback to system Python. -- Fallback to system Python.
return exepath('python3') or exepath('python') or 'python', return exepath("python3") or exepath("python") or "python", "fallback to system python path"
'fallback to system python path'
end end
return T return T

View file

@ -1,15 +1,13 @@
local accounts = {} local accounts = {}
local _, gmailuser = pipe_from( local _, gmailuser = pipe_from("pass show misc/gmail-app-password | grep username | cut -d: -f2")
'pass show misc/gmail-app-password | grep username | cut -d: -f2') local _, gmailpass = pipe_from("pass show misc/gmail-app-password | head -n1")
local _, gmailpass = pipe_from(
'pass show misc/gmail-app-password | head -n1')
-- Setup an imap account called gmail -- Setup an imap account called gmail
accounts.gmail = IMAP { accounts.gmail = IMAP({
server = "imap.gmail.com", server = "imap.gmail.com",
username = gmailuser, username = gmailuser,
password = gmailpass, password = gmailpass,
ssl = "auto" ssl = "auto",
} })
return accounts return accounts

View file

@ -20,7 +20,9 @@ CONTINUOUS = false
UPDATE_TIME = 120 UPDATE_TIME = 120
-- implement simple wait function in case server does not support IDLE mode -- implement simple wait function in case server does not support IDLE mode
function sleep(n) os.execute("sleep " .. tonumber(n)) end function sleep(n)
os.execute("sleep " .. tonumber(n))
end
-- will set filters to be grabbed from XDG-compliant filter directory -- will set filters to be grabbed from XDG-compliant filter directory
-- can be overridden with env var IMAPFILTER_FILTERDIR -- can be overridden with env var IMAPFILTER_FILTERDIR
@ -60,27 +62,22 @@ end
-- create global variable containing the configuration files -- create global variable containing the configuration files
configDir = getConfigDir() configDir = getConfigDir()
assert(configDir, assert(configDir, "No configuration directory found. Ensure " .. os.getenv("HOME") .. "/.config/imapfilter exists.")
"No configuration directory found. Ensure " .. os.getenv("HOME") ..
"/.config/imapfilter exists.")
-- create global variable containing account access -- create global variable containing account access
accounts = loadfile(configDir .. "/accounts.lua")() accounts = loadfile(configDir .. "/accounts.lua")()
assert(accounts, assert(accounts, "No accounts configured. Ensure accounts.lua exists and returns a table of accounts.")
"No accounts configured. Ensure accounts.lua exists and returns a table of accounts.")
-- immediately act on the filters once -- immediately act on the filters once
applyFilters(getFilterDir()) applyFilters(getFilterDir())
-- continuously watch for mail if needed -- continuously watch for mail if needed
while CONTINUOUS == true do while CONTINUOUS == true do
local has_idle = accounts.gmail['Inbox']:enter_idle() local has_idle = accounts.gmail["Inbox"]:enter_idle()
applyFilters(getFilterDir()) applyFilters(getFilterDir())
if has_idle == false then if has_idle == false then
print( print("Server does not support idle, application will be polling again in " .. UPDATE_TIME .. "minutes.")
"Server does not support idle, application will be polling again in " ..
UPDATE_TIME .. "minutes.")
sleep(UPDATE_TIME) sleep(UPDATE_TIME)
end end
end end

View file

@ -27,14 +27,13 @@ function getSenderList(rollupfile)
local file = io.open(rollupfile) local file = io.open(rollupfile)
if file then if file then
for line in file:lines() do table.insert(rollupSenders, line) end for line in file:lines() do
table.insert(rollupSenders, line)
end
else else
print( print("rollup did not find rollup.txt file containing mail addresses at " .. rollupfile or ". Skipping.")
"rollup did not find rollup.txt file containing mail addresses at " ..
rollupfile or ". Skipping.")
end end
return rollupSenders return rollupSenders
end end
sendToFolder(accounts.gmail["Inbox"], accounts.gmail["Dump"], sendToFolder(accounts.gmail["Inbox"], accounts.gmail["Dump"], getSenderList(getRollupFile()))
getSenderList(getRollupFile()))

View file

@ -1,56 +1,62 @@
local wezterm = require 'wezterm' local wezterm = require("wezterm")
local io = require 'io' local io = require("io")
local os = require 'os' local os = require("os")
local act = wezterm.action local act = wezterm.action
local function setup() local function setup()
local function isViProcess(pane) local function isViProcess(pane)
return pane:get_foreground_process_name():find('n?vim') ~= nil return pane:get_foreground_process_name():find("n?vim") ~= nil
end end
local function conditionalActivatePane(window, pane, pane_direction, local function conditionalActivatePane(window, pane, pane_direction, vim_direction)
vim_direction) if isViProcess(pane) then
if (isViProcess(pane)) then window:perform_action(
window:perform_action(act.Multiple { act.Multiple({
act.SendKey { key = 'w', mods = 'CTRL' }, act.SendKey({ key = "w", mods = "CTRL" }),
act.SendKey { key = vim_direction } act.SendKey({ key = vim_direction }),
}, pane) }),
pane
)
else else
window:perform_action(act.ActivatePaneDirection(pane_direction), window:perform_action(act.ActivatePaneDirection(pane_direction), pane)
pane)
end end
end end
wezterm.on('ActivatePaneDirection-right', function(window, pane) wezterm.on("ActivatePaneDirection-right", function(window, pane)
conditionalActivatePane(window, pane, 'Right', 'l') conditionalActivatePane(window, pane, "Right", "l")
end) end)
wezterm.on('ActivatePaneDirection-left', function(window, pane) wezterm.on("ActivatePaneDirection-left", function(window, pane)
conditionalActivatePane(window, pane, 'Left', 'h') conditionalActivatePane(window, pane, "Left", "h")
end) end)
wezterm.on('ActivatePaneDirection-up', function(window, pane) wezterm.on("ActivatePaneDirection-up", function(window, pane)
conditionalActivatePane(window, pane, 'Up', 'k') conditionalActivatePane(window, pane, "Up", "k")
end) end)
wezterm.on('ActivatePaneDirection-down', function(window, pane) wezterm.on("ActivatePaneDirection-down", function(window, pane)
conditionalActivatePane(window, pane, 'Down', 'j') conditionalActivatePane(window, pane, "Down", "j")
end) end)
-- Retrieve the current scrollback text and send to editor -- Retrieve the current scrollback text and send to editor
wezterm.on('edit-scrollback', function(window, pane) wezterm.on("edit-scrollback", function(window, pane)
local viewport_text = pane:get_lines_as_text(10000) local viewport_text = pane:get_lines_as_text(10000)
-- Create a temporary file to pass to vim -- Create a temporary file to pass to vim
local name = os.tmpname() local name = os.tmpname()
local f = io.open(name, 'w+') local f = io.open(name, "w+")
if f == nil then return false end if f == nil then
return false
end
f:write(viewport_text) f:write(viewport_text)
f:flush() f:flush()
f:close() f:close()
-- Open a new window running vim and tell it to open the file -- Open a new window running vim and tell it to open the file
window:perform_action(act.SpawnCommandInNewTab { window:perform_action(
args = { (os.getenv('EDITOR') or 'vi'), name } act.SpawnCommandInNewTab({
}, pane) args = { (os.getenv("EDITOR") or "vi"), name },
}),
pane
)
-- Wait time for vim to read the file before we remove it. -- Wait time for vim to read the file before we remove it.
wezterm.sleep_ms(1000) wezterm.sleep_ms(1000)
@ -62,7 +68,7 @@ local function setup()
local overrides = window:get_config_overrides() or {} local overrides = window:get_config_overrides() or {}
if not overrides.leader then if not overrides.leader then
wezterm.log_info("leader wasn't set") wezterm.log_info("leader wasn't set")
overrides.leader = { key = "s", mods = "SUPER" }; overrides.leader = { key = "s", mods = "SUPER" }
else else
wezterm.log_info("leader was set") wezterm.log_info("leader was set")
overrides.leader = nil overrides.leader = nil

View file

@ -1,127 +1,137 @@
local wezterm = require('wezterm') local wezterm = require("wezterm")
local act = wezterm.action local act = wezterm.action
local keys = { local keys = {
{ key = 'O', mods = 'CTRL', action = act.ShowDebugOverlay }, { key = "O", mods = "CTRL", action = act.ShowDebugOverlay },
{ key = '[', mods = 'CTRL', action = act.ScrollToPrompt(-1) }, { key = "[", mods = "CTRL", action = act.ScrollToPrompt(-1) },
{ key = ']', mods = 'CTRL', action = act.ScrollToPrompt(1) }, { key = "]", mods = "CTRL", action = act.ScrollToPrompt(1) },
{ -- vertical pane { -- vertical pane
key = '\\', key = "\\",
mods = 'LEADER', mods = "LEADER",
action = act.SplitHorizontal { domain = 'CurrentPaneDomain' } action = act.SplitHorizontal({ domain = "CurrentPaneDomain" }),
}, { -- horizontal pane },
key = '-', { -- horizontal pane
mods = 'LEADER', key = "-",
action = act.SplitVertical { domain = 'CurrentPaneDomain' } mods = "LEADER",
action = act.SplitVertical({ domain = "CurrentPaneDomain" }),
}, -- pane movement keys }, -- pane movement keys
{ {
key = 'h', key = "h",
mods = 'CTRL', mods = "CTRL",
action = act.EmitEvent 'ActivatePaneDirection-left' action = act.EmitEvent("ActivatePaneDirection-left"),
}, },
{ {
key = 'j', key = "j",
mods = 'CTRL', mods = "CTRL",
action = act.EmitEvent 'ActivatePaneDirection-down' action = act.EmitEvent("ActivatePaneDirection-down"),
}, },
{ {
key = 'k', key = "k",
mods = 'CTRL', mods = "CTRL",
action = act.EmitEvent 'ActivatePaneDirection-up' action = act.EmitEvent("ActivatePaneDirection-up"),
}, { },
key = 'l',
mods = 'CTRL',
action = act.EmitEvent 'ActivatePaneDirection-right'
}, { key = 'z', mods = 'LEADER', action = act.TogglePaneZoomState },
{ key = ' ', mods = 'LEADER', action = act.RotatePanes 'Clockwise' },
{ key = 'q', mods = 'LEADER', action = act.PaneSelect { mode = 'Activate' } },
{ {
key = 'Q', key = "l",
mods = 'LEADER', mods = "CTRL",
action = act.PaneSelect { mode = 'SwapWithActive' } action = act.EmitEvent("ActivatePaneDirection-right"),
}, { key = 'c', mods = 'LEADER', action = act.SpawnTab 'CurrentPaneDomain' }, },
{ key = ',', mods = 'LEADER', action = act.MoveTabRelative(-1) }, { key = "z", mods = "LEADER", action = act.TogglePaneZoomState },
{ key = '.', mods = 'LEADER', action = act.MoveTabRelative(1) }, -- workspace selection { key = " ", mods = "LEADER", action = act.RotatePanes("Clockwise") },
{ key = "q", mods = "LEADER", action = act.PaneSelect({ mode = "Activate" }) },
{ {
key = 's', key = "Q",
mods = 'LEADER', mods = "LEADER",
action = act.ShowLauncherArgs { flags = 'FUZZY|WORKSPACES' } action = act.PaneSelect({ mode = "SwapWithActive" }),
}, { key = 't', mods = 'LEADER', action = act.ShowTabNavigator }, },
{ key = '[', mods = 'LEADER', action = act.ActivateCopyMode }, { { key = "c", mods = "LEADER", action = act.SpawnTab("CurrentPaneDomain") },
key = 'r', { key = ",", mods = "LEADER", action = act.MoveTabRelative(-1) },
mods = 'LEADER', { key = ".", mods = "LEADER", action = act.MoveTabRelative(1) }, -- workspace selection
action = act.ActivateKeyTable { {
name = 'resize_pane', key = "s",
mods = "LEADER",
action = act.ShowLauncherArgs({ flags = "FUZZY|WORKSPACES" }),
},
{ key = "t", mods = "LEADER", action = act.ShowTabNavigator },
{ key = "[", mods = "LEADER", action = act.ActivateCopyMode },
{
key = "r",
mods = "LEADER",
action = act.ActivateKeyTable({
name = "resize_pane",
one_shot = false, one_shot = false,
timeout_milliseconds = 2000, timeout_milliseconds = 2000,
replace_current = true replace_current = true,
} }),
}, { key = 'f', mods = 'LEADER', action = act.QuickSelect }, { },
key = 'F', { key = "f", mods = "LEADER", action = act.QuickSelect },
mods = 'LEADER', {
action = wezterm.action.QuickSelectArgs { key = "F",
mods = "LEADER",
action = wezterm.action.QuickSelectArgs({
patterns = { "https?://\\S+" }, patterns = { "https?://\\S+" },
action = wezterm.action_callback( action = wezterm.action_callback(function(window, pane)
function(window, pane)
local url = window:get_selection_text_for_pane(pane) local url = window:get_selection_text_for_pane(pane)
wezterm.log_info("opening: " .. url) wezterm.log_info("opening: " .. url)
wezterm.open_with(url) wezterm.open_with(url)
end) end),
} }),
}, { },
key = '/', {
mods = 'LEADER', key = "/",
action = act.Search('CurrentSelectionOrEmptyString') mods = "LEADER",
}, { action = act.Search("CurrentSelectionOrEmptyString"),
key = 'b', },
mods = 'LEADER', {
action = act.ActivateKeyTable { key = "b",
name = 'scroll_mode', mods = "LEADER",
action = act.ActivateKeyTable({
name = "scroll_mode",
one_shot = false, one_shot = false,
replace_current = true, replace_current = true,
timeout_milliseconds = 15000 timeout_milliseconds = 15000,
} }),
}, { key = 'e', mods = 'LEADER', action = act.EmitEvent 'edit-scrollback' }, },
{ key = "e", mods = "LEADER", action = act.EmitEvent("edit-scrollback") },
{ {
key = 'l', key = "l",
mods = 'LEADER', mods = "LEADER",
action = act.EmitEvent 'ActivatePaneDirection-Right' action = act.EmitEvent("ActivatePaneDirection-Right"),
}, { key = 'a', mods = 'CTRL|ALT', action = act.EmitEvent 'toggle-leader' } },
{ key = "a", mods = "CTRL|ALT", action = act.EmitEvent("toggle-leader") },
} }
-- Leader + number to activate that tab -- Leader + number to activate that tab
for i = 1, 8 do for i = 1, 8 do
table.insert(keys, { table.insert(keys, {
key = tostring(i), key = tostring(i),
mods = 'LEADER', mods = "LEADER",
action = act.ActivateTab(i - 1) action = act.ActivateTab(i - 1),
}) })
end end
-- key table sub modes -- key table sub modes
local key_tables = { local key_tables = {
-- mode to change size of any panes -- mode to change size of any panes
resize_pane = { resize_pane = {
{ key = 'h', action = act.AdjustPaneSize { 'Left', 1 } }, { key = "h", action = act.AdjustPaneSize({ "Left", 1 }) },
{ key = 'l', action = act.AdjustPaneSize { 'Right', 1 } }, { key = "l", action = act.AdjustPaneSize({ "Right", 1 }) },
{ key = 'k', action = act.AdjustPaneSize { 'Up', 1 } }, { key = "k", action = act.AdjustPaneSize({ "Up", 1 }) },
{ key = 'j', action = act.AdjustPaneSize { 'Down', 1 } }, { key = "j", action = act.AdjustPaneSize({ "Down", 1 }) },
{ key = 'H', action = act.AdjustPaneSize { 'Left', 10 } }, { key = "H", action = act.AdjustPaneSize({ "Left", 10 }) },
{ key = 'L', action = act.AdjustPaneSize { 'Right', 10 } }, { key = "L", action = act.AdjustPaneSize({ "Right", 10 }) },
{ key = 'K', action = act.AdjustPaneSize { 'Up', 10 } }, { key = "K", action = act.AdjustPaneSize({ "Up", 10 }) },
{ key = 'J', action = act.AdjustPaneSize { 'Down', 10 } }, { key = "J", action = act.AdjustPaneSize({ "Down", 10 }) },
{ key = 'Escape', action = 'PopKeyTable' } { key = "Escape", action = "PopKeyTable" },
}, },
scroll_mode = { scroll_mode = {
{ key = 'y', mods = 'CTRL', action = act.ScrollByLine(-1) }, { key = "y", mods = "CTRL", action = act.ScrollByLine(-1) },
{ key = 'e', mods = 'CTRL', action = act.ScrollByLine(1) }, { key = "e", mods = "CTRL", action = act.ScrollByLine(1) },
{ key = 'f', mods = 'CTRL', action = act.ScrollByPage(1) }, { key = "f", mods = "CTRL", action = act.ScrollByPage(1) },
{ key = 'b', mods = 'CTRL', action = act.ScrollByPage(-1) }, { key = "b", mods = "CTRL", action = act.ScrollByPage(-1) },
{ key = 'd', mods = 'CTRL', action = act.ScrollByPage(0.5) }, { key = "d", mods = "CTRL", action = act.ScrollByPage(0.5) },
{ key = 'u', mods = 'CTRL', action = act.ScrollByPage(-0.5) }, { key = "u", mods = "CTRL", action = act.ScrollByPage(-0.5) },
{ key = 'g', mods = 'CTRL', action = act.ScrollToTop }, { key = "g", mods = "CTRL", action = act.ScrollToTop },
{ key = 'G', mods = 'CTRL', action = act.ScrollToBottom }, { key = "G", mods = "CTRL", action = act.ScrollToBottom },
{ key = 'Escape', action = 'PopKeyTable' } { key = "Escape", action = "PopKeyTable" },
} },
} }
return { keys = keys, key_tables = key_tables } return { keys = keys, key_tables = key_tables }

View file

@ -1,45 +1,46 @@
local wezterm = require 'wezterm' local wezterm = require("wezterm")
local function basename(s) return string.gsub(s or '', '(.*[/\\])(.*)', '%2') end local function basename(s)
return string.gsub(s or "", "(.*[/\\])(.*)", "%2")
end
local SEPARATOR = ' | ' local SEPARATOR = " | "
local function setup() local function setup()
-- STATUSBAR -- STATUSBAR
-- show currently active key table in lower right status bar -- show currently active key table in lower right status bar
-- mimicing Vim modes -- mimicing Vim modes
wezterm.on('update-status', function(window, pane) wezterm.on("update-status", function(window, pane)
local displayed = { left = {}, right = {} } local displayed = { left = {}, right = {} }
local keytable = window:active_key_table() local keytable = window:active_key_table()
if keytable then if keytable then
displayed.left[#displayed.left + 1] = 'MODE: ' .. keytable displayed.left[#displayed.left + 1] = "MODE: " .. keytable
end end
local workspace = window:active_workspace() local workspace = window:active_workspace()
if workspace and workspace ~= 'default' then if workspace and workspace ~= "default" then
displayed.left[#displayed.left + 1] = 'WORKSPACE: ' .. workspace displayed.left[#displayed.left + 1] = "WORKSPACE: " .. workspace
end end
local bat = '' local bat = ""
for _, b in ipairs(wezterm.battery_info()) do for _, b in ipairs(wezterm.battery_info()) do
bat = '🔋 ' .. string.format('%.0f%%', b.state_of_charge * 100) .. bat = "🔋 " .. string.format("%.0f%%", b.state_of_charge * 100) .. " " .. b.state
' ' .. b.state
end end
displayed.right[#displayed.right + 1] = bat displayed.right[#displayed.right + 1] = bat
local currentprogram = pane:get_foreground_process_name() local currentprogram = pane:get_foreground_process_name()
displayed.right[#displayed.right + 1] = basename(currentprogram) displayed.right[#displayed.right + 1] = basename(currentprogram)
local statusleft = '' local statusleft = ""
for _, v in ipairs(displayed.left) do for _, v in ipairs(displayed.left) do
statusleft = statusleft .. v .. SEPARATOR statusleft = statusleft .. v .. SEPARATOR
end end
local statusright = '' local statusright = ""
for _, v in ipairs(displayed.right) do for _, v in ipairs(displayed.right) do
statusright = statusright .. v .. SEPARATOR statusright = statusright .. v .. SEPARATOR
end end
window:set_left_status(statusleft or '') window:set_left_status(statusleft or "")
window:set_right_status(statusright or '') window:set_right_status(statusright or "")
end) end)
end end

View file

@ -1,9 +1,9 @@
local wezterm = require 'wezterm' local wezterm = require("wezterm")
local maps = require 'maps' local maps = require("maps")
require 'statusbar'.setup() require("statusbar").setup()
require 'events'.setup() require("events").setup()
local function file_exists(name) local function file_exists(name)
local f = io.open(name, "r") local f = io.open(name, "r")
@ -16,9 +16,7 @@ local function file_exists(name)
end end
-- automatically reload colors file -- automatically reload colors file
local colorsfile = (os.getenv('XDG_STATE_HOME') or local colorsfile = (os.getenv("XDG_STATE_HOME") or (os.getenv("HOME") .. "/.local/state")) .. "/wezterm/colors.toml"
(os.getenv('HOME') .. '/.local/state')) ..
'/wezterm/colors.toml'
local colors = {} local colors = {}
if file_exists(colorsfile) == true then if file_exists(colorsfile) == true then
wezterm.add_to_config_reload_watch_list(colorsfile) wezterm.add_to_config_reload_watch_list(colorsfile)
@ -35,48 +33,46 @@ local settings = {
color_scheme = "Nord (base16)", -- will be overwritten by colors color_scheme = "Nord (base16)", -- will be overwritten by colors
-- default_prog = {"nu"}, -- default_prog = {"nu"},
scrollback_lines = 10000, scrollback_lines = 10000,
font = wezterm.font('Iosevka Nerd Font'), font = wezterm.font("Iosevka Nerd Font"),
-- add cursive italic font from Victor font for all weights -- add cursive italic font from Victor font for all weights
font_rules = { font_rules = {
{ {
intensity = 'Bold', intensity = "Bold",
italic = true, italic = true,
font = wezterm.font { font = wezterm.font({
family = 'VictorMono Nerd Font', family = "VictorMono Nerd Font",
weight = 'Bold', weight = "Bold",
style = 'Italic', style = "Italic",
}, }),
}, },
{ {
italic = true, italic = true,
intensity = 'Half', intensity = "Half",
font = wezterm.font { font = wezterm.font({
family = 'VictorMono Nerd Font', family = "VictorMono Nerd Font",
weight = 'DemiBold', weight = "DemiBold",
style = 'Italic', style = "Italic",
}, }),
}, },
{ {
italic = true, italic = true,
intensity = 'Normal', intensity = "Normal",
font = wezterm.font { font = wezterm.font({
family = 'VictorMono Nerd Font', family = "VictorMono Nerd Font",
style = 'Italic', style = "Italic",
}, }),
}, },
}, },
line_height = 1.0, line_height = 1.0,
leader = { key = 'a', mods = 'CTRL', timeout_milliseconds = 1500 }, leader = { key = "a", mods = "CTRL", timeout_milliseconds = 1500 },
keys = maps.keys, keys = maps.keys,
key_tables = maps.key_tables, key_tables = maps.key_tables,
mouse_bindings = { mouse_bindings = {
{ {
event = { Up = { streak = 1, button = 'Left' } }, event = { Up = { streak = 1, button = "Left" } },
mods = 'NONE', mods = "NONE",
action = wezterm.action action = wezterm.action.CompleteSelectionOrOpenLinkAtMouseCursor("ClipboardAndPrimarySelection"),
.CompleteSelectionOrOpenLinkAtMouseCursor },
'ClipboardAndPrimarySelection' },
}
}
} }
return settings return settings