-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathexecutor.lisp
64 lines (56 loc) · 2.52 KB
/
executor.lisp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
(defpackage :elis/executor
(:use :cl)
(:export :execute))
(in-package :elis/executor)
(defvar *process-list* '())
(defvar *write-callback*)
(defvar *exit-process-callback*)
(defgeneric execute-aux (operator arguments))
(defun run-process (command)
(let ((process (async-process:create-process command :nonblock nil)))
(push process *process-list*)
(bt:make-thread (lambda ()
(loop
(unless (async-process:process-alive-p process)
(alexandria:deletef *process-list* process)
(funcall *exit-process-callback*)
(return))
(alexandria:when-let
(string (async-process:process-receive-output process))
(funcall *write-callback* string))))
:name (format nil "elis run-process ~S" command)
:initial-bindings `((*write-callback* . ,*write-callback*)
(*exit-process-callback* . ,*exit-process-callback*)
,@bt:*default-special-bindings*))))
(defmethod execute-aux ((operator (eql :execute)) arguments)
(destructuring-bind (command-name &rest args) arguments
(let ((process
(run-process
(cons command-name
(mapcar (lambda (arg)
(case arg
(:current-directory (namestring (probe-file ".")))
(:parent-directory (namestring (probe-file "..")))
(otherwise (maybe-expand-path arg))))
args)))))
process)))
(defun execute (string &key ((:write-callback *write-callback*)
(error "Missing :write-callback"))
((:exit-process-callback *exit-process-callback*)
(error "Missing :exit-process-callback")))
(let ((expression (elis/parser:parse string)))
(execute-aux (first expression)
(rest expression))))
(defun homedir (&optional (trim-slash t))
(if trim-slash
(string-right-trim '(#\/) (namestring (user-homedir-pathname)))
(namestring (user-homedir-pathname))))
(defun maybe-expand-path (string)
(cond ((alexandria:starts-with-subseq "~/" string)
(concatenate 'string
(homedir nil)
(subseq string 2)))
((equal string "~")
(homedir t))
(t
string)))