;; tinmop: a multiprotocol client ;; Copyright © cage ;; This program is free software: you can redistribute it and/or modify ;; it under the terms of the GNU General Public License as published by ;; the Free Software Foundation, either version 3 of the License, or ;; (at your option) any later version. ;; This program is distributed in the hope that it will be useful, ;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;; GNU General Public License for more details. ;; You should have received a copy of the GNU General Public License ;; along with this program. ;; If not, see [[http://www.gnu.org/licenses/][http://www.gnu.org/licenses/]]. (in-package :command-line) (defun print-version () (format t (_ "~a version ~a~%") +program-name+ +program-version+)) (define-constant +start-server-command-line+ #\S :test #'char=) (eval-when (:compile-toplevel :load-toplevel :execute) (defun options () `((:name :help :description (_ "Print help and exit.") :short #\h :long "help") (:name :version :description (_ "Print program information and exit.") :short #\v :long "version") (:name :folder :description (_ "Starting folder") :short #\f :arg-parser #'identity :meta-var (_ "FOLDER-NAME") :long "folder") (:name :timeline :description (_ "Starting timeline.") :short #\t :meta-var (_ "TIMELINE-NAME") :arg-parser #'identity :long "timeline") (:name :update-timeline :description (_ "Update timeline.") :short #\u :long "update-timeline") (:name :reset-timeline-pagination :description (_ "Reset the timeline pagination.") :short #\R :long "reset-timeline-pagination") (:name :check-follows-requests :description (_ "Check follows requests.") :short #\c :long "check-follows-requests") (:name :execute :description (_ "Execute script.") :short #\e :arg-parser #'identity :meta-var (_ "SCRIPT-FILE") :long "execute-script") (:name :notify-mentions :description (_ "Notify messages that mentions the user.") :short #\m :long "notify-mentions") (:name :open-net-address :description (_ "Open net address.") :short #\o :arg-parser #'identity :long "open-net-address") (:name :gemini-full-screen-mode :description (_ "Start as gemini client only.") :short #\G :long "gemini-client-only") (:name :gemini-gui :description (_ "Start as gemini gui client only.") :short #\U :long "gemini-gui-client-only") (:name :gemini-gui-server :description (_ "Start as gemini gui server only.") :short ,+start-server-command-line+ :long "gemini-gui-server-only") (:name :load-module :description (_ "Load a module.") :short #\M :meta-var (_ "MODULE-FILE") :arg-parser #'identity :long "load-module") (:name :fediverse-account :description (_ "Specify a fediverse user account (format: user-name@server-name).") :meta-var (_ "FEDIVERSE-ACCOUNT") :arg-parser #'identity :short #\F :long "fediverse-account") (:name :print-lisp-dependencies :description (_ "Download lisp libraries (useful for packaging only).") :short #\X :long "lisp-dependencies-uris") (:name :start-dummy-server :description (_ "Start a dummy sever, just useful for debugging.") :long "start-dummy-server") (:name :bash-complete :description (_ "Complete command line switches (for bash complation only).") :long "bash-complete")))) (defmacro gen-opts () `(opts:define-opts ,@(options))) (defparameter *start-folder* nil) (defparameter *start-timeline* nil) (defparameter *update-timeline* nil) (defparameter *script-file* nil) (defparameter *module-file* nil) (defparameter *check-follow-requests* nil) (defparameter *reset-timeline-pagination* nil) (defparameter *notify-mentions* nil) (defparameter *net-address* nil) (defparameter *update-timeline-climb-message-tree* nil) (defparameter *gemini-full-screen-mode* nil) (defparameter *print-lisp-dependencies* nil) (defparameter *rpc-server-mode* nil) (defparameter *rpc-client-mode* nil) (defparameter *start-dummy-server* nil) (defparameter *fediverse-account* nil) (defun exit-on-error (e) (format *error-output* "~a~%" e) (os-utils:exit-program 1)) (defmacro set-option-variable (options option-name option-variable) (with-gensyms (option-value) `(alexandria:when-let ((,option-value (getf ,options ,option-name))) (setf ,option-variable ,option-value)))) (defun complete () (flet ((write-shell-array (sequence) (write-sequence (text-utils:join-with-strings sequence " ") *standard-output*)) (build-options (all-options switch-prefix key) (remove-if (lambda (a) (string= a switch-prefix)) (mapcar (lambda (a) (format nil "~a~a" switch-prefix (getf a key ""))) all-options)))) (let* ((all-options (options)) (long-options (build-options all-options "--" :long)) (short-options (build-options all-options "-" :short)) (options (nconc long-options short-options)) (words (text-utils:split-words (os-utils:getenv "COMP_WORDS"))) (words-index (ignore-errors (parse-integer (os-utils:getenv "COMP_CWORD")))) (command-line (os-utils:getenv "COMP_LINE"))) (declare (ignore command-line)) (when (and words words-index) (if (< words-index (length words)) (let ((matched (sort (remove-if-not (lambda (a) (cl-ppcre:scan (strcat "^" (elt words words-index)) a)) options) (lambda (a b) (< (length a) (length b)))))) (if matched (progn (write-shell-array matched)) (write-shell-array options))) (write-shell-array options)))))) (defun fediverse-account-parameters () (when-let ((splitted (cl-ppcre:split +fediverse-account-name-server-separator+ *fediverse-account*))) (values (elt splitted 0) (elt splitted 1)))) (defun manage-opts () (handler-bind ((opts:unknown-option #'exit-on-error) (opts:missing-arg #'exit-on-error) (opts:missing-required-option #'exit-on-error)) (gen-opts) (let ((options (opts:get-opts))) (when (getf options :bash-complete) (complete) (os-utils:exit-program)) (when (getf options :help) (print-version) (opts:describe :usage-of +program-name+ :usage-of-label (_ "Usage") :available-options-label (_ "Available options")) (os-utils:exit-program)) (when (getf options :version) (print-version) (os-utils:exit-program)) (set-option-variable options :gemini-gui-server *rpc-server-mode*) (set-option-variable options :gemini-gui *rpc-client-mode*) (set-option-variable options :folder *start-folder*) (set-option-variable options :open-net-address *net-address*) (set-option-variable options :timeline *start-timeline*) (set-option-variable options :reset-timeline-pagination *reset-timeline-pagination*) (set-option-variable options :update-timeline *update-timeline*) (set-option-variable options :execute *script-file*) (set-option-variable options :load-module *module-file*) (set-option-variable options :fediverse-account *fediverse-account*) (set-option-variable options :check-follows-requests *check-follow-requests*) (set-option-variable options :gemini-full-screen-mode *gemini-full-screen-mode*) (set-option-variable options :notify-mentions *notify-mentions*) (set-option-variable options :print-lisp-dependencies *print-lisp-dependencies*) (set-option-variable options :start-dummy-server *start-dummy-server*))))