;nyquist plug-in
;version 4
;type tool
;name "Macro Step Through"
;author "Steve Daulton"
;release 3.0.0.2
;copyright "Released under terms of the GNU General Public License version 2"

;control macro "Macro name" string "" "Fade Ends" ""
;control action "Action" choice "Step,Restart,Skip Step,Repeat Step,Run All,Reset" 0

;; Global variables
(setf macro (string-trim " " macro))  ;trim spaces
(setf fname "")
(setf id 'Macro-Step-Through-21Mar2021-13:55) ;Unique ID for *scratch*
(setf line-num (get '*scratch* id)) ;last line processed or NIL.


(defun set-fname ()
  (setf fname (format nil "~a.txt" macro))
  ;; Get fully qualified name of file
  (setf fname (format nil "~a~aMacros~a~a"
                      (string-right-trim "\/" (get '*system-dir* 'data))
                      *file-separator*
                      *file-separator*
                      fname)))

(defun reset ()
  (format t "Plug-in reset.~%")
  (setf line-num 0)
  (remprop '*scratch* id))

(defun do-command (fp)
  (let (command
        rslt)
    (if line-num
        (incf line-num)
        (setf line-num 1))
    ; save the current line number as property of *scratch*.
    (putprop '*scratch* line-num id)
    ;; ignore lines that have already been done.
    (dotimes (i line-num)
      (setf command (read-line fp)))
    (cond
     ((not command)
        (reset)
        "Macro completed")
     ((string= command "")
        (format t "Line ~a empty in ~s" line-num macro)
        "")
     (t (get-rslt command)
        ""))))

(defun repeat-command (fp)
  (when line-num
    (putprop '*scratch* (decf line-num) id))
  (do-command fp))

(defun skip-command (fp)
  (if line-num
    (putprop '*scratch* (incf line-num) id)
    (putprop '*scratch* 1 id))
  (do-command fp))

(defun do-all ()
  (format t "Running ~s~%" macro)
  ; Spaces not allowed in Macro names
  (setf macro (char-remove #\space macro))
  (aud-do (format nil "Macro_~a:" macro)))

(defun get-rslt (cmd)
  (let ((rslt (aud-do cmd)))
    (cond
     ((not rslt)
        (format t "Unexpected error at line ~a~%" line-num))
     ((equal rslt '(""))
        (format t "Line ~a of ~s FAILED.~%   ~s~%"
                line-num macro cmd))
     ((equal rslt '("" . T))
        (format t "Line ~a of ~s~%   ~s~%"
                line-num macro cmd))
     (t (format t "Line ~a of ~a~%   ~s~%"
                line-num macro cmd)
        (format t "~a" rslt)))))

(defun run ()
  (set-fname)
  (let ((fp (open fname :direction :input)))
    (cond
      ((string= fname "")
          (reset)
          "Macro name not entered.\nPlug-in reset.")
      ((not fp)
          (reset)
          (format nil "~a not found.~%~
                       ~a~%does not exist." macro fname))
      ((= action 0) ;Step
          (setf rslt (do-command fp))
          (close fp)
          rslt)
      ((= action 1) ;Restart
          (reset)
          (setf rslt (do-command fp))
          (close fp)
          rslt)
      ((= action 2) ;Skip
          (setf rslt (skip-command fp))
          (close fp)
          rslt)
      ((= action 3) ;Repeat
          (setf rslt (repeat-command fp))
          (close fp)
          rslt)
      ((= action 4) ;Run All
          (reset)
          (do-all)
          (close fp)
          "")
      (t (reset)
          "Plug-in reset."))))

(run)
