1.1--- a/lisp/lib/cli/cli.asd Mon Aug 05 21:57:13 2024 -0400
1.2+++ b/lisp/lib/cli/cli.asd Tue Aug 06 21:17:24 2024 -0400
1.3@@ -1,6 +1,6 @@
1.4 ;;; cli.asd --- CLI library
1.5 (defsystem :cli
1.6- :depends-on (:std :log :dat)
1.7+ :depends-on (:std :log :dat :obj)
1.8 :components ((:file "pkg")
1.9 (:file "ansi" :depends-on ("pkg"))
1.10 (:file "env" :depends-on ("pkg"))
2.1--- a/lisp/lib/cli/tools/pkg.lisp Mon Aug 05 21:57:13 2024 -0400
2.2+++ b/lisp/lib/cli/tools/pkg.lisp Tue Aug 06 21:17:24 2024 -0400
2.3@@ -12,6 +12,8 @@
2.4
2.5 (defpackage :cli/tools/tmux
2.6 (:use :cl :std :cli/env :cli/tools/term)
2.7+ (:import-from :obj/cfg
2.8+ :defcfg :make-cfg :find-cfg)
2.9 (:export
2.10 :*tmux-user-config-path*
2.11 :*tmux-system-config-path*
2.12@@ -21,7 +23,7 @@
2.13 :tmux-format-string
2.14 :*tmux-variables*
2.15 :*tmux-var-table*
2.16- :tmux-error))
2.17+ :simple-tmux-error))
2.18
2.19 (defpackage :cli/tools/cc
2.20 (:use :cl :std :cli/env)
3.1--- a/lisp/lib/cli/tools/tmux.lisp Mon Aug 05 21:57:13 2024 -0400
3.2+++ b/lisp/lib/cli/tools/tmux.lisp Tue Aug 06 21:17:24 2024 -0400
3.3@@ -19,10 +19,10 @@
3.4 ;;; Code:
3.5 (in-package :cli/tools/tmux)
3.6
3.7-(deferror tmux-error (simple-error error) ())
3.8+(deferror simple-tmux-error (simple-error error) ())
3.9
3.10-(defun tmux-error (fmt &rest args)
3.11- (error 'tmux-error :format-arguments args :format-control fmt))
3.12+(defun simple-tmux-error (fmt &rest args)
3.13+ (error 'simple-tmux-error :format-arguments args :format-control fmt))
3.14
3.15 (defparameter *tmux-user-config-path* (merge-pathnames ".tmux.conf" (user-homedir-pathname)))
3.16 (defparameter *tmux-system-config-path* (merge-pathnames "tmux.conf" "/etc/"))
3.17@@ -32,10 +32,26 @@
3.18 (defparameter *default-tmux-tmpdir* (pathname (format nil "/tmp/tmux-~A/" (sb-posix:getuid))))
3.19 (defparameter *default-tmux-socket* (merge-pathnames "default" *default-tmux-tmpdir*))
3.20
3.21+;;; Utils
3.22+(defun run-tmux (&rest args)
3.23+ (let ((proc (sb-ext:run-program *tmux* (or args nil) :output :stream)))
3.24+ (with-open-stream (s (sb-ext:process-output proc))
3.25+ (loop for l = (read-line s nil nil)
3.26+ while l
3.27+ do (write-line l)))
3.28+ (if (eq 0 (sb-ext:process-exit-code proc))
3.29+ nil
3.30+ (simple-tmux-error "tmux command failed: ~A ~A" args))))
3.31+
3.32+(defun spawn-tmux (&rest args)
3.33+ (run-terminal (append (list "-e" "tmux") args)))
3.34+
3.35+;;; Session > Window > Pane
3.36 (defstruct tmux-session
3.37 (id 0 :type fixnum)
3.38 name
3.39 (windows nil :type list))
3.40+
3.41 (defstruct tmux-window
3.42 (id 0 :type fixnum)
3.43 name
3.44@@ -46,249 +62,7 @@
3.45 (id 0 :type fixnum)
3.46 name)
3.47
3.48-(defun run-tmux (&rest args)
3.49- (let ((proc (sb-ext:run-program *tmux* (or args nil) :output :stream)))
3.50- (with-open-stream (s (sb-ext:process-output proc))
3.51- (loop for l = (read-line s nil nil)
3.52- while l
3.53- do (write-line l)))
3.54- (if (eq 0 (sb-ext:process-exit-code proc))
3.55- nil
3.56- (tmux-error "tmux command failed: ~A ~A" args))))
3.57-
3.58-(defun spawn-tmux (&rest args)
3.59- (run-terminal (append (list "-e" "tmux") args)))
3.60-
3.61-;;; Format Strings
3.62-(defun format-tmux-string (dst fmt &rest args)
3.63- (apply #'format dst fmt (mapcar (lambda (a) (format nil "#{~A}" a)) args)))
3.64-
3.65-(defvar *tmux-variables*
3.66- '(active_window_index ;; Index of active window in session
3.67- alternate_on ;; 1 if pane is in alternate screen
3.68- alternate_saved_x ;; Saved cursor X in alternate screen
3.69- alternate_saved_y ;; Saved cursor Y in alternate screen
3.70- buffer_created ;; Time buffer created
3.71- buffer_name ;; Name of buffer
3.72- buffer_sample ;; Sample of start of buffer
3.73- buffer_size ;; Size of the specified buffer in bytes
3.74- client_activity ;; Time client last had activity
3.75- client_cell_height ;; Height of each client cell in pixels
3.76- client_cell_width ;; Width of each client cell in pixels
3.77- client_control_mode ;; 1 if client is in control mode
3.78- client_created ;; Time client created
3.79- client_discarded ;; Bytes discarded when client behind
3.80- client_flags ;; List of client flags
3.81- client_height ;; Height of client
3.82- client_key_table ;; Current key table
3.83- client_last_session ;; Name of the client's last session
3.84- client_name ;; Name of client
3.85- client_pid ;; PID of client process
3.86- client_prefix ;; 1 if prefix key has been pressed
3.87- client_readonly ;; 1 if client is read-only
3.88- client_session ;; Name of the client's session
3.89- client_termfeatures ;; Terminal features of client, if any
3.90- client_termname ;; Terminal name of client
3.91- client_termtype ;; Terminal type of client, if available
3.92- client_tty ;; Pseudo terminal of client
3.93- client_uid ;; UID of client process
3.94- client_user ;; User of client process
3.95- client_utf8 ;; 1 if client supports UTF-8
3.96- client_width ;; Width of client
3.97- client_written ;; Bytes written to client
3.98- command ;; Name of command in use, if any
3.99- command_list_alias ;; Command alias if listing commands
3.100- command_list_name ;; Command name if listing commands
3.101- command_list_usage ;; Command usage if listing commands
3.102- config_files ;; List of configuration files loaded
3.103- copy_cursor_line ;; Line the cursor is on in copy mode
3.104- copy_cursor_word ;; Word under cursor in copy mode
3.105- copy_cursor_x ;; Cursor X position in copy mode
3.106- copy_cursor_y ;; Cursor Y position in copy mode
3.107- current_file ;; Current configuration file
3.108- cursor_character ;; Character at cursor in pane
3.109- cursor_flag ;; Pane cursor flag
3.110- cursor_x ;; Cursor X position in pane
3.111- cursor_y ;; Cursor Y position in pane
3.112- history_bytes ;; Number of bytes in window history
3.113- history_limit ;; Maximum window history lines
3.114- history_size ;; Size of history in lines
3.115- hook ;; Name of running hook, if any
3.116- hook_client ;; Name of client where hook was run, if any
3.117- hook_pane ;; ID of pane where hook was run, if any
3.118- hook_session ;; ID of session where hook was run, if any
3.119- hook_session_name ;; Name of session where hook was run, if any
3.120- hook_window ;; ID of window where hook was run, if any
3.121- hook_window_name ;; Name of window where hook was run, if any
3.122- host ;; H Hostname of local host
3.123- host_short ;; h Hostname of local host (no domain name)
3.124- insert_flag ;; Pane insert flag
3.125- keypad_cursor_flag ;; Pane keypad cursor flag
3.126- keypad_flag ;; Pane keypad flag
3.127- last_window_index ;; Index of last window in session
3.128- line ;; Line number in the list
3.129- mouse_all_flag ;; Pane mouse all flag
3.130- mouse_any_flag ;; Pane mouse any flag
3.131- mouse_button_flag ;; Pane mouse button flag
3.132- mouse_hyperlink ;; Hyperlink under mouse, if any
3.133- mouse_line ;; Line under mouse, if any
3.134- mouse_sgr_flag ;; Pane mouse SGR flag
3.135- mouse_standard_flag ;; Pane mouse standard flag
3.136- mouse_status_line ;; Status line on which mouse event took place
3.137- mouse_status_range ;; Range type or argument of mouse event on status line
3.138- mouse_utf8_flag ;; Pane mouse UTF-8 flag
3.139- mouse_word ;; Word under mouse, if any
3.140- mouse_x ;; Mouse X position, if any
3.141- mouse_y ;; Mouse Y position, if any
3.142- next_session_id ;; Unique session ID for next new session
3.143- origin_flag ;; Pane origin flag
3.144- pane_active ;; 1 if active pane
3.145- pane_at_bottom ;; 1 if pane is at the bottom of window
3.146- pane_at_left ;; 1 if pane is at the left of window
3.147- pane_at_right ;; 1 if pane is at the right of window
3.148- pane_at_top ;; 1 if pane is at the top of window
3.149- pane_bg ;; Pane background colour
3.150- pane_bottom ;; Bottom of pane
3.151- pane_current_command ;; Current command if available
3.152- pane_current_path ;; Current path if available
3.153- pane_dead ;; 1 if pane is dead
3.154- pane_dead_signal ;; Exit signal of process in dead pane
3.155- pane_dead_status ;; Exit status of process in dead pane
3.156- pane_dead_time ;; Exit time of process in dead pane
3.157- pane_fg ;; Pane foreground colour
3.158- pane_format ;; 1 if format is for a pane
3.159- pane_height ;; Height of pane
3.160- pane_id ;; D Unique pane ID
3.161- pane_in_mode ;; 1 if pane is in a mode
3.162- pane_index ;; P Index of pane
3.163- pane_input_off ;; 1 if input to pane is disabled
3.164- pane_last ;; 1 if last pane
3.165- pane_left ;; Left of pane
3.166- pane_marked ;; 1 if this is the marked pane
3.167- pane_marked_set ;; 1 if a marked pane is set
3.168- pane_mode ;; Name of pane mode, if any
3.169- pane_path ;; Path of pane (can be set by application)
3.170- pane_pid ;; PID of first process in pane
3.171- pane_pipe ;; 1 if pane is being piped
3.172- pane_right ;; Right of pane
3.173- pane_search_string ;; Last search string in copy mode
3.174- pane_start_command ;; Command pane started with
3.175- pane_start_path ;; Path pane started with
3.176- pane_synchronized ;; 1 if pane is synchronized
3.177- pane_tabs ;; Pane tab positions
3.178- pane_title ;; T Title of pane (can be set by application)
3.179- pane_top ;; Top of pane
3.180- pane_tty ;; Pseudo terminal of pane
3.181- pane_unseen_changes ;; 1 if there were changes in pane while in mode
3.182- pane_width ;; Width of pane
3.183- pid ;; Server PID
3.184- rectangle_toggle ;; 1 if rectangle selection is activated
3.185- scroll_position ;; Scroll position in copy mode
3.186- scroll_region_lower ;; Bottom of scroll region in pane
3.187- scroll_region_upper ;; Top of scroll region in pane
3.188- search_match ;; Search match if any
3.189- search_present ;; 1 if search started in copy mode
3.190- selection_active ;; 1 if selection started and changes with the cursor in copy mode
3.191- selection_end_x ;; X position of the end of the selection
3.192- selection_end_y ;; Y position of the end of the selection
3.193- selection_present ;; 1 if selection started in copy mode
3.194- selection_start_x ;; X position of the start of the selection
3.195- selection_start_y ;; Y position of the start of the selection
3.196- server_sessions ;; Number of sessions
3.197- session_activity ;; Time of session last activity
3.198- session_alerts ;; List of window indexes with alerts
3.199- session_attached ;; Number of clients session is attached to
3.200- session_attached_list ;; List of clients session is attached to
3.201- session_created ;; Time session created
3.202- session_format ;; 1 if format is for a session
3.203- session_group ;; Name of session group
3.204- session_group_attached ;; Number of clients sessions in group are attached to
3.205- session_group_attached_list ;; List of clients sessions in group are attached to
3.206- session_group_list ;; List of sessions in group
3.207- session_group_many_attached ;; 1 if multiple clients attached to sessions in group
3.208- session_group_size ;; Size of session group
3.209- session_grouped ;; 1 if session in a group
3.210- session_id ;; Unique session ID
3.211- session_last_attached ;; Time session last attached
3.212- session_many_attached ;; 1 if multiple clients attached
3.213- session_marked ;; 1 if this session contains the marked pane
3.214- session_name ;; S Name of session
3.215- session_path ;; Working directory of session
3.216- session_stack ;; Window indexes in most recent order
3.217- session_windows ;; Number of windows in session
3.218- socket_path ;; Server socket path
3.219- start_time ;; Server start time
3.220- uid ;; Server UID
3.221- user ;; Server user
3.222- version ;; Server version
3.223- window_active ;; 1 if window active
3.224- window_active_clients ;; Number of clients viewing this window
3.225- window_active_clients_list ;; List of clients viewing this window
3.226- window_active_sessions ;; Number of sessions on which this window is active
3.227- window_active_sessions_list ;; List of sessions on which this window is active
3.228- window_activity ;; Time of window last activity
3.229- window_activity_flag ;; 1 if window has activity
3.230- window_bell_flag ;; 1 if window has bell
3.231- window_bigger ;; 1 if window is larger than client
3.232- window_cell_height ;; Height of each cell in pixels
3.233- window_cell_width ;; Width of each cell in pixels
3.234- window_end_flag ;; 1 if window has the highest index
3.235- window_flags ;; F Window flags with # escaped as ##
3.236- window_format ;; 1 if format is for a window
3.237- window_height ;; Height of window
3.238- window_id ;; Unique window ID
3.239- window_index ;; I Index of window
3.240- window_last_flag ;; 1 if window is the last used
3.241- window_layout ;; Window layout description, ignoring zoomed window panes
3.242- window_linked ;; 1 if window is linked across sessions
3.243- window_linked_sessions ;; Number of sessions this window is linked to
3.244- window_linked_sessions_list ;; List of sessions this window is linked to
3.245- window_marked_flag ;; 1 if window contains the marked pane
3.246- window_name ;; W Name of window
3.247- window_offset_x ;; X offset into window if larger than client
3.248- window_offset_y ;; Y offset into window if larger than client
3.249- window_panes ;; Number of panes in window
3.250- window_raw_flags ;; Window flags with nothing escaped
3.251- window_silence_flag ;; 1 if window has silence alert
3.252- window_stack_index ;; Index in session most recent stack
3.253- window_start_flag ;; 1 if window has the lowest index
3.254- window_visible_layout ;; Window layout description, respecting zoomed window panes
3.255- window_width ;; Width of window
3.256- window_zoomed_flag ;; 1 if window is zoomed
3.257- wrap_flag ;; Pane wrap flag
3.258- ;; display-menu vars
3.259- popup_centre_x Centered in the client
3.260- popup_centre_y ;; entered in the client
3.261- popup_height ;; eight of menu or popup
3.262- popup_mouse_bottom ;; ottom of at the mouse
3.263- popup_mouse_centre_x ;; orizontal centre at the mouse
3.264- popup_mouse_centre_y ;; ertical centre at the mouse
3.265- popup_mouse_top ;; op at the mouse
3.266- popup_mouse_x ;; ouse X position
3.267- popup_mouse_y ;; ouse Y position
3.268- popup_pane_bottom ;; ottom of the pane
3.269- popup_pane_left ;; eft of the pane
3.270- popup_pane_right ;; ight of the pane
3.271- popup_pane_top ;; op of the pane
3.272- popup_status_line_y ;; bove or below the status line
3.273- popup_width ;; idth of menu or popup
3.274- popup_window_status_line_x ;; t the window position in status line
3.275- popup_window_status_line_y ;; t the status line showing the window
3.276- ))
3.277-
3.278-(defvar *tmux-var-table*
3.279- (let ((tbl (make-hash-table :test 'equal :size (length *tmux-variables*))))
3.280- (dolist (v *tmux-variables* tbl)
3.281- (setf (gethash v tbl) (string-downcase (symbol-name v))))))
3.282-
3.283-(defmacro tmux-format (dst fmt &rest args)
3.284- "Format a tmux string, replacing symbols in ARGS that match a member of
3.285-*TMUX-VARIABLES* with their corresponding lower-case name."
3.286- `(format-tmux-string ,dst ,fmt
3.287- ,@(mapcar (lambda (a)
3.288- (gethash (symbolicate a) *tmux-var-table* a))
3.289- args)))
3.290-
3.291+;;; Controller
3.292 (defstruct tmux-controller
3.293 (input nil :type (or null sb-sys:fd-stream))
3.294 (output nil :type (or null sb-sys:fd-stream))
3.295@@ -312,3 +86,281 @@
3.296 (defun read-tmux-line (ctrl)
3.297 (read-line (tmux-controller-output ctrl)))
3.298
3.299+(defstruct tmux-command name flags args)
3.300+
3.301+(defun parse-tmux-command (str)
3.302+ "Parse a single TMUX-COMMAND from a string."
3.303+ (let ((words (split-sequence #\space str)))
3.304+ ;; TODO 2024-08-06: parse for real
3.305+ (make-tmux-command :name (car words) :args (cdr words))))
3.306+
3.307+(defcfg tmux-config ()
3.308+ ((commands :initform nil)
3.309+ (server-options :type hash-table)
3.310+ (session-options :type hash-table)
3.311+ (window-options :type hash-table)
3.312+ (keys :type hash-table))
3.313+ (:documentation "A CFG object containing the parsed content of a tmux configuration file."))
3.314+
3.315+(defmethod make-cfg ((obj (eql :tmux)) &key commands server session window keys)
3.316+ (let ((cfg (make-instance 'tmux-config)))
3.317+ (when commands (setf (slot-value cfg 'commands) commands))
3.318+ (when server (setf (slot-value cfg 'server-options) server))
3.319+ (when session (setf (slot-value cfg 'session-options) session))
3.320+ (when window (setf (slot-value cfg 'window-options) window))
3.321+ (when keys (setf (slot-value cfg 'keys) keys))
3.322+ cfg))
3.323+
3.324+(defmethod find-cfg ((obj (eql :tmux)) &key system user)
3.325+ "Find a tmux configuration and load it.
3.326+
3.327+When SYSTEM is non-nil, skip check for user config.
3.328+
3.329+When USER is non-nil it should be the name of a user whose cfg will be loaded
3.330+from /home/USER/.tmux.conf."
3.331+ (let ((path (cond
3.332+ (system (probe-file *tmux-system-config-path*))
3.333+ (user (probe-file (format nil "/home/~A/.tmux.conf" user)))
3.334+ (t (or (probe-file *tmux-user-config-path*) (probe-file *tmux-system-config-path*)))))
3.335+ (obj (make-cfg :tmux :commands nil)))
3.336+ (with-open-file (file path)
3.337+ (with-output-to-string (str)
3.338+ (loop for l = (read-line file nil nil)
3.339+ while l
3.340+ unless (or (zerop (length l)) (equal (char l 0) #\#))
3.341+ do (push (parse-tmux-command l) (slot-value obj 'commands)))))
3.342+ obj))
3.343+
3.344+;; (describe (find-cfg :tmux))
3.345+
3.346+;;; Format Strings
3.347+(defun format-tmux-string (dst fmt &rest args)
3.348+ (apply #'format dst fmt (mapcar (lambda (a) (format nil "#{~A}" a)) args)))
3.349+
3.350+(defmacro tmux-format (dst fmt &rest args)
3.351+ "Format a tmux string, replacing symbols in ARGS that match a member of
3.352+*TMUX-VARIABLES* with their corresponding lower-case name."
3.353+ `(format-tmux-string ,dst ,fmt
3.354+ ,@(mapcar (lambda (a)
3.355+ (gethash (symbolicate a) *tmux-var-table* a))
3.356+ args)))
3.357+
3.358+(declaim ((vector symbol) *tmux-variables*))
3.359+(defvar *tmux-variables*
3.360+ #(active-window-index ;; Index of active window in session
3.361+ alternate-on ;; 1 if pane is in alternate screen
3.362+ alternate-saved-x ;; Saved cursor X in alternate screen
3.363+ alternate-saved-y ;; Saved cursor Y in alternate screen
3.364+ buffer-created ;; Time buffer created
3.365+ buffer-name ;; Name of buffer
3.366+ buffer-sample ;; Sample of start of buffer
3.367+ buffer-size ;; Size of the specified buffer in bytes
3.368+ client-activity ;; Time client last had activity
3.369+ client-cell-height ;; Height of each client cell in pixels
3.370+ client-cell-width ;; Width of each client cell in pixels
3.371+ client-control-mode ;; 1 if client is in control mode
3.372+ client-created ;; Time client created
3.373+ client-discarded ;; Bytes discarded when client behind
3.374+ client-flags ;; List of client flags
3.375+ client-height ;; Height of client
3.376+ client-key-table ;; Current key table
3.377+ client-last-session ;; Name of the client's last session
3.378+ client-name ;; Name of client
3.379+ client-pid ;; PID of client process
3.380+ client-prefix ;; 1 if prefix key has been pressed
3.381+ client-readonly ;; 1 if client is read-only
3.382+ client-session ;; Name of the client's session
3.383+ client-termfeatures ;; Terminal features of client, if any
3.384+ client-termname ;; Terminal name of client
3.385+ client-termtype ;; Terminal type of client, if available
3.386+ client-tty ;; Pseudo terminal of client
3.387+ client-uid ;; UID of client process
3.388+ client-user ;; User of client process
3.389+ client-utf8 ;; 1 if client supports UTF-8
3.390+ client-width ;; Width of client
3.391+ client-written ;; Bytes written to client
3.392+ command ;; Name of command in use, if any
3.393+ command-list-alias ;; Command alias if listing commands
3.394+ command-list-name ;; Command name if listing commands
3.395+ command-list-usage ;; Command usage if listing commands
3.396+ config-files ;; List of configuration files loaded
3.397+ copy-cursor-line ;; Line the cursor is on in copy mode
3.398+ copy-cursor-word ;; Word under cursor in copy mode
3.399+ copy-cursor-x ;; Cursor X position in copy mode
3.400+ copy-cursor-y ;; Cursor Y position in copy mode
3.401+ current-file ;; Current configuration file
3.402+ cursor-character ;; Character at cursor in pane
3.403+ cursor-flag ;; Pane cursor flag
3.404+ cursor-x ;; Cursor X position in pane
3.405+ cursor-y ;; Cursor Y position in pane
3.406+ history-bytes ;; Number of bytes in window history
3.407+ history-limit ;; Maximum window history lines
3.408+ history-size ;; Size of history in lines
3.409+ hook ;; Name of running hook, if any
3.410+ hook-client ;; Name of client where hook was run, if any
3.411+ hook-pane ;; ID of pane where hook was run, if any
3.412+ hook-session ;; ID of session where hook was run, if any
3.413+ hook-session-name ;; Name of session where hook was run, if any
3.414+ hook-window ;; ID of window where hook was run, if any
3.415+ hook-window-name ;; Name of window where hook was run, if any
3.416+ host ;; H Hostname of local host
3.417+ host-short ;; h Hostname of local host (no domain name)
3.418+ insert-flag ;; Pane insert flag
3.419+ keypad-cursor-flag ;; Pane keypad cursor flag
3.420+ keypad-flag ;; Pane keypad flag
3.421+ last-window-index ;; Index of last window in session
3.422+ line ;; Line number in the list
3.423+ mouse-all-flag ;; Pane mouse all flag
3.424+ mouse-any-flag ;; Pane mouse any flag
3.425+ mouse-button-flag ;; Pane mouse button flag
3.426+ mouse-hyperlink ;; Hyperlink under mouse, if any
3.427+ mouse-line ;; Line under mouse, if any
3.428+ mouse-sgr-flag ;; Pane mouse SGR flag
3.429+ mouse-standard-flag ;; Pane mouse standard flag
3.430+ mouse-status-line ;; Status line on which mouse event took place
3.431+ mouse-status-range ;; Range type or argument of mouse event on status line
3.432+ mouse-utf8-flag ;; Pane mouse UTF-8 flag
3.433+ mouse-word ;; Word under mouse, if any
3.434+ mouse-x ;; Mouse X position, if any
3.435+ mouse-y ;; Mouse Y position, if any
3.436+ next-session-id ;; Unique session ID for next new session
3.437+ origin-flag ;; Pane origin flag
3.438+ pane-active ;; 1 if active pane
3.439+ pane-at-bottom ;; 1 if pane is at the bottom of window
3.440+ pane-at-left ;; 1 if pane is at the left of window
3.441+ pane-at-right ;; 1 if pane is at the right of window
3.442+ pane-at-top ;; 1 if pane is at the top of window
3.443+ pane-bg ;; Pane background colour
3.444+ pane-bottom ;; Bottom of pane
3.445+ pane-current-command ;; Current command if available
3.446+ pane-current-path ;; Current path if available
3.447+ pane-dead ;; 1 if pane is dead
3.448+ pane-dead-signal ;; Exit signal of process in dead pane
3.449+ pane-dead-status ;; Exit status of process in dead pane
3.450+ pane-dead-time ;; Exit time of process in dead pane
3.451+ pane-fg ;; Pane foreground colour
3.452+ pane-format ;; 1 if format is for a pane
3.453+ pane-height ;; Height of pane
3.454+ pane-id ;; D Unique pane ID
3.455+ pane-in-mode ;; 1 if pane is in a mode
3.456+ pane-index ;; P Index of pane
3.457+ pane-input-off ;; 1 if input to pane is disabled
3.458+ pane-last ;; 1 if last pane
3.459+ pane-left ;; Left of pane
3.460+ pane-marked ;; 1 if this is the marked pane
3.461+ pane-marked-set ;; 1 if a marked pane is set
3.462+ pane-mode ;; Name of pane mode, if any
3.463+ pane-path ;; Path of pane (can be set by application)
3.464+ pane-pid ;; PID of first process in pane
3.465+ pane-pipe ;; 1 if pane is being piped
3.466+ pane-right ;; Right of pane
3.467+ pane-search-string ;; Last search string in copy mode
3.468+ pane-start-command ;; Command pane started with
3.469+ pane-start-path ;; Path pane started with
3.470+ pane-synchronized ;; 1 if pane is synchronized
3.471+ pane-tabs ;; Pane tab positions
3.472+ pane-title ;; T Title of pane (can be set by application)
3.473+ pane-top ;; Top of pane
3.474+ pane-tty ;; Pseudo terminal of pane
3.475+ pane-unseen-changes ;; 1 if there were changes in pane while in mode
3.476+ pane-width ;; Width of pane
3.477+ pid ;; Server PID
3.478+ rectangle-toggle ;; 1 if rectangle selection is activated
3.479+ scroll-position ;; Scroll position in copy mode
3.480+ scroll-region-lower ;; Bottom of scroll region in pane
3.481+ scroll-region-upper ;; Top of scroll region in pane
3.482+ search-match ;; Search match if any
3.483+ search-present ;; 1 if search started in copy mode
3.484+ selection-active ;; 1 if selection started and changes with the cursor in copy mode
3.485+ selection-end-x ;; X position of the end of the selection
3.486+ selection-end-y ;; Y position of the end of the selection
3.487+ selection-present ;; 1 if selection started in copy mode
3.488+ selection-start-x ;; X position of the start of the selection
3.489+ selection-start-y ;; Y position of the start of the selection
3.490+ server-sessions ;; Number of sessions
3.491+ session-activity ;; Time of session last activity
3.492+ session-alerts ;; List of window indexes with alerts
3.493+ session-attached ;; Number of clients session is attached to
3.494+ session-attached-list ;; List of clients session is attached to
3.495+ session-created ;; Time session created
3.496+ session-format ;; 1 if format is for a session
3.497+ session-group ;; Name of session group
3.498+ session-group-attached ;; Number of clients sessions in group are attached to
3.499+ session-group-attached-list ;; List of clients sessions in group are attached to
3.500+ session-group-list ;; List of sessions in group
3.501+ session-group-many-attached ;; 1 if multiple clients attached to sessions in group
3.502+ session-group-size ;; Size of session group
3.503+ session-grouped ;; 1 if session in a group
3.504+ session-id ;; Unique session ID
3.505+ session-last-attached ;; Time session last attached
3.506+ session-many-attached ;; 1 if multiple clients attached
3.507+ session-marked ;; 1 if this session contains the marked pane
3.508+ session-name ;; S Name of session
3.509+ session-path ;; Working directory of session
3.510+ session-stack ;; Window indexes in most recent order
3.511+ session-windows ;; Number of windows in session
3.512+ socket-path ;; Server socket path
3.513+ start-time ;; Server start time
3.514+ uid ;; Server UID
3.515+ user ;; Server user
3.516+ version ;; Server version
3.517+ window-active ;; 1 if window active
3.518+ window-active-clients ;; Number of clients viewing this window
3.519+ window-active-clients-list ;; List of clients viewing this window
3.520+ window-active-sessions ;; Number of sessions on which this window is active
3.521+ window-active-sessions-list ;; List of sessions on which this window is active
3.522+ window-activity ;; Time of window last activity
3.523+ window-activity-flag ;; 1 if window has activity
3.524+ window-bell-flag ;; 1 if window has bell
3.525+ window-bigger ;; 1 if window is larger than client
3.526+ window-cell-height ;; Height of each cell in pixels
3.527+ window-cell-width ;; Width of each cell in pixels
3.528+ window-end-flag ;; 1 if window has the highest index
3.529+ window-flags ;; F Window flags with # escaped as ##
3.530+ window-format ;; 1 if format is for a window
3.531+ window-height ;; Height of window
3.532+ window-id ;; Unique window ID
3.533+ window-index ;; I Index of window
3.534+ window-last-flag ;; 1 if window is the last used
3.535+ window-layout ;; Window layout description, ignoring zoomed window panes
3.536+ window-linked ;; 1 if window is linked across sessions
3.537+ window-linked-sessions ;; Number of sessions this window is linked to
3.538+ window-linked-sessions-list ;; List of sessions this window is linked to
3.539+ window-marked-flag ;; 1 if window contains the marked pane
3.540+ window-name ;; W Name of window
3.541+ window-offset-x ;; X offset into window if larger than client
3.542+ window-offset-y ;; Y offset into window if larger than client
3.543+ window-panes ;; Number of panes in window
3.544+ window-raw-flags ;; Window flags with nothing escaped
3.545+ window-silence-flag ;; 1 if window has silence alert
3.546+ window-stack-index ;; Index in session most recent stack
3.547+ window-start-flag ;; 1 if window has the lowest index
3.548+ window-visible-layout ;; Window layout description, respecting zoomed window panes
3.549+ window-width ;; Width of window
3.550+ window-zoomed-flag ;; 1 if window is zoomed
3.551+ wrap-flag ;; Pane wrap flag
3.552+ ;; display-menu vars
3.553+ popup-centre-x Centered in the client
3.554+ popup-centre-y ;; entered in the client
3.555+ popup-height ;; eight of menu or popup
3.556+ popup-mouse-bottom ;; ottom of at the mouse
3.557+ popup-mouse-centre-x ;; orizontal centre at the mouse
3.558+ popup-mouse-centre-y ;; ertical centre at the mouse
3.559+ popup-mouse-top ;; op at the mouse
3.560+ popup-mouse-x ;; ouse X position
3.561+ popup-mouse-y ;; ouse Y position
3.562+ popup-pane-bottom ;; ottom of the pane
3.563+ popup-pane-left ;; eft of the pane
3.564+ popup-pane-right ;; ight of the pane
3.565+ popup-pane-top ;; op of the pane
3.566+ popup-status-line-y ;; bove or below the status line
3.567+ popup-width ;; idth of menu or popup
3.568+ popup-window-status-line-x ;; t the window position in status line
3.569+ popup-window-status-line-y ;; t the status line showing the window
3.570+ ))
3.571+
3.572+(defvar *tmux-variable-names*
3.573+ (coerce
3.574+ (loop for v across *tmux-variables*
3.575+ collect (string-downcase (substitute #\_ #\- (symbol-name v))))
3.576+ '(vector string)))
4.1--- a/lisp/lib/dat/csv.lisp Mon Aug 05 21:57:13 2024 -0400
4.2+++ b/lisp/lib/dat/csv.lisp Tue Aug 06 21:17:24 2024 -0400
4.3@@ -15,6 +15,8 @@
4.4 ;; - buffered reads
4.5 ;; - multithreading
4.6
4.7+;; ref: https://datatracker.ietf.org/doc/html/rfc4180
4.8+
4.9 ;;; Code:
4.10 (in-package :dat/csv)
4.11
4.12@@ -78,6 +80,10 @@
4.13 :external-format external-format)
4.14 (write-csv-stream f table :delimiter delimiter)))
4.15
4.16+(defun write-csv-string (table)
4.17+ (with-output-to-string (str)
4.18+ (write-csv-stream str table)))
4.19+
4.20 (defun parse-csv-string (str &key (delimiter *csv-separator*)) ;; refer RFC4180
4.21 (coerce
4.22 ;; (regexp:split-re "," str)
5.1--- a/lisp/lib/dat/pkg.lisp Mon Aug 05 21:57:13 2024 -0400
5.2+++ b/lisp/lib/dat/pkg.lisp Tue Aug 06 21:17:24 2024 -0400
5.3@@ -41,7 +41,8 @@
5.4 :write-csv-file
5.5 :write-csv-stream
5.6 :read-csv-file-and-sort
5.7- :parse-csv-string))
5.8+ :parse-csv-string
5.9+ #:write-csv-string))
5.10
5.11 (defpackage :dat/toml
5.12 (:use :cl :std :dat/proto :obj/time)
6.1--- a/lisp/lib/obj/cfg.lisp Mon Aug 05 21:57:13 2024 -0400
6.2+++ b/lisp/lib/obj/cfg.lisp Tue Aug 06 21:17:24 2024 -0400
6.3@@ -19,7 +19,7 @@
6.4 ())
6.5
6.6 (defgeneric make-cfg (obj &rest args &key &allow-other-keys))
6.7-(defgeneric find-cfg (kind obj &rest args &key &allow-other-keys))
6.8+(defgeneric find-cfg (obj &rest args &key &allow-other-keys))
6.9 (defgeneric cfg-find (obj key &key &allow-other-keys))
6.10 (defgeneric cfg-get (obj key))
6.11 (defgeneric (setf cfg-get) (obj key val))
7.1--- a/lisp/lib/obj/pkg.lisp Mon Aug 05 21:57:13 2024 -0400
7.2+++ b/lisp/lib/obj/pkg.lisp Tue Aug 06 21:17:24 2024 -0400
7.3@@ -315,7 +315,8 @@
7.4 (:nicknames :cfg)
7.5 (:use :cl :std)
7.6 (:export :cfg :make-cfg :find-cfg
7.7- :cfg-find :cfg-get :defcfg))
7.8+ :cfg-find :cfg-get :defcfg
7.9+ :load-cfg))
7.10
7.11 (defpackage :obj/db
7.12 (:nicknames :db)
7.13@@ -455,7 +456,12 @@
7.14 :register-data-source
7.15 :register-df
7.16 :file-data-path
7.17- :file-data-source))
7.18+ :file-data-source
7.19+ :optimize-query
7.20+ :projection-pushdown-optimizer
7.21+ :extract-columns*
7.22+ :extract-columns
7.23+ :query-vop))
7.24
7.25 (defpackage :obj/secret
7.26 (:nicknames :secret)
8.1--- a/lisp/lib/q/engine.lisp Mon Aug 05 21:57:13 2024 -0400
8.2+++ b/lisp/lib/q/engine.lisp Tue Aug 06 21:17:24 2024 -0400
8.3@@ -18,8 +18,26 @@
8.4
8.5 ;;; Engine
8.6 ;; NOTE 2024-08-04: only slot inherited should be :SCHEMA from DATA-SOURCE. A
8.7-;; QUERY-ENGINE may always act as a source for another engine.
8.8+;; QUERY-ENGINE may always act as a source for another engine (maybe, probably)
8.9 (defclass query-engine (query-planner execution-context data-source)
8.10 ((sources :initarg :sources)
8.11 (parser :initarg :parser :type query-parser)
8.12 (optimizer :initarg :optimizer :type query-optimizer)))
8.13+
8.14+(defgeneric sql (self input)
8.15+ (:documentation "Process sql input and return a DATA-FRAME."))
8.16+
8.17+(defgeneric dql (self input)
8.18+ (:documentation "Process dql input and return a DATA-FRAME."))
8.19+
8.20+(defmethod execute* ((self query-engine) (plan data-frame))
8.21+ (declare (ignore self))
8.22+ (execute plan))
8.23+
8.24+(defmethod optimize-query ((self query-engine) (plan logical-plan))
8.25+ (optimize-query (slot-value self 'query-optimizer) plan))
8.26+
8.27+(defmethod execute* ((self query-engine) (plan logical-plan))
8.28+ (execute
8.29+ (make-physical-plan
8.30+ (optimize-query self plan))))
9.1--- a/lisp/lib/q/pkg.lisp Mon Aug 05 21:57:13 2024 -0400
9.2+++ b/lisp/lib/q/pkg.lisp Tue Aug 06 21:17:24 2024 -0400
9.3@@ -9,7 +9,8 @@
9.4 :query-engine :query-parser
9.5 :*query-engine*
9.6 :*query-dialect*
9.7- :query-dialect-designator))
9.8+ :query-dialect-designator
9.9+ :sql :dql))
9.10
9.11 (defpackage :q/sql
9.12 (:nicknames :sql)
10.1--- a/lisp/lib/q/sql.lisp Mon Aug 05 21:57:13 2024 -0400
10.2+++ b/lisp/lib/q/sql.lisp Tue Aug 06 21:17:24 2024 -0400
10.3@@ -799,7 +799,6 @@
10.4 (slot-value select 'group-by))
10.5 aggregate-expr)))))
10.6
10.7-;; TODO 2024-08-04: fix deadlock
10.8 (defun make-sql-data-frame (select tables)
10.9 (let* ((table (gethash (slot-value select 'table-name)
10.10 tables
11.1--- a/lisp/lib/q/tests/fuzz.lisp Mon Aug 05 21:57:13 2024 -0400
11.2+++ b/lisp/lib/q/tests/fuzz.lisp Tue Aug 06 21:17:24 2024 -0400
11.3@@ -5,7 +5,7 @@
11.4 ;;; Code:
11.5 (in-package :q/tests/fuzz)
11.6
11.7-(defclass query-fuzzer (fuzzer) ())
11.8+(defclass query-fuzzer (fuzzer) (data-source))
11.9
11.10 (defclass sql-fuzzer (query-fuzzer) ())
11.11
12.1--- a/lisp/lib/rt/fuzz.lisp Mon Aug 05 21:57:13 2024 -0400
12.2+++ b/lisp/lib/rt/fuzz.lisp Tue Aug 06 21:17:24 2024 -0400
12.3@@ -2,11 +2,48 @@
12.4
12.5 ;; FUZZER API
12.6
12.7+;;; Commentary:
12.8+
12.9+;;
12.10+;; wiki: https://en.wikipedia.org/wiki/Fuzzing
12.11+
12.12 ;;; Code:
12.13 (in-package :rt/fuzz)
12.14
12.15+(defvar *default-fuzz-generator*
12.16+ (lambda (state)
12.17+ (random most-positive-fixnum state)))
12.18+
12.19 (defclass fuzzer ()
12.20- ((state)))
12.21+ ((state :initform (make-random-state t)
12.22+ :initarg :state
12.23+ :accessor fuzzer-state)
12.24+ (generator :initform *default-fuzz-generator*
12.25+ :initarg :generator
12.26+ :type (function (state))
12.27+ :accessor fuzz-generator))
12.28+ (:documentation "An object which provides invalid, unexpected or random data as inputs to some
12.29+program."))
12.30
12.31-(defgeneric fuzz (self &optional n))
12.32-(defgeneric fuzz* (self &key &allow-other-keys))
12.33+(defgeneric fuzz (self &key &allow-other-keys)
12.34+ (:method ((self fuzzer) &key count)
12.35+ (if count
12.36+ (let ((ret))
12.37+ (dotimes (i count ret)
12.38+ (push (funcall (the function (fuzz-generator self)) (fuzzer-state self)) ret)))
12.39+ (funcall (the function (fuzz-generator self)) (fuzzer-state self)))))
12.40+
12.41+(defgeneric fuzz* (state generator &key &allow-other-keys)
12.42+ (:method ((state list) (generator function) &key (count 1))
12.43+ (let ((ret))
12.44+ (dotimes (i count ret)
12.45+ (push (funcall generator state) ret))))
12.46+ (:method ((state vector) (generator function) &key (count 1))
12.47+ (let ((ret (make-array count :fill-pointer 0)))
12.48+ (dotimes (i count ret)
12.49+ (setf (aref ret i) (funcall generator state)))))
12.50+ (:method ((state hash-table) (generator function) &key (count 1))
12.51+ (let ((ret (make-hash-table)))
12.52+ (dotimes (i count ret)
12.53+ (destructuring-bind (k v) (funcall generator state)
12.54+ (setf (gethash k ret) v))))))