# HG changeset patch # User Steve Losh # Date 1643730776 18000 # Node ID d7650a70ef267bb82178e241f324492fc83627ad # Parent b7239c572353b66c4057a6da74072fd189a2df9b# Parent 958358268b7ec03db1aecf8433b6bf2fdc2efc5e Merge diff -r b7239c572353 -r d7650a70ef26 bin/ecl-vlime --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/bin/ecl-vlime Tue Feb 01 10:52:56 2022 -0500 @@ -0,0 +1,4 @@ +#!/usr/bin/env bash + +set -e +ecl --eval "(load \"~/src/dotfiles/vim/bundle/vlime/lisp/start-vlime.lisp\")" "$@" diff -r b7239c572353 -r d7650a70ef26 bin/external-ip --- a/bin/external-ip Tue Feb 01 10:49:39 2022 -0500 +++ b/bin/external-ip Tue Feb 01 10:52:56 2022 -0500 @@ -2,5 +2,7 @@ set -euo pipefail -dig @resolver1.opendns.com ANY myip.opendns.com +short +#dig @resolver1.opendns.com ANY myip.opendns.com +short +curl whatismyip.stevelosh.com + diff -r b7239c572353 -r d7650a70ef26 lisp/parsre.lisp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lisp/parsre.lisp Tue Feb 01 10:52:56 2022 -0500 @@ -0,0 +1,227 @@ +(eval-when (:compile-toplevel :load-toplevel :execute) + (ql:quickload '(:adopt :cl-ppcre :iterate :with-user-abort + :jarl :conserve :losh) + :silent t)) + +(defpackage :parsre + (:use :cl :iterate) + (:export :toplevel :*ui*)) + +(in-package :parsre) + +;;;; Configuration ------------------------------------------------------------ +(defparameter *output-format* :text) +(defparameter *case-sensitive* t) + + +;;;; Errors ------------------------------------------------------------------- +(define-condition user-error (error) ()) + +(define-condition missing-regex (user-error) () + (:report "A regular expression is required.")) + +(define-condition missing-registers (user-error) () + (:report "Invalid regex, at least one named register is required.")) + +(define-condition anonymous-register (user-error) () + (:report "Invalid regex, anonymous registers are not supported. Use non-capturing groups (?:…) if you need grouping but not capturing.")) + +(define-condition malformed-regex (user-error) + ((underlying-error :initarg :underlying-error)) + (:report (lambda (c s) + (format s "Invalid regex: ~A" (slot-value c 'underlying-error))))) + + +;;;; Functionality ------------------------------------------------------------ +(defgeneric header (format names)) +(defmethod header (format names) nil) +(defmethod header ((format (eql :csv)) names) (conserve:write-row names)) + + +(defmethod output (format names values)) + +(defmethod output ((format (eql :text)) names values) + (iterate (for name :in names) + (for value :in values) + (format t "~A: ~A~%" name value)) + (terpri)) + +(defmethod output ((format (eql :json)) names values) + (jarl:print (alexandria:alist-hash-table (mapcar #'cons names values) :test #'equal)) + (terpri)) + +(defmethod output ((format (eql :csv)) names values) + (declare (ignore names)) + (conserve:write-row values)) + + +(defun register-values (string register-starts register-ends) + (iterate + (for start :in-vector register-starts) + (for end :in-vector register-ends) + (collect (subseq string start end)))) + +(defun run%% (scanner register-names string) + (iterate (with start = 0) + (for (values ms me rs re) = (ppcre:scan scanner string :start start)) + (while ms) + (output *output-format* register-names (register-values string rs re)) + (setf start (max (1+ start) me)))) + +(defun run% (scanner register-names stream) + (iterate (for line :in-stream stream :using #'read-line) + (run%% scanner register-names line) + (force-output))) + + +(defun make-scanner (pattern) + (handler-case + (ppcre:create-scanner pattern + :case-insensitive-mode (not *case-sensitive*) + :single-line-mode t) + (ppcre:ppcre-syntax-error (c) (error 'malformed-regex :underlying-error c)))) + +(defun run (pattern paths) + (let ((ppcre:*allow-named-registers* t) + (ppcre:*use-bmh-matchers* t) + (paths (or paths '("-")))) + (multiple-value-bind (scanner register-names) (make-scanner pattern) + (cond ((null register-names) (error 'missing-registers)) + ((member nil register-names) (error 'anonymous-register))) + (header *output-format* register-names) + (dolist (path paths) + (if (string= "-" path) + (run% scanner register-names *standard-input*) + (with-open-file (stream path :direction :input) + (run% scanner register-names stream))))))) + + +;;;; User Interface ----------------------------------------------------------- +(defparameter *examples* + '(("Parse some web service logs:" . + "parsre '^(?\\\\S+) (?INFO|WARN|ERROR|DEBUG) (?.*)$'") + ("Parse wordcount report into JSON:" . + "wc **.lisp | parsre --json '^ *(?\\\\d+) +(?\\\\d+) +(?\\\\d+) +(?.+)$'"))) + + +(defparameter *option/help* + (adopt:make-option 'help + :help "Display help and exit." + :long "help" + :short #\h + :reduce (constantly t))) + +(defparameter *option/version* + (adopt:make-option 'version + :help "Display version information and exit." + :long "version" + :reduce (constantly t))) + +(adopt:defparameters (*option/debug* *option/no-debug*) + (adopt:make-boolean-options 'debug + :long "debug" + :short #\d + :help "Enable the Lisp debugger." + :help-no "Disable the Lisp debugger (default).")) + +(adopt:defparameters (*option/profile* *option/no-profile*) + (adopt:make-boolean-options 'profile + :long "profile" + :help "Profile the run and write results to lisp.prof." + :help-no "Do not profile (default).")) + +(adopt:defparameters (*option/matching/ignore-case* *option/matching/no-ignore-case*) + (adopt:make-boolean-options 'ignore-case + :long "ignore-case" + :short #\i + :help "Ignore case (i.e. case-insensitive)." + :help-no "Do not ignore case (i.e. case-sensitive) (default)." + :initial-value nil)) + +(defparameter *option/output-format/text* + (adopt:make-option 'output-format/text + :result-key 'output-format + :help "Output results as text (default)." + :long "text" + :short #\t + :initial-value :text + :reduce (constantly :text))) + +(defparameter *option/output-format/json* + (adopt:make-option 'output-format/json + :result-key 'output-format + :help "Output results as JSON." + :long "json" + :short #\j + :reduce (constantly :json))) + +(defparameter *option/output-format/csv* + (adopt:make-option 'output-format/csv + :result-key 'output-format + :help "Output results as CSV." + :long "csv" + :short #\c + :reduce (constantly :csv))) + + +(adopt:define-string *help-text* + "Parsre takes a Perl-compatible regular expression, matches it against input, ~ + and outputs the expression's registers in a variety of formats.~@ + ~@ + The regular expression will be matched against the input line-by-line. ~ + Multiple matches per line are supported.~@ + ~@ + Registers can be named or anonymous. Anonymous registers will be named ~ + arbitrarily (the scheme may change in the future).") + + +(defparameter *ui* + (adopt:make-interface + :name "parsre" + :usage "[OPTIONS] REGEX [FILE...]" + :summary "almost a parser" + :help *help-text* + :examples *examples* + :contents (list *option/help* + *option/version* + (adopt:make-group + 'matching-options + :title "Matching Options" + :options (list *option/matching/ignore-case* + *option/matching/no-ignore-case*)) + (adopt:make-group + 'output-options + :title "Output Options" + :options (list *option/output-format/text* + *option/output-format/json* + *option/output-format/csv*)) + (adopt:make-group + 'debugging-options + :title "Debugging Options" + :options (list *option/debug* + *option/no-debug* + *option/profile* + *option/no-profile*))))) + +(defun configure (options) + (setf *output-format* (gethash 'output-format options) + *case-sensitive* (not (gethash 'ignore-case options))) + (values)) + +(defun toplevel () + (sb-ext:disable-debugger) + (multiple-value-bind (arguments options) (adopt:parse-options-or-exit *ui*) + (when (gethash 'debug options) + (sb-ext:enable-debugger)) + (handler-case + (with-user-abort:with-user-abort + (cond + ((gethash 'help options) (adopt:print-help-and-exit *ui*)) + ((null arguments) (error 'missing-regex)) + (t (destructuring-bind (pattern . files) arguments + (configure options) + (if (gethash 'profile options) + (losh:profile (run pattern files)) + (run pattern files)))))) + (with-user-abort:user-abort () (adopt:exit 130)) + (user-error (e) (adopt:print-error-and-exit e))))) diff -r b7239c572353 -r d7650a70ef26 stumpwmrc --- a/stumpwmrc Tue Feb 01 10:49:39 2022 -0500 +++ b/stumpwmrc Tue Feb 01 10:52:56 2022 -0500 @@ -1,7 +1,7 @@ (in-package :stumpwm-user) +(shadow :window) -(ql:quickload '(:losh :split-sequence :alexandria :parse-number :str :cl-ppcre :bordeaux-threads) :silent t) -(shadow 'window) +(ql:quickload '(:losh :split-sequence :alexandria :parse-number :str :cl-ppcre :bordeaux-threads :jarl) :silent t) (use-package :losh) @@ -387,23 +387,6 @@ (defcommand describe-window () () (show-window-properties)) -(defcommand unfuck-zoom-link () () - (let ((url (pbpaste))) - (ppcre:register-groups-bind - (meeting-id meeting-pass) - ("^https://[a-zA-Z0-9]+[.]zoom[.]us/j/(\\d+)[?]pwd=([A-Za-z0-9]+)$" url) - (pbcopy meeting-id) - (message "Zoom meeting ID copied.") - (bt:make-thread (lambda () - (sleep 3) - (pbcopy meeting-pass) - (message "Zoom meeting password copied.") - (sleep 5) - (pbcopy "")) - :name "Zoom Link Defuckulator") - (return-from unfuck-zoom-link)) - (message "Clipboard doesn't seem to be a Zoom link."))) - (defcommand rain () () (message (run-shell-command "weather -H 36" t))) @@ -585,8 +568,7 @@ ("H-C" "clear-clipboard-history") ("H-u" "generate-random-uuid") ("H-U" "bee-movie-script") - ("M-H-u" "urlize-jira-issue") - ("H-Z" "unfuck-zoom-link")) + ("M-H-u" "urlize-jira-issue")) (define-top-keys ;; movement ("H-h" "move-focus* left") @@ -710,6 +692,57 @@ ("s-v" . "C-v")))) +;;;; Sensors ------------------------------------------------------------------ +(defun ? (obj &rest keys) + (if (null keys) + obj + (apply #'? (etypecase obj + (hash-table (gethash (first keys) obj))) + (rest keys)))) + +(defun parse-sensors () + ;; sensors -j is stupid and will output errors before the actual output on + ;; standard out, instead of putting them on standard err like a reasonable + ;; program, e.g.: + ;; + ;; ERROR: Can't get value of subfeature temp1_input: Can't read + ;; { + ;; "iwlwifi_1-virtual-0":{ … }, + ;; … + ;; + ;; So we'll have to drop the `ERROR` lines before we can get to the actual + ;; goddamn JSON. UNIX programs are so great. + (let ((s (losh:sh '("sensors" "-j") :result-type 'stream))) + (loop :while (char= #\E (peek-char nil s)) :do (read-line s)) + (jarl:read t s))) + +(defparameter *sensors-refresh-delay* 5.0 "How long between sensor refreshes (in seconds).") +(defparameter *sensors-next-refresh* nil) +(defparameter *sensors-cache* nil) + +(defun sensors% (&aux (sensors (parse-sensors))) + (hostcase + (:ouroboros (format nil "[CPU ~D°C] [GPU ~D°C ~D°C ~D°C]" + (round (? sensors "nct6779-isa-0290" "CPUTIN" "temp2_input")) + (round (? sensors "amdgpu-pci-4500" "edge" "temp1_input")) + (round (? sensors "amdgpu-pci-4500" "junction" "temp2_input")) + (round (? sensors "amdgpu-pci-4500" "mem" "temp3_input")))) + (t "?"))) + +(defun sensors (&aux (now (get-internal-real-time))) + (if (or (null *sensors-next-refresh*) + (>= now *sensors-next-refresh*)) + (setf *sensors-next-refresh* (+ now (* internal-time-units-per-second *sensors-refresh-delay*)) + *sensors-cache* (sensors%)) + *sensors-cache*)) + +(defun sensors-modeline (ml) + (declare (ignore ml)) + (sensors)) + +(add-screen-mode-line-formatter #\S #'sensors-modeline) + + ;;;; Modeline ----------------------------------------------------------------- (load-module "battery-portable") (load-module "cpu") @@ -730,7 +763,7 @@ "^[~A~3D%^]" cpu::*cpu-modeline-fmt* - "[%c] [%t] [%f]" + "[%c] [%f]" mem::*mem-modeline-fmt* "%b" @@ -752,8 +785,8 @@ (:eval (princ-to-string (brightness))) "%)"))) - ;; cpu, time, tray - (list " (CPU %C) (MEM %M) %d %T"))) + ;; temp, cpu, mem, time, tray + (list "(TEMP %S) (CPU %C) (MEM %M) %d %T"))) (setf *mode-line-timeout* 10) (setf *mode-line-background-color* "#111111") diff -r b7239c572353 -r d7650a70ef26 weechat/alias.conf --- a/weechat/alias.conf Tue Feb 01 10:49:39 2022 -0500 +++ b/weechat/alias.conf Tue Feb 01 10:52:56 2022 -0500 @@ -4,7 +4,7 @@ # WARNING: It is NOT recommended to edit this file by hand, # especially if WeeChat is running. # -# Use commands like /set or /fset to change settings in WeeChat. +# Use /set or similar command to change settings in WeeChat. # # For more info, see: https://weechat.org/doc/quickstart # diff -r b7239c572353 -r d7650a70ef26 weechat/autosort.conf --- a/weechat/autosort.conf Tue Feb 01 10:49:39 2022 -0500 +++ b/weechat/autosort.conf Tue Feb 01 10:52:56 2022 -0500 @@ -4,7 +4,7 @@ # WARNING: It is NOT recommended to edit this file by hand, # especially if WeeChat is running. # -# Use commands like /set or /fset to change settings in WeeChat. +# Use /set or similar command to change settings in WeeChat. # # For more info, see: https://weechat.org/doc/quickstart # diff -r b7239c572353 -r d7650a70ef26 weechat/buflist.conf --- a/weechat/buflist.conf Tue Feb 01 10:49:39 2022 -0500 +++ b/weechat/buflist.conf Tue Feb 01 10:52:56 2022 -0500 @@ -4,7 +4,7 @@ # WARNING: It is NOT recommended to edit this file by hand, # especially if WeeChat is running. # -# Use commands like /set or /fset to change settings in WeeChat. +# Use /set or similar command to change settings in WeeChat. # # For more info, see: https://weechat.org/doc/quickstart # @@ -21,7 +21,6 @@ nick_prefix_empty = on signals_refresh = "" sort = "number,-active" -use_items = 1 [format] buffer = "${format_number}${indent}${format_nick_prefix}${color_hotlist}${format_name}" @@ -38,4 +37,3 @@ name = "${name}" nick_prefix = "${color_nick_prefix}${nick_prefix}" number = "${color:green}${number}${if:${number_displayed}?.: }" -tls_version = " ${color:default}(${if:${tls_version}==TLS1.3?${color:green}:${if:${tls_version}==TLS1.2?${color:yellow}:${color:red}}}${translate:${tls_version}}${color:default})" diff -r b7239c572353 -r d7650a70ef26 weechat/charset.conf --- a/weechat/charset.conf Tue Feb 01 10:49:39 2022 -0500 +++ b/weechat/charset.conf Tue Feb 01 10:52:56 2022 -0500 @@ -4,7 +4,7 @@ # WARNING: It is NOT recommended to edit this file by hand, # especially if WeeChat is running. # -# Use commands like /set or /fset to change settings in WeeChat. +# Use /set or similar command to change settings in WeeChat. # # For more info, see: https://weechat.org/doc/quickstart # diff -r b7239c572353 -r d7650a70ef26 weechat/exec.conf --- a/weechat/exec.conf Tue Feb 01 10:49:39 2022 -0500 +++ b/weechat/exec.conf Tue Feb 01 10:52:56 2022 -0500 @@ -4,7 +4,7 @@ # WARNING: It is NOT recommended to edit this file by hand, # especially if WeeChat is running. # -# Use commands like /set or /fset to change settings in WeeChat. +# Use /set or similar command to change settings in WeeChat. # # For more info, see: https://weechat.org/doc/quickstart # @@ -12,7 +12,6 @@ [command] default_options = "" purge_delay = 0 -shell = "${env:SHELL}" [color] flag_finished = lightred diff -r b7239c572353 -r d7650a70ef26 weechat/fifo.conf --- a/weechat/fifo.conf Tue Feb 01 10:49:39 2022 -0500 +++ b/weechat/fifo.conf Tue Feb 01 10:52:56 2022 -0500 @@ -4,7 +4,7 @@ # WARNING: It is NOT recommended to edit this file by hand, # especially if WeeChat is running. # -# Use commands like /set or /fset to change settings in WeeChat. +# Use /set or similar command to change settings in WeeChat. # # For more info, see: https://weechat.org/doc/quickstart # diff -r b7239c572353 -r d7650a70ef26 weechat/fset.conf --- a/weechat/fset.conf Tue Feb 01 10:49:39 2022 -0500 +++ b/weechat/fset.conf Tue Feb 01 10:52:56 2022 -0500 @@ -4,13 +4,12 @@ # WARNING: It is NOT recommended to edit this file by hand, # especially if WeeChat is running. # -# Use commands like /set or /fset to change settings in WeeChat. +# Use /set or similar command to change settings in WeeChat. # # For more info, see: https://weechat.org/doc/quickstart # [look] -auto_refresh = "*" auto_unmark = off condition_catch_set = "${count} >= 1" export_help_default = on diff -r b7239c572353 -r d7650a70ef26 weechat/logger.conf --- a/weechat/logger.conf Tue Feb 01 10:49:39 2022 -0500 +++ b/weechat/logger.conf Tue Feb 01 10:52:56 2022 -0500 @@ -4,7 +4,7 @@ # WARNING: It is NOT recommended to edit this file by hand, # especially if WeeChat is running. # -# Use commands like /set or /fset to change settings in WeeChat. +# Use /set or similar command to change settings in WeeChat. # # For more info, see: https://weechat.org/doc/quickstart # @@ -19,7 +19,6 @@ [file] auto_log = on -color_lines = off flush_delay = 120 fsync = off info_lines = off diff -r b7239c572353 -r d7650a70ef26 weechat/python.conf --- a/weechat/python.conf Tue Feb 01 10:49:39 2022 -0500 +++ b/weechat/python.conf Tue Feb 01 10:52:56 2022 -0500 @@ -4,7 +4,7 @@ # WARNING: It is NOT recommended to edit this file by hand, # especially if WeeChat is running. # -# Use commands like /set or /fset to change settings in WeeChat. +# Use /set or similar command to change settings in WeeChat. # # For more info, see: https://weechat.org/doc/quickstart # diff -r b7239c572353 -r d7650a70ef26 weechat/relay.conf --- a/weechat/relay.conf Tue Feb 01 10:49:39 2022 -0500 +++ b/weechat/relay.conf Tue Feb 01 10:52:56 2022 -0500 @@ -4,7 +4,7 @@ # WARNING: It is NOT recommended to edit this file by hand, # especially if WeeChat is running. # -# Use commands like /set or /fset to change settings in WeeChat. +# Use /set or similar command to change settings in WeeChat. # # For more info, see: https://weechat.org/doc/quickstart # @@ -27,20 +27,14 @@ [network] allow_empty_password = off allowed_ips = "" -auth_timeout = 60 bind_address = "" clients_purge_delay = 0 compression_level = 6 ipv6 = on max_clients = 5 -nonce_size = 16 password = "" -password_hash_algo = "*" -password_hash_iterations = 100000 ssl_cert_key = "%h/ssl/relay.pem" ssl_priorities = "NORMAL:-VERS-SSL3.0" -totp_secret = "" -totp_window = 0 websocket_allowed_origins = "" [irc] @@ -51,9 +45,4 @@ backlog_tags = "irc_privmsg" backlog_time_format = "[%H:%M] " -[weechat] -commands = "" - [port] - -[path] diff -r b7239c572353 -r d7650a70ef26 weechat/script.conf --- a/weechat/script.conf Tue Feb 01 10:49:39 2022 -0500 +++ b/weechat/script.conf Tue Feb 01 10:52:56 2022 -0500 @@ -4,7 +4,7 @@ # WARNING: It is NOT recommended to edit this file by hand, # especially if WeeChat is running. # -# Use commands like /set or /fset to change settings in WeeChat. +# Use /set or similar command to change settings in WeeChat. # # For more info, see: https://weechat.org/doc/quickstart # @@ -50,7 +50,6 @@ [scripts] autoload = on cache_expire = 60 -download_enabled = on download_timeout = 30 hold = "" path = "%h/script" diff -r b7239c572353 -r d7650a70ef26 weechat/trigger.conf --- a/weechat/trigger.conf Tue Feb 01 10:49:39 2022 -0500 +++ b/weechat/trigger.conf Tue Feb 01 10:52:56 2022 -0500 @@ -4,7 +4,7 @@ # WARNING: It is NOT recommended to edit this file by hand, # especially if WeeChat is running. # -# Use commands like /set or /fset to change settings in WeeChat. +# Use /set or similar command to change settings in WeeChat. # # For more info, see: https://weechat.org/doc/quickstart # diff -r b7239c572353 -r d7650a70ef26 weechat/urlgrab.conf --- a/weechat/urlgrab.conf Tue Feb 01 10:49:39 2022 -0500 +++ b/weechat/urlgrab.conf Tue Feb 01 10:52:56 2022 -0500 @@ -4,7 +4,7 @@ # WARNING: It is NOT recommended to edit this file by hand, # especially if WeeChat is running. # -# Use commands like /set or /fset to change settings in WeeChat. +# Use /set or similar command to change settings in WeeChat. # # For more info, see: https://weechat.org/doc/quickstart # diff -r b7239c572353 -r d7650a70ef26 weechat/xfer.conf --- a/weechat/xfer.conf Tue Feb 01 10:49:39 2022 -0500 +++ b/weechat/xfer.conf Tue Feb 01 10:52:56 2022 -0500 @@ -4,7 +4,7 @@ # WARNING: It is NOT recommended to edit this file by hand, # especially if WeeChat is running. # -# Use commands like /set or /fset to change settings in WeeChat. +# Use /set or similar command to change settings in WeeChat. # # For more info, see: https://weechat.org/doc/quickstart # @@ -31,8 +31,7 @@ own_ip = "" port_range = "" send_ack = on -speed_limit_recv = 0 -speed_limit_send = 0 +speed_limit = 0 timeout = 300 [file] @@ -44,6 +43,5 @@ auto_resume = on convert_spaces = on download_path = "%h/xfer" -download_temporary_suffix = ".part" upload_path = "~" use_nick_in_filename = on