8

in emacs in haskell-mode, I wanted to change the command

  • "C-x C-s"

to

  • "C-x C-s" followed by "C-c C-l".

Taking a cue from : Haskell.org : Emacs/Keybindings and simple usage I tried inserting the following variants into the .emacs file but they did not work. Any suggestions as to how I might go about implementing the functionality above would be most welcomed! Thanks.

Variant 1

(defun haskell-hook ()
  (define-key haskell-mode-map (kbd "C-x C-s") (kbd "C-x C-s C-c C-l"))

(add-hook 'haskell-mode-hook 'haskell-hook)

Variant 2

(defun haskell-hook ()
  (define-key haskell-mode-map (kbd "C-x C-s") 'my-haskell-mode-save-buffer)

(defun my-haskell-mode-save-buffer ()
  (interactive)
  (execute-kbd-macro [?\C-s ?\C-x ?\C-c ?\C-l return]))

(add-hook 'haskell-mode-hook 'haskell-hook)


[EDIT 1] @Tikhon Jelvis : that was definitely a good learning exercise! Thanks. Using the methods outlined in your post I changed your function to :

(defun my-haskell-mode-save-buffer ()
  (interactive)
  (save-buffer)
  (inferior-haskell-load-file)
  (other-window 1))

where the last line programmatically switches the cursor to the interactive window. Thank you.

[EDIT2] Other variants include :

(defun my-haskell-mode-save-buffer ()
  (interactive)
  (execute-kbd-macro (read-kbd-macro "C-c C-l"))
  (other-window 1)) 

and :

(defun my-haskell-mode-save-buffer ()
  (interactive)
  (execute-kbd-macro [?\C-c ?\C-l])
  (other-window 1))
Richard J. Ross III
  • 55,009
  • 24
  • 135
  • 201
artella
  • 5,068
  • 4
  • 27
  • 35
  • You can bind a keyboard sequence to a command, not another keyboard sequence. What are you trying to accomplish? – tripleee Aug 11 '12 at 19:48
  • Basically I want "C-s C-x" to first save the file and then automatically load the file in the launcher, rather than just saving the file. Thanks – artella Aug 11 '12 at 19:55
  • 2
    Look for a `haskell-mode-after-save-hook` or create a function which does this. `(defun my-haskell-save-buffer (buf) (interactive ...) (save-buffer buf) (haskell-launch buf) )` ... Proof of concept, look up how to pass the current buffer with `interactive` and the exact command for "the launcher". – tripleee Aug 11 '12 at 20:10
  • 1
    It might make more sense to bind saving the file then loading to `C-c C-l` rather than loading the file every time you save it. – vivian Aug 12 '12 at 07:55
  • @vivian : It was just an experiment for me to learn about emacs. As Tikhon Jelvis points out "C-c C-l" already saves so (apart from the moving of the cursor between buffers) there is not really any value added by the functionality above! Thanks – artella Aug 12 '12 at 08:00

2 Answers2

6

What you want to do is run the function that C-x C-s runs followed by running the function C-c C-l does. You can find out what function is run by some key binding via C-h k. That is, first type C-h k then the key command you're interested in.

This gives us (save-buffer &optional ARGS) for C-x C-s and (inferior-haskell-load-file &optional RELOAD) for C-c C-l. The &optional means exactly what you think it does--that argument is optional, so we don't care about it.

Now write the function that does both of them:

(defun my-haskell-mode-save-buffer ()
  (interactive)
  (save-buffer)
  (inferior-haskell-load-file)) 

Now you can bind this function to C-x C-s in haskell mode exactly how you've been doing it:

(add-hook 'haskell-mode-hook (lambda () 
                                (local-set-key (kbd "C-x C-s") 'my-haskell-mode-save-buffer)))

EDIT: It seems C-c C-l saves your file by default before loading it. This means you can just write

(add-hook 'haskell-mode-hook (lambda ()
                            (local-set-key (kbd "C-x C-s") 'inferior-haskell-load-file)))

and have exactly the same effect without writing your own function. However, I think writing it my way is a good learning exercise :P. That approach works whenever you want to combine multiple different key bindings into one.

Stefan
  • 27,908
  • 4
  • 53
  • 82
Tikhon Jelvis
  • 67,485
  • 18
  • 177
  • 214
0

The accepted answer does not work in the year 2020. To fix it, you'd have to replace (inferior-haskell-load-file) with (haskell-process-load-file).

So the function after fixing is

(defun haskell-mode-save-load-buffer ()
      (interactive)
      (save-buffer)
      (haskell-process-load-file))