changelog shortlog graph tags branches files raw help

Mercurial > core / changeset: tmux work, fuzzer

changeset 581: d3e2829521a3
parent 580: 571685ae64f1
child 582: 568c39371122
author: Richard Westhaver <ellis@rwest.io>
date: Tue, 06 Aug 2024 21:17:24 -0400
files: lisp/lib/cli/cli.asd lisp/lib/cli/tools/pkg.lisp lisp/lib/cli/tools/tmux.lisp lisp/lib/dat/csv.lisp lisp/lib/dat/pkg.lisp lisp/lib/obj/cfg.lisp lisp/lib/obj/pkg.lisp lisp/lib/q/engine.lisp lisp/lib/q/pkg.lisp lisp/lib/q/sql.lisp lisp/lib/q/tests/fuzz.lisp lisp/lib/rt/fuzz.lisp
description: tmux work, fuzzer
     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))))))