mirror of
https://github.com/acedanger/dotfiles.git
synced 2025-12-05 22:30:13 -08:00
copied profile
This commit is contained in:
266
wezterm/.config/utils/class/picker.lua
Normal file
266
wezterm/.config/utils/class/picker.lua
Normal file
@@ -0,0 +1,266 @@
|
||||
---@module "utils.class.picker"
|
||||
---@author sravioli
|
||||
---@license GNU-GPLv3
|
||||
|
||||
---@diagnostic disable: undefined-field
|
||||
|
||||
local Utils = require "utils"
|
||||
local fs, Logger = Utils.fn.fs, Utils.class.logger
|
||||
|
||||
local wt = require "wezterm"
|
||||
local config_dir = wt.config_dir
|
||||
|
||||
-- {{{1 Meta
|
||||
|
||||
--~ {{{2 wt.Window
|
||||
|
||||
---@class wt.Window
|
||||
---@field active_key_table function
|
||||
---@field active_pane function
|
||||
---@field active_tab function
|
||||
---@field active_workspace function
|
||||
---@field composition_status function
|
||||
---@field copy_to_clipboard function
|
||||
---@field current_event function
|
||||
---@field effective_config function
|
||||
---@field focus function
|
||||
---@field get_appearance function
|
||||
---@field get_config_overrides function
|
||||
---@field get_dimensions function
|
||||
---@field get_selection_escapes_for_pane function
|
||||
---@field get_selection_text_for_pane function
|
||||
---@field is_focused function
|
||||
---@field keyboard_modifiers function
|
||||
---@field leader_is_active function
|
||||
---@field maximize function
|
||||
---@field mux_window function
|
||||
---@field perform_action function
|
||||
---@field restore function
|
||||
---@field set_config_overrides function
|
||||
---@field set_inner_size function
|
||||
---@field set_left_status function
|
||||
---@field set_position function
|
||||
---@field set_right_status function
|
||||
---@field toast_notification function
|
||||
---@field toggle_fullscreen function
|
||||
---@field window_id function
|
||||
|
||||
--~ }}}
|
||||
|
||||
--~ {{{2 wt.Pane
|
||||
|
||||
---@class wt.Pane
|
||||
---@field activate function
|
||||
---@field get_current_working_dir function
|
||||
---@field get_cursor_position function
|
||||
---@field get_dimensions function
|
||||
---@field get_domain_name function
|
||||
---@field get_foreground_process_info function
|
||||
---@field get_foreground_process_name function
|
||||
---@field get_lines_as_escapes function
|
||||
---@field get_lines_as_text function
|
||||
---@field get_logical_lines_as_text function
|
||||
---@field get_metadata function
|
||||
---@field get_semantic_zone_at function
|
||||
---@field get_semantic_zones function
|
||||
---@field get_text_from_region function
|
||||
---@field get_text_from_semantic_zone function
|
||||
---@field get_title function
|
||||
---@field get_tty_name function
|
||||
---@field get_user_vars function
|
||||
---@field has_unseen_output function
|
||||
---@field inject_output function
|
||||
---@field is_alt_screen_active function
|
||||
---@field move_to_new_tab function
|
||||
---@field move_to_new_window function
|
||||
---@field mux_pane function
|
||||
---@field pane_id function
|
||||
---@field paste function
|
||||
---@field send_paste function
|
||||
---@field send_text function
|
||||
---@field split function
|
||||
---@field tab function
|
||||
---@field window function
|
||||
|
||||
--~ }}}
|
||||
|
||||
--~ {{{2 Utils.Class.Picker
|
||||
|
||||
---@alias Module PickList
|
||||
---@alias Choice { id: string, label: string|table }
|
||||
---@alias Choice.private { module: Module, value: Choice }
|
||||
|
||||
---@class Utils.Class.Picker
|
||||
---@field subdir string name of the picker module
|
||||
---@field title string defaults to `"Pick a value"`
|
||||
---@field choices? Choice[] defaults to `{}`
|
||||
---@field __choices? Choice.private[] defaults to `{}`
|
||||
---@field fuzzy? boolean defaults to `false`
|
||||
---@field alphabet? string defaults to `"1234567890abcdefghilmnopqrstuvwxyz"`
|
||||
---@field description? string defaults to `"Select an item."`
|
||||
---@field fuzzy_description? string defaults to `"Fuzzy matching: "`
|
||||
---@field comp? fun(a, b): boolean function to sort choices
|
||||
---@field build? fun(__choices: Choice.private[], comp: function, opts: { window: wt.Window, pane: wt.Pane }): Choice[]
|
||||
---@field new? fun(opts: Utils.Class.Picker): Utils.Class.Picker
|
||||
---@field private log? Utils.Class.Logger
|
||||
|
||||
--~ }}}
|
||||
|
||||
--~ {{{2 PickList.Opts
|
||||
|
||||
---@alias PickList.Opts { window: wt.Window, pane: wt.Pane, id: string|nil, label: string|nil }
|
||||
---@alias PickList.getReturn string|{ id: string|nil, label: string|table|nil }
|
||||
|
||||
---@class PickList
|
||||
---@field get fun(): PickList.getReturn
|
||||
---@field activate fun(Config: table, opts: PickList.Opts): nil
|
||||
|
||||
--~ }}}
|
||||
|
||||
-- }}}
|
||||
|
||||
-- {{{1 Helper functions
|
||||
|
||||
local h = {}
|
||||
|
||||
---Normalize an item to the `choices` format
|
||||
---@param item string|number
|
||||
---@return table normalized_item
|
||||
function h.normalize(item)
|
||||
return type(item) == "table" and item or { id = item }
|
||||
end
|
||||
|
||||
---Determines whether the given item is an array or not.
|
||||
---@param item PickList.getReturn
|
||||
---@return boolean result whether or not the item is an array
|
||||
function h.is_array(item)
|
||||
return type(item) == "table" and item[1] ~= nil
|
||||
end
|
||||
|
||||
---Build the choices table
|
||||
---@param items table
|
||||
---@param comp? fun(a, b): boolean
|
||||
---@return Choice[] choices
|
||||
function h.build(items, comp)
|
||||
local choices = {}
|
||||
for _, item in pairs(items) do
|
||||
choices[#choices + 1] = { id = item.value.id, label = item.value.label }
|
||||
end
|
||||
|
||||
table.sort(choices, comp or function(a, b)
|
||||
return a.id < b.id
|
||||
end)
|
||||
|
||||
return choices
|
||||
end
|
||||
|
||||
---Converts a file path to a lua require path
|
||||
---@param path string
|
||||
---@return string require_path
|
||||
function h.path_to_module(path)
|
||||
return (path:sub(#config_dir + 2):gsub("%.lua$", ""):gsub(fs.path_separator, "."))
|
||||
end
|
||||
|
||||
-- }}}
|
||||
|
||||
---@class Utils.Class.Picker
|
||||
local M = {}
|
||||
|
||||
---Creates a new picker object
|
||||
---@param opts Utils.Class.Picker
|
||||
---@return Utils.Class.Picker Picker
|
||||
function M.new(opts)
|
||||
local self = setmetatable({}, { __index = M })
|
||||
self.title = opts.title or "Pick a value"
|
||||
self.choices = {}
|
||||
self.__choices = {}
|
||||
self.log = Logger:new("Picker > " .. self.title)
|
||||
|
||||
self.comp = opts.comp
|
||||
self.build = opts.build or h.build
|
||||
|
||||
self.fuzzy = opts.fuzzy or false
|
||||
self.alphabet = opts.alphabet or "1234567890abcdefghilmnopqrstuvwxyz"
|
||||
self.description = opts.description or "Select an item."
|
||||
self.fuzzy_description = opts.fuzzy_description or "Fuzzy matching: "
|
||||
|
||||
local dir = fs.pathconcat(config_dir, "picker", "assets", opts.subdir)
|
||||
local paths = fs.ls_dir(dir)
|
||||
if not paths then
|
||||
self.log:error("Cannot read files from %s", dir)
|
||||
return {}
|
||||
end
|
||||
for i = 1, #paths do
|
||||
self:register(h.path_to_module(paths[i]))
|
||||
end
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
---Registers the module by requiring it and filling the `__choices` table
|
||||
---@param name string the lua require path to the module
|
||||
function M:register(name)
|
||||
---@class PickList
|
||||
local module = require(name)
|
||||
local result = module.get()
|
||||
|
||||
if h.is_array(result) then
|
||||
for i = 1, #result do
|
||||
local item = h.normalize(result[i])
|
||||
self.__choices[item.id] =
|
||||
{ module = module, value = { id = item.id, label = item.label } }
|
||||
self.log:debug("registered item: %s", self.__choices[item.id])
|
||||
end
|
||||
else
|
||||
---@cast result string
|
||||
result = h.normalize(result)
|
||||
self.__choices[result.id] =
|
||||
{ module = module, value = { id = result.id, label = result.label } }
|
||||
self.log:debug("registered item: %s", self.__choices[result.id])
|
||||
end
|
||||
end
|
||||
|
||||
---Activates the selected module
|
||||
---@param Overrides table config overrides
|
||||
---@param opts PickList.Opts
|
||||
---@return nil
|
||||
function M:select(Overrides, opts)
|
||||
local choice = self.__choices[opts.id]
|
||||
if not choice then
|
||||
return self.log:error("%s is not defined for %s", opts.id, self.title)
|
||||
end
|
||||
|
||||
choice.module.activate(Overrides, opts)
|
||||
end
|
||||
|
||||
---Invoke the picker.
|
||||
---@return nil
|
||||
function M:pick()
|
||||
return wt.action_callback(function(window, pane)
|
||||
local opts = { window = window, pane = pane }
|
||||
window:perform_action(
|
||||
wt.action.InputSelector {
|
||||
action = wt.action_callback(function(inner_window, _, id, label)
|
||||
if not id and not label then
|
||||
self.log:error "cancelled by user"
|
||||
else
|
||||
local callback_opts = { window = window, pane = pane, id = id, label = label }
|
||||
self.log:info("applying %s", id)
|
||||
local Overrides = inner_window:get_config_overrides() or {}
|
||||
self:select(Overrides, callback_opts)
|
||||
window:set_config_overrides(Overrides)
|
||||
end
|
||||
end),
|
||||
title = self.title,
|
||||
choices = self.build(self.__choices, self.comp, opts),
|
||||
fuzzy = self.fuzzy,
|
||||
description = self.description,
|
||||
fuzzy_description = self.fuzzy_description,
|
||||
alphabet = self.alphabet,
|
||||
},
|
||||
pane
|
||||
)
|
||||
end)
|
||||
end
|
||||
|
||||
return M
|
||||
Reference in New Issue
Block a user