lem-project / lem

Common Lisp editor/IDE with high expansibility
http://lem-project.github.io/
MIT License
2.4k stars 180 forks source link

On Mac is there a way to change Meta so that it uses the command key? #858

Open cianoc opened 1 year ago

cianoc commented 1 year ago

I have my emacs configuration setup so I can use 'cmd' for meta. However in Lem this is configured to use the option key.

Is there a way to change this?

seanfarley commented 1 year ago

Not yet but hopefully we will be able to do that soon.

vindarel commented 1 year ago

I'll bet there is something you can do with keyboard.lisp:get-modifier (you could re-define it in your Lem init file).

(defun get-modifier (keysym)
  (let* ((mod (sdl2:mod-value keysym))
        …
         (meta (mod-p mod sdl2-ffi:+kmod-lalt+))
         (super (or (mod-p mod sdl2-ffi:+kmod-lgui+)
                    (mod-p mod sdl2-ffi:+kmod-rgui+))))

Here Meta is only left Alt. (I don't know if Super is Cmd on Macs)

Dima-369 commented 1 year ago

(you could re-define it in your Lem init file)

Sorry, I am a bit inexperienced with Common Lisp. For me lem-sdl2/keyboard:get-modifier() is defined in frontends/sdl2/keyboard.lisp and there the function is not exported. How would one re-define it the best way without directly modifying the source?

Dima-369 commented 1 year ago

How would one re-define it the best way without directly modifying the source?

Like this in init.lisp:

(in-package :lem-sdl2/keyboard)

(defun get-modifier (keysym)
  (let* ((mod (sdl2:mod-value keysym))
         (shift (or (mod-p mod sdl2-ffi:+kmod-lshift+)
                    (mod-p mod sdl2-ffi:+kmod-rshift+)))
         (ctrl (or (mod-p mod sdl2-ffi:+kmod-lctrl+)
                   (mod-p mod sdl2-ffi:+kmod-rctrl+)))
         (meta (mod-p mod sdl2-ffi:+kmod-lalt+))
         (super (or (mod-p mod sdl2-ffi:+kmod-lgui+)
                    (mod-p mod sdl2-ffi:+kmod-rgui+))))
    (make-modifier :shift shift :ctrl ctrl :meta meta :super super)))
Dima-369 commented 1 year ago

I debugged the method like this:

(with-open-file (stream "~/a.txt" :direction :output :if-exists :append)
                    (format stream "~a ~a ~a ~a ~a ~a ~%" mod shift ctrl meta super (eq mod 1024)))

I noticed that mod will be equal to 1024 when the left or right Command key is hit on macOS 13.3.1. Meaning, adjusting the function like this brings the expected result:

(defun get-modifier (keysym)
  (let* ((mod (sdl2:mod-value keysym))
         (shift (mod-p mod sdl2-ffi:+kmod-shift+))
         (ctrl (mod-p mod sdl2-ffi:+kmod-ctrl+))
         (super (mod-p mod sdl2-ffi:+kmod-gui+)))
    (make-modifier :shift shift :ctrl ctrl :meta (eq mod 1024) :super super)))

I also merged the (or ...) calls together which is cleaner. sdl2-ffi:+kmod-shift+ means left or right shift, for instance.

cianoc commented 1 year ago

Thank you!

cxxxr commented 1 year ago

In the past we had treated command as super, but once I disabled it because there were cases where SDL2 could not detect that a key had been released. However, it might be a good idea to enable it as an option.

Dima-369 commented 1 year ago

I also merged the (or ...) calls together which is cleaner. sdl2-ffi:+kmod-shift+ means left or right shift, for instance.

With further tests, don't do this, and keep the (or)s. As for whatever reason sdl2-ffi:+kmod-ctrl+ does not properly work for me on macOS, but (or)ing them together does. So just do the (eq mod 1024) change.

vindarel commented 1 year ago

debugged … (with-open-file (stream "~/a.txt"

tip: I use (log:info mod shift …) coupled with (log:config :info) in your Lem init or typed in a REPL. Logs are printed on the terminal (not on Lem's REPL).

great to see advancements :rocket:

Dima-369 commented 1 year ago

tip: I use (log:info mod shift …) coupled with (log:config :info) in your Lem init or typed in a REPL. Logs are printed on the terminal (not on Lem's REPL).

Ah wonderful, I was looking for that. Thanks 😄

Actually (log:info) logs to both Lem REPL and the Terminal, depending on the evaluation context I think. If I use lisp-eval-defun, it goes into both (which is good for me though!).

vindarel commented 1 year ago

I notice the code has changed a bit: now the mapping that says what is a modifier key is moved to a global parameter.

In frontends/sdl2/keyboard.lisp:


(defparameter *modifier-code-table*
  `((:shift ,sdl2-ffi:+kmod-lshift+ ,sdl2-ffi:+kmod-rshift+)
    (:ctrl ,sdl2-ffi:+kmod-lctrl+ ,sdl2-ffi:+kmod-rctrl+)
    (:meta ,sdl2-ffi:+kmod-lalt+)
    (:super ,sdl2-ffi:+kmod-lgui+ ,sdl2-ffi:+kmod-rgui+)))

This for example defines that the Meta is (and only is) the Left Alt.

If we want Right Alt to act as a meta key too (I don't, I need it (french keyboard) to write important chars (< > [ ] { } etc):

(defparameter lem-sdl2/keyboard::*modifier-code-table*
  `((:shift ,sdl2-ffi:+kmod-lshift+ ,sdl2-ffi:+kmod-rshift+)
    (:ctrl ,sdl2-ffi:+kmod-lctrl+ ,sdl2-ffi:+kmod-rctrl+)
    (:meta ,sdl2-ffi:+kmod-lalt+ ,sdl2-ffi:+kmod-ralt+)  ;; <-- ralt added
    (:super ,sdl2-ffi:+kmod-lgui+ ,sdl2-ffi:+kmod-rgui+)))

The get-modifier function is now this one, and I don't think it needs to be changed, only the defparameter above.


(defun get-modifier (keysym)
  (let* ((mod (sdl2:mod-value keysym))
         (shift (mod-p mod :shift))
         (ctrl (mod-p mod :ctrl))
         (meta (mod-p mod :meta))
         (super (mod-p mod :super)))
    (make-modifier :shift shift :ctrl ctrl :meta meta :super super)))
Sasanidas commented 11 months ago

(ping @cianoc ) Did the last comment solved the issue?

cianoc commented 11 months ago

Due to https://github.com/lem-project/lem/issues/1134 I'm unable to test this I'm afraid.

ahanikel commented 10 months ago

My issue was the opposite: both my alt (option) keys were mapped to meta but I need one of them for typing '#' etc. Thanks to @vindarel 's comment I can now use left alt for alt and right alt for meta. Thank you!

mjstahl commented 10 months ago

@Sasanidas My branch is up to date (5012c3f). I installed from scratch (make sdl2). I can confirm left and right option are Meta. Left and right command do nothing.

cianoc commented 10 months ago

(ping @cianoc ) Did the last comment solved the issue?

Yes it did solve the issue.