1;; envelopes.lsp -- support functions for envelope editor in NyquistIDE 2 3#| In Nyquist, editable envelopes are saved as one entry in the workspace 4named *envelopes*. The entry is an association list where each element 5looks like this: 6 7(name type parameters... ) 8 9where name is a symbol, e.g. MY-ENVELOPE-1, 10 type is a function name, e.g. PWL, PWLV, PWE, etc., and 11 parameters are breakpoint data, e.g. 0.1 1 0.2 0.5 1 12 13Example of two envelopes named FOO and BAR: 14 15((FOO PWL 0.1 1 1) (BAR PWE 0.2 1 1)) 16 17To convert envelope data into functions, call (MAKE-ENV-FUNCTIONS). 18This function should be on the workspace's list of functions to call. 19(See ADD-ACTION-TO-WORKSPACE in Nyquist Manual.) 20 21When the NyquistIDE wants to get the envelope data from the workspace, it 22should call (GET-ENV-DATA), which will dump formatted data to Nyquist's 23standard output as follows: 24 25get-env-data: begin 26name (type parameters...) newline 27name (type parameters...) newline 28... 29get-env-data: end 30 31When the IDE wants to save a definition, it should call 32(DEFINE-ENV 'NAME 'EXPRESSION) 33 34To delete a definition, call: 35(DELETE-ENV 'NAME) 36 37Envelope data will be loaded when the editor window is opened and saved 38whenever the user issues a "save" command. If the user switches envelopes 39without saving, there is a prompt to save or ignore. 40 41The user will also be prompted to save when the editor window is closed 42or when Nyquist is exited. 43 44Saving the workspace automatically is something that Nyquist should do 45(or prompt the user to do) when it exits. 46 47|# 48 49;; WORKSPACE -- the workspace is just a set of variables, typically 50;; with scores as values. These are stored in the file workspace.lsp 51;; so that you can work on some data and then store it for use later. 52 53(cond ((not (boundp '*workspace*)) 54 (setf *workspace* nil))) 55(cond ((not (boundp '*workspace-actions*)) 56 (setf *workspace-actions* nil))) 57;; one of the variables in the workspace is *envelopes* 58(cond ((not (boundp '*envelopes*)) 59 (setf *envelopes* nil))) 60 61;; DESCRIBE -- add a description to a global variable 62;; 63(defun describe (symbol &optional description) 64 (add-to-workspace symbol) 65 (cond (description 66 (putprop symbol description 'description)) 67 (t 68 (get symbol 'description)))) 69 70;; ADD-TO-WORKSPACE -- add a global symbol to workspace 71;; 72(defun add-to-workspace (symbol) 73 (cond ((not (symbolp symbol)) 74 (format t "add-to-workspace expects a (quoted) symbol~%")) 75 ((not (member symbol *workspace*)) 76 (push symbol *workspace*)))) 77 78 79;; ADD-ACTION-TO-WORKSPACE -- call function when workspace is loaded 80;; 81(defun add-action-to-workspace (symbol) 82 (cond ((not (symbolp symbol)) 83 (format t "add-action-to-workspace expects a (quoted) symbol~%")) 84 ((not (member symbol *workspace-actions*)) 85 (push symbol *workspace-actions*)))) 86 87;; SAVE-WORKSPACE -- write data to file 88;; 89(defun save-workspace () 90 (let (val (outf (open "workspace.lsp" :direction :output))) 91 (dolist (sym *workspace*) 92 (format outf "(add-to-workspace '~A)~%" sym) 93 (cond ((get sym 'description) 94 (format outf "(putprop '~A \"~A\" 'description)~%" 95 sym (get sym 'description)))) 96 (format outf "(setf ~A '" sym) 97 (setf val (symbol-value sym)) 98 (cond ((listp val) 99 (format outf "(~%") 100 (dolist (elem val) 101 (format outf " ~A~%" elem)) 102 (format outf " ))~%~%")) 103 (t 104 (format outf "~A)~%~%" val)))) 105 (dolist (sym *workspace-actions*) ;; call hooks after reading data 106 (format outf "(add-action-to-workspace '~A)~%" sym) 107 (format outf "(if (fboundp '~A) (~A))~%" sym sym)) 108 (format outf "(princ \"workspace loaded\\n\")~%") 109 (close outf) 110 (princ "workspace saved\n") 111 nil)) 112 113 114;; DEFINE-ENV -- save the env data and make corresponding function 115;; 116(defun define-env (name expression) 117 (delete-env name) 118 (push (cons name expression) *envelopes*) 119 (make-env-function name expression) 120 ; make sure envelopes are redefined when workspace is loaded 121 (add-to-workspace '*envelopes*) ; so *envelopes* will be saved 122 (describe '*envelopes* "data for envelope editor in NyquistIDE") 123 (add-action-to-workspace 'make-env-functions) 124 nil) 125 126 127;; DELETE-ENV -- delete an envelope definition from workspace 128;; 129;; note that this will not undefine the corresponding envelope function 130;; 131(defun delete-env (name) 132 (setf *envelopes* 133 (remove name *envelopes* 134 :test #'(lambda (key item) (eql key (car item)))))) 135 136 137;; MAKE-ENV-FUNCTION -- convert data to a defined function 138;; 139(defun make-env-function (name expression) 140 (setf (symbol-function name) 141 (eval (list 'lambda '() expression)))) 142 143 144;; MAKE-ENV-FUNCTIONS -- convert data to defined functions 145;; 146(defun make-env-functions () 147 (let (name type parameters) 148 (dolist (env *envelopes*) 149 (setf name (car env)) 150 (setf type (cadr env)) 151 (setf parameters (cddr env)) 152 (make-env-function name (cons type parameters))))) 153 154 155;; GET-ENV-DATA -- print env data for IDE 156;; 157(defun get-env-data () 158 (princ "get-env-data: begin\n") 159 (dolist (env *envelopes*) 160 (format t "~A ~A~%" (car env) (cdr env))) 161 (princ "get-env-data: end\n") 162 nil) 163 164