This repository was archived by the owner on Sep 25, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 9
/
Copy pathvars.lisp
258 lines (206 loc) · 7.68 KB
/
vars.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
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
;;;
;;; vars.lisp - Variables for Lish
;;;
(in-package :lish)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Versioning
;; Yet another version of versions where presumably the new "improved" build
;; script will increment it.
(defparameter *version* #.(read-file-form
(asdf:system-relative-pathname
:lish "version.lisp")))
(let ((split-version (mapcar (_ (parse-integer _ :junk-allowed t))
(split-sequence #\. *version*))))
(defparameter *major-version* (first split-version)
"Major version number. Releases with the same major version number should be
compatible in the default configuration.")
(defparameter *minor-version* (second split-version)
"Minor version number. This should change at least for every release.")
(defparameter *build-version* (third split-version)
"Build version number. This should increase for every build, which probably
means every dumped executable."))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Misc
(defparameter *shell-name* "Lish"
"The somewhat superfluous name of the shell.")
(defvar *shell* nil
"The current shell instance.")
;; Pipeline input and output values
(defvar %*input* nil
"The output of the previous command in pipeline.")
(defvar %*output* nil
"The output of the current command.")
(defun input ()
"The pipeline input object."
%*input*)
(defun output ()
"The pipeline output object."
%*output*)
(defun export-input ()
"Let external processes access *input*."
(when (and (lish-export-pipe-results *shell*) %*input*)
(setf (nos:env "LISH_INPUT") (princ-to-string %*input*))))
(defun export-output ()
"Let external processes access *output*."
(when (and (lish-export-pipe-results *shell*) %*output*)
(setf (nos:env "LISH_OUTPUT") (princ-to-string %*output*))))
(defun set-input (value)
"Set the pipeline input object to VALUE."
(setf %*input* value)
(export-input)
value)
(defun set-output (value)
"Set the pipeline output object to VALUE."
(setf %*output* value)
(export-output)
value)
;; Possibly exporting *input* and *output* in the environment to sub-processes
;; when they're set is the reason for the symbol macro and functions nonsense.
(defsetf input set-input)
(defsetf output set-output)
(define-symbol-macro *input* (input))
(define-symbol-macro *output* (output))
(define-symbol-macro *i* (input))
(define-symbol-macro *o* (output))
(defmacro with-input ((x) &body body)
"Dynamicly rebind ‘*input*' to ‘x’."
`(let ((%*input* ,x))
(export-input)
,@body))
(defmacro with-output ((x) &body body)
"Dynamicly rebind ‘*output*' to ‘x’."
`(let ((%*output* ,x))
(export-output)
,@body))
(defvar *accepts* nil
"What the next command in the pipeline accepts.")
(defvar *pipe-plus* nil
"True to omap objects to a parenless function call.")
(eval-when (:compile-toplevel :load-toplevel :execute)
(defun make-user-package ()
(or (and (boundp '*lish-user-package*)
(symbol-value '*lish-user-package*))
(find-package "LISH-USER")
(make-package "LISH-USER" :use '(:cl :lish
#+use-regex :regex
#-use-regex :cl-ppcre
:glob)
:nicknames '("LU")))))
(defparameter *lish-user-package* (make-user-package)
"Package for lish to hang out in. Auto-updates from :cl-user.")
(defvar *junk-package*
(progn
(when (find-package :lish-junk)
(delete-package :lish-junk))
(make-package :lish-junk))
"Package to put partial or unknown reader junk.")
;; @@@ Something else that should be in opsys?
(defvar *buffer-size* (nos:memory-page-size)
"General buffer size for file or stream operations.")
(defparameter *options* nil
"List of options defined.")
(defun default-lishrc ()
(nos:path-append (nos:user-home) ".lishrc"))
(defvar *default-lishrc* (default-lishrc)
"Default value for the start up file.")
(defvar *lishrc* nil
"Pathname of the start up file.")
(defvar *use-bracketed-paste* t
"True to use safer pasting in terminals that support it.")
(defvar *dont-deblarg* nil
"True to not activate our debugger even if it's loaded.")
;; I really have some reservations about including this. It's somewhat
;; serendipitous that it works out this way, and it is highly efficient
;; keystroke-wise, but seems like an unorthogonal hackish trick.
(defvar ! nil
"The previous command, so you can say e.g.: sudo !!")
;; These are my magic cookies. I would GENSYM them, but I would like them to
;; be constant over loads or systems.
(defparameter *real-eof-symbol* :Z-REAL-EOF-Z)
(defparameter *continue-symbol* :Z-CONTINUE-Z)
(defparameter *empty-symbol* :Z-EMPTY-Z)
(defparameter *error-symbol* :Z-ERROR-Z)
(defparameter *quit-symbol* :Z-QUIT-Z)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Types?
(defstruct shell-expr
"The result of the shell lexer. A sequence of words and their start and ~
end points in the original string."
words ; sequence of objects
line) ; the original string
(defstruct shell-word
"A word in a shell-expr."
word ; an object
start ; integer start position
end ; integer end position
quoted ; boolean, true if word quoted
eval ; boolean, true to evaluate word
join) ; nil :left :right or :both, to add to adjacent word
;; @@@ I'm not really sure if this is good idea yet.
(defmethod print-object ((object shell-word) stream)
"Print a shell-word to STREAM."
(with-slots (word quoted) object
(cond
((or *print-readably* *print-escape*) (call-next-method))
(quoted (format stream "\"~a\"" word))
(t (format stream "~a" word)))))
(defstruct context
"The context for a command. It's input and output streams and environment
variables."
;; These are a stream or NIL for the default.
in-pipe
out-pipe
;; This is NIL for unspecified, :empty, or an alist environement.
environment
;; True if we flipped *input* to *output* for a pipeline.
flipped-io
;; True if we should run things in the background.
background
;; True if we should map parenless function calls.
pipe-plus
;; True if we should not pass the *output*.
pipe-dot
;; True if we should pipe both output and error
pipe-both
)
(defvar *context* nil
"The dynamic command context. If it is NIL it is equivalent to all the
slots of the context being NIL, and so therefore equivalent to the default
input, output and environment.")
;; We do a simple fake out for signals on OS's that don't really support them.
(defparameter *siggy*
#+windows
'(("TERM" 15 terminate-process)
("STOP" 17 suspend-process)
("CONT" 19 resume-process))
#+unix
(loop :for i :from 1 :below os-unix:*signal-count*
:collect (list (os-unix:signal-name i) i))
"Fake windows signals.")
(defparameter *signal-names*
#+unix (make-array
(list os-unix:*signal-count*)
:initial-contents
(cons ""
(loop :for i :from 1 :below os-unix:*signal-count*
:collect (os-unix:signal-name i))))
#+windows (mapcar #'car *siggy*)
"Names of the signals.")
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Hooks
(defvar *pre-command-hook* nil
"Called before a command is run. Arguments are:
COMMAND-NAME : string - The name of the command.
COMMAND-TYPE : keyword - What kind of command it is.")
(defvar *post-command-hook* nil
"Called after a command is run. Arguments are:
COMMAND-NAME : string - The name of the command.
COMMAND-TYPE : keyword - What kind of command it is.")
(defvar *unknown-command-hook* nil
"Called when a command is not found. Arguments are the shell and the
condition.")
(defvar *enter-shell-hook* nil
"Called when the shell starts, after loading the *lishrc*.")
(defvar *exit-shell-hook* nil
"Called when the shell exits.")
;; End