1

I have written a custom interactive command that takes a character as an argument. When I happen to use the key binding for that command while in a eshell buffer where a long-running command is currently running, I get this backtrace:

Debugger entered--Lisp error: (wrong-type-argument characterp (switch-frame #<frame perf_log.1 0x2b7af490>))
  char-to-string((switch-frame #<frame perf_log.1 0x2b7af490>))
  eshell-self-insert-command()
  call-interactively(eshell-self-insert-command nil nil)
  command-execute(eshell-self-insert-command)

So I looked at the code for that function:

(defun eshell-self-insert-command ()
  (interactive)
  (process-send-string
   (eshell-interactive-process)
   (char-to-string (if (symbolp last-command-event)
               (get last-command-event 'ascii-character)
               last-command-event))))

The only reference to which I can find is inside the ominous sounding function eshell-intercept-commands.

I suspect that in that circumstance eshell mistakenly thinks that the last command event was intended for it. Is there a way to filter those instances?

The full implementation of my command is below (it assigns unique characters to emacs windows, displays the character in the modeline, then lets me switch to that window by pressing a hotkey and letter assigned to the window):

(defconst md-glyphs
   '(?A ?B ?C ?D ?E ?F ?G ?H ?I ?J ?K ?L ?M ?N ?O ?P ?Q ?R ?S ?T ?U ?V ?W ?X ?Y ?Z
   ?0 ?1 ?2 ?3 ?4 ?5 ?6 ?7 ?8 ?9
   ?^ ?\# ?\ ?> ?\; ?\" ?* ?\' ?% ?\\ ?\` ?$ ?[ ?_ ?\, ?{ ?:
   ?! ?- ?\( ?\| ?~ ?\. ?? ?= ?\) ?< ?} ?& ?/ ?@ ?+ ?]))

(defun md-get-window-glyph (w)
  (let* ((fp (frame-parameters (window-frame w)))
         (frame-top (cdr (assoc 'top fp)))
         (frame-left (cdr (assoc 'left fp)))
         (window-top (window-top-line w))
         (window-left (window-left-column w))
         (hash (md5 (format "%S %S %S %S" frame-top frame-left window-top window-left)))
         (glyph (nth (% (string-to-number (substring hash 0 2) 16) (length md-glyphs)) md-glyphs)))
    (char-to-string glyph)))

(setq-default mode-line-format
              (append
               (list '(:eval (propertize (format "[%s] " (md-get-window-glyph (get-buffer-window))) 'face 'font-lock-constant-face)))
               mode-line-format))

(defun md-select-window-with-glyph (chosen-glyph)
  (interactive "cWindow glyph: ")
  (dolist (f (frame-list))
    (dolist (w (window-list f 0))
      (ignore-errors 
        (when (equal (downcase (md-get-window-glyph w)) (downcase (char-to-string chosen-glyph)))
          (select-frame-set-input-focus f)
          (select-window w))))))

(global-set-key (kbd "M-d") #'md-select-window-with-glyph)
1

Clearly this code is bugged:

(char-to-string (if (symbolp last-command-event)
                    (get last-command-event 'ascii-character)
                  last-command-event)

If, as is the case in your backtrace, last-command-event is a list such as (switch-frame #<frame perf_log.1 0x2b7af490>) then char-to-string barfs because it expects a character.

Report the bug to the library maintainer.

It's not clear what the relation is between that code that raises the error (the backtrace) and your own code that you show. Presumably your code has a similar problem? (The question seems unclear.)

As for your code: You don't show how md-glyphs is populated. If you are asking about your code, and your code raises a similar error for (char-to-string glyph), then use M-x debug-on-entry md-get-window-glyph and see where it goes wrong. Should be quick to see. (Presumably glyph is not a character.)

  • I've updated my code to show how I define md-glyphs, it only contains characters, and never changes after being defined. I only included my code since its presence seems to be necessary to trigger the bug in eshell. – Joseph Garvin Feb 14 '16 at 20:12

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.