Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bind markdown-insert-list-item to M-RET rather than M-<return> #317

Closed
wants to merge 2 commits into from

Conversation

peniblec
Copy link
Contributor

@peniblec peniblec commented Feb 15, 2018

tl;dr This is consistent with org-mode and tex-mode and fixes the binding for terminals.

Description

<return> refers to the actual function key, which cannot be picked up by Emacs in a terminal. AFAIU this is because terminals translate function keys into character sequences before they tell the application what is going on. So:

  • <return> is translated into RET ≡ \r^M
  • M-<return> is translated into M-RET ≡ \E\r^[^M

In graphical frames, Emacs knows that <return> was pressed, and translates it to RET if there is no binding specifically for <return>; in terminals, Emacs has no idea that <return> was pressed.

As a side effect, this change also makes C-M-m insert new list items since C-m ≡ RET ≡ "control character 13".

(The first commit message provides additional gory details explanations)

Related Issue

I did not raise an issue. Let me know if you feel this deserves more discussion; I will open one.

Type of Change

  • Bug fix (non-breaking change which fixes an issue)
  • Improvement (non-breaking change which improves an existing feature)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)

⚠ NITPICKING ⚠ Not sure about some checkboxes:

  • It's not really a bug fix because I did not open a formal issue; it does fix the binding in a terminal though.
  • Does adding more bindings (C-M-m) count as a new feature?
  • It could be a breaking change for people who bind M-RET.

Checklist

  • I have read the CONTRIBUTING.md document.
  • I have updated the documentation in the README.md file if necessary.
    • I did not find explicit mentions of <return> in the documentation; I took a look at the guide and it actually mentions M-RET, so I guess everything works out?
  • I have added an entry to CHANGES.md.
    • Not yet; would the following work under "Bug fixes"?

      Fix M-RET binding for terminals (GH-TODO)

  • I have added tests to cover my changes.
  • All new and existing tests passed (using make test).

Originally, the test checked for M-<return> unconditionally:

(ert-deftest test-markdown-insertion/list-item-bound-keys ()
  "Test that `markdown-insert-list-item' is bound to M-RET and equivalents."
  (markdown-test-string "- foo"
                        (goto-char (point-max))
                        (execute-kbd-macro (read-kbd-macro "M-RET bar C-M-m baz M-<return> quux"))
                        (should (string-equal (buffer-string) "- foo\n- bar\n- baz\n- quux"))))

This does not pass when run with make test, though it does pass when run in a graphical Emacs:

emacs -Q
M-x load-file RET markdown-mode.el RET
M-x load-file RET tests/markdown-test.el RET
M-x ert-run-tests-interactively RET test-markdown-insertion/list-item-bound-keys RET

I am assuming this is because --batch does not load a window system; hence I added (when display-graphic-p …) before testing M-<return>.

This follows what e.g. org-mode and tex-mode do:

    lisp/org/org.el:            (org-defkey org-mode-map (kbd "M-RET") #'org-meta-return)
    lisp/textmodes/tex-mode.el: (define-key map "\M-\r" 'latex-insert-item)

Long story short (but hopefully accurate):

- <return> refers to the physical "⏎" function key;

- terminals do not tell applications  that a function key was pressed,
  rather they send a character sequence;

- so on terminals, M-<return> cannot work;

- RET ≡  \r is  not an  actual key, but  rather the  control character
  emitted by pressing Control-M in a terminal;

- on graphical displays, Emacs  automatically translates <return> into
  RET if there is no binding for <return>.

Using M-RET rather than M-<return> allows the following things:

1. the binding works on terminals[^1];
2. C-M-m  now also works  as an alternative  (…  which was  my initial
   motivation to investigate this).

Sources and gory details:

- (emacs) Keymaps

    > Most modern  keyboards have function  keys as well  as character
    > keys.  Function  keys send input  events just as  character keys
    > do, and keymaps can have bindings for them.
    >
    > …
    >
    > On  text terminals,  typing a  function key  actually sends  the
    > computer a  sequence of characters;  the precise details  of the
    > sequence depends on the function key and on the terminal type.

- (emacs) Named ASCII Chars

    > Emacs can distinguish  these two kinds of input  if the keyboard
    > does.  It treats the special  keys as function keys named ‘tab’,
    > ‘return’,  ‘backspace’,  ‘linefeed’,   ‘escape’,  and  ‘delete’.
    > These   function   keys   translate   automatically   into   the
    > corresponding  ASCII characters  _if_ they  have no  bindings of
    > their own.
    >
    > If you  do not want  to distinguish between (for  example) <TAB>
    > and  ‘C-i’,  make just  one  binding,  for the  ASCII  character
    > <TAB> (octal code 011).  If you do want to distinguish, make one
    > binding for this  ASCII character, and another  for the function
    > key ‘tab’.
    >
    > With an ordinary ASCII terminal,  there is no way to distinguish
    > between <TAB>  and ‘C-i’  (and likewise  for other  such pairs),
    > because the terminal sends the same character in both cases.

- Xah Lee:

    - <http://ergoemacs.org/emacs/emacs_key_notation_return_vs_RET.html>
    - <http://ergoemacs.org/emacs/keyboard_shortcuts.html>
    - <http://ergoemacs.org/emacs/keystroke_rep.html>

- a *scratch* buffer:

        (kbd "RET")         ; "^M"
        (kbd "\r")          ; "^M"
        (kbd "C-m")         ; "^M"
        (kbd "<return>")    ; [return]

- on X:

        C-h c ⏎ ; RET (translated from <return>) runs the command newline

- on a TTY:

        C-h c ⏎ ; RET runs the command newline

[^1]:  Provided the  terminals send  the correct  character sequences.
This is not always straightforward.   Here are the results of pressing
Alt-⏎ on three different terminals:

    - on a TTY:         M-RET
    - on Terminator:    C-M-j
    - on XTerm:         toggles fullscreen

    With this .Xresources snippet:

        XTerm.vt100.translations: #override \n\
            Alt <Key>Return: insert-eight-bit()

    XTerm also sends M-RET.
The test originally checked for M-<return> unconditionally:

    (ert-deftest test-markdown-insertion/list-item-bound-keys ()
      "Test that `markdown-insert-list-item' is bound to M-RET and equivalents."
      (markdown-test-string "- foo"
                            (goto-char (point-max))
                            (execute-kbd-macro (read-kbd-macro "M-RET bar C-M-m baz M-<return> quux"))
                            (should (string-equal (buffer-string) "- foo\n- bar\n- baz\n- quux"))))

However, this failed when running make test, although it did pass when
run in a graphical Emacs:

    emacs -Q
    M-x load-file RET markdown-mode.el RET
    M-x load-file RET tests/markdown-test.el RET
    M-x ert-run-tests-interactively RET test-markdown-insertion/list-item-bound-keys RET

I'm assuming  this is due to  --batch running things without  a window
system.
@jrblevin
Copy link
Owner

Thanks for the patches! I squashed these, along with an update to CHANGES.md as you suggested, and applied as c0fc524.

I agree about the checkboxes–it is based on a template I found somewhere. They aren't mutually exclusive, so a first-order approximation is fine.

@jrblevin jrblevin closed this May 26, 2018
This pull request was closed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants