After digging further, I think the best place to make changes isnt inthese functions, but rather in get-completion-preview-list. Does this sound correct?
Thanks, Nathan s Responding to: > Hello, > > When Emacs is accepting input via M-x one can forego writing the whole command > due to the way emacs completes it. While I'm not skilled enough to implement > emacs style completion, I do think it would be nice to be able to complete > incomplete commands when there is only one possible completion. I'm putting > this > here instead of in a github pull request because, in all truthfulness, github > forking and pull-requesting confuses me, and someone told me I could also > submit my contributions throught this mailing list. > > I've modified the functions eval-command and call-interactively to have an > additional optional argument called auto-complete, which when true retries > completion before throwing an error. I'm not sure if this is the right way > to get the behavior I want, but it works. If theres a better way to do this > I'll gladly try to implement it. > > Apologies for the length of this email; I figured it was better to include > every > function than just the small bits i changed, but if its not let me know and > I'll > do it differently in the future. > > Cheers, > Nathan > > Heres the code: > > (defun call-interactively (command &optional (input "") auto-complete) > "Parse the command's arguments from input given the command's > argument specifications then execute it. Returns a string or nil if > user aborted." > (declare (type (or string symbol) command) > (type (or string argument-line) input)) > ;; Catch parse errors > (catch 'error > (let* ((arg-line (if (stringp input) > (make-argument-line :string input > :start 0) > input)) > (cmd-data (or (get-command-structure command) > (and auto-complete > (let ((comp (input-find-completions command > (all-commands)))) > (when (and comp (= 1 (length comp))) > (get-command-structure (car comp))))) > (throw 'error (format nil "Command '~a' not found." > command)))) > (arg-specs (command-args cmd-data)) > (args (loop for spec in arg-specs > collect (let* ((type (if (listp spec) > (first spec) > spec)) > (prompt (when (listp spec) > (second spec))) > (fn (gethash type *command-type-hash*))) > (unless fn > (throw 'error (format nil "Bad argument > type: ~s" type))) > ;; If the prompt is NIL then it's > ;; considered an optional argument and > ;; we shouldn't prompt for it if the > ;; arg line is empty. > (if (and (null prompt) > (argument-line-end-p arg-line)) > (loop-finish) > (funcall fn arg-line prompt)))))) > ;; Did the whole string get parsed? > (unless (or (argument-line-end-p arg-line) > (position-if 'alphanumericp (argument-line-string arg-line) > :start (argument-line-start arg-line))) > (throw 'error (format nil "Trailing garbage: ~{~A~^ ~}" (subseq > (argument-line-string arg-line) > > (argument-line-start arg-line))))) > ;; Success > (prog1 > (apply (command-name cmd-data) args) > (setf *last-command* command))))) > > (defun eval-command (cmd &optional interactivep auto-complete) > "exec cmd and echo the result." > (labels ((parse-and-run-command (input) > (let* ((arg-line (make-argument-line :string input > :start 0)) > (cmd (argument-pop arg-line))) > (let ((*interactivep* interactivep)) > (call-interactively cmd arg-line auto-complete))))) > (multiple-value-bind (result error-p) > ;; this fancy footwork lets us grab the backtrace from where the > ;; error actually happened. > (restart-case > (handler-bind > ((error (lambda (c) > (invoke-restart 'eval-command-error > (format nil "^B^1*Error In Command > '^b~a^B': ^n~A~a" > cmd c (if > *show-command-backtrace* > (backtrace-string) > "")))))) > (parse-and-run-command cmd)) > (eval-command-error (err-text) > :interactive (lambda () nil) > (values err-text t))) > ;; interactive commands update the modeline > (update-all-mode-lines) > (cond ((stringp result) > (if error-p > (message-no-timeout "~a" result) > (message "~a" result))) > ((eq result :abort) > (unless *suppress-abort-messages* > (message "Abort."))))))) > > (defcommand colon (&optional initial-input) (:rest) > "Read a command from the user. @var{initial-text} is optional. When > supplied, the text will appear in the prompt. > > String arguments with spaces may be passed to the command by > delimiting them with double quotes. A backslash can be used to escape > double quotes or backslashes inside the string. This does not apply to > commands taking :REST or :SHELL type arguments." > (let ((cmd (completing-read (current-screen) ": " (all-commands) > :initial-input (or initial-input "")))) > (unless cmd > (throw 'error :abort)) > (when (plusp (length cmd)) > (eval-command cmd t t))))