aboutsummaryrefslogtreecommitdiff
path: root/src/lib.lisp
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib.lisp')
-rw-r--r--src/lib.lisp117
1 files changed, 117 insertions, 0 deletions
diff --git a/src/lib.lisp b/src/lib.lisp
new file mode 100644
index 0000000..20f75ea
--- /dev/null
+++ b/src/lib.lisp
@@ -0,0 +1,117 @@
+;;;; main.lisp -- oneliners.cli entrypoint
+
+(defpackage oneliners.cli
+ (:use :cl)
+ (:local-nicknames (#:api #:oneliners.api-client)))
+(in-package :oneliners.cli)
+
+;;; CLI OPTIONS
+
+;; (opts:define-opts
+;; (:name :add
+;; :description "Intaractively add a oneliner to the a wiki."
+;; :long "add")
+;; (:name :tags
+;; :description "A comma separated list of tags to filter search results."
+;; :short #\t
+;; :long "tags"
+;; :arg-parser #'identity
+;; :meta-var "'T1, T2, ...'")
+;; (:name :limit
+;; :description "An integer. The maximum number of results to return."
+;; :short #\l
+;; :long "limit"
+;; :meta-var "N"
+;; :default 10
+;; :arg-parser #'parse-integer)
+;; (:name :edit
+;; :description "An integer, a result number. Interactively edit af command."
+;; :long "edit"
+;; :meta-var "RESULT"
+;; :arg-parser #'parse-integer)
+;; (:name :not-flagged
+;; :description "Filter flagged oneliners from the search results"
+;; :long "not-flagged"))
+
+(defparameter +help-suffix+
+ "Unless RESULT is an integer, search for oneliners that involve each command in COMMANDS.
+E.g.
+ # search for oneliners involving both 'find' and 'grep'
+ ol find grep
+
+Otherwise, when RESULT is an integer, run the oneliner with index RESULT from the most
+recent search command, and supply ARGS to that oneliner, if provided.
+E.g.
+ # run the third result from the last search with arguments foo and bar
+ ol 3 foo bar")
+
+;; (defun help-text ()
+;; (opts:describe :prefix "Oneliners Wiki Command Line Tool"
+;; :args "[[RESULT ARGS | COMMANDS]"
+;; :usage-of "ol"
+;; :suffix +help-suffix+))
+
+;;; CONFIG AND RESULTS FILE LOCATIONS
+
+(defun config-file ()
+ (merge-pathnames ".config/oneliners.config" (user-homedir-pathname) ))
+
+(defun last-search-file ()
+ (merge-pathnames ".last_oneliners_search" (user-homedir-pathname)))
+
+;;; RUNNING COMMANDS
+
+(defun parent-process-name ()
+ "Prints the name of the parent process of the current process."
+ (let ((ppidfile (format nil "/proc/~a/status" (osicat-posix:getppid))))
+ (first (last
+ (ppcre:split "\\s"
+ (with-open-file (input ppidfile)
+ (read-line input)))))))
+
+(defmacro wait-until ((&key (timeout 1) (poll-every 0.01)) &body check)
+ "Run CHECK every POLL-EVERY seconds until either TIMEOUT seconds
+have passed or CHECK returns non-nil."
+ (let ((clockvar (gensym))
+ (var (gensym)))
+ `(loop
+ for ,clockvar from 0 by ,poll-every to ,timeout
+ for ,var = (progn ,@check)
+ when ,var
+ return ,var
+ do (sleep ,poll-every))))
+
+(defun run-with-shell
+ (command
+ &key
+ (shell-name (parent-process-name))
+ (await-output-p 0.8)
+ (output-stream *standard-output*))
+ "run COMMAND, a string, in a fresh shell environment, initialized
+with SHELL-NAME. The output from the command read line by line and is
+printed to OUTPUT-STREAM. "
+ (let ((shell
+ (uiop:launch-program shell-name :input :stream :output :stream)))
+ (symbol-macrolet ((shell-input (uiop:process-info-input shell))
+ (shell-output (uiop:process-info-output shell)))
+ (write-line command shell-input)
+ (finish-output shell-input)
+ (when await-output-p
+ (wait-until (:timeout await-output-p :poll-every 0.005)
+ (listen shell-output))
+ (loop while (listen shell-output)
+ do (princ (read-line shell-output) output-stream)
+ (terpri output-stream))))))
+
+;;; main
+
+;; (defun main ()
+;; (handler-case
+;; (multiple-value-bind (options free-args) (opts:get-opts)
+;; (print (list :options options :free-args free-args))
+;; (terpri)
+;; (uiop:quit))
+;; (unix-opts:unknown-option (err)
+;; (declare (ignore err))
+;; (princ (help-text))
+;; (terpri))))