4

In coffee-mode RET is bound to coffee-newline-and-indent which works fine.

I also use evil-mode to have Vim emulation. evil-mode uses the standard newline-and-indent so the indentation is not correct for some vim commands such as o or O.

What would be the best way to rebind newline-and-indent to coffee-newline-and-indent ?

I'm still a newbie in ELisp and tried the line below but it doesn't work.

(add-hook 'coffee-mode-hook
          (lambda () 
            (setq newline-and-indent '(funcall coffee-newline-and-indent))))
mtgred
  • 1,449
  • 14
  • 17
  • Instead of remapping functions, you will probably be fine mapping RET back to `coffee-newline-and-indent`. Check out various SO questions how to do that. – Thomas Aug 19 '13 at 12:39
  • @Thomas `coffee-mode` already binds RET to the correct function. But in vim emulation, `evil-mode` uses the standard `newline-and-indent`. – mtgred Aug 19 '13 at 12:42
  • Sure, but you could re-bind it to `coffee-newline-and-indent` in `coffee-mode` even though `evil-mode` is active. That's what I meant. – Thomas Aug 19 '13 at 12:57
  • @Thomas from what I understand, the binding is still there in coffee mode map, but the binding in evil mode map takes precedence. Simply binding it again in coffee mode won't solve this. He needs to bind it in evil mode map, but only inside coffee mode buffers. – Malabarba Aug 19 '13 at 23:19
  • @BruceConnor You're absolutely right, and that's exactly what I meant, too. I meant to write "in buffers that are in coffee-mode" above. – Thomas Aug 20 '13 at 08:19
  • Actually, nowadayd the default binding for RET should be `newline` which should do the "and indent" part automatically thanks to `electric-indent-mode`. If that misbehaves in coffee-mode, please report it as a bug. – Stefan Oct 18 '17 at 21:46

5 Answers5

1

Here's my attempt. It should work, but I don't really like it.

(add-hook
 'coffee-mode-hook 
 (lambda ()
   (defalias 
       'newline-and-indent 
       (lambda()
         (interactive)
         (if (eq major-mode 'coffee-mode)
             (coffee-newline-and-indent)
           (delete-horizontal-space t)
           (newline)
           (indent-according-to-mode))))))

I wish I could use something more elegant that just copying the source of newline-and-indent, but make-variable-buffer-local doesn't work for this case, and I couldn't get a deep copy for symbol-function either. I'd be happy to see a better method.

abo-abo
  • 20,038
  • 3
  • 50
  • 71
  • Instead of an alias, you could bind ret in evil-mode to your lambda. Then you would be free to call new-line-and-indent from within your lambda. – Malabarba Aug 19 '13 at 22:50
  • That's not the point. I was trying to substitute the function without changing the binding. I wanted initially not to copy the code of `newline-and-indent` but to store it somewhere and call it later. Like `virtual` in C++. But then I got an infinite recursion problem, because I couldn't deep-copy the body of `newline-and-indent`. – abo-abo Aug 20 '13 at 06:21
  • Allow me to solve all your problems. `(symbol-function 'newline-and-indent)` returns the actual function (the lambda). You can then call this function with funcall or call-interactively from inside your alias without any recursion problem. – Malabarba Aug 20 '13 at 15:41
  • Haha. You must have missed the point in my answer where I've tried `symbol-function`. Say I take the data from `symbol-function` and put it somewhere, sort of to save the original function. Then I redefine `newline-and-indent`, trying to use in this re-definition the previous value of `newline-and-indent`. But this overwrites the value that `symbol-function` returned previously and I get an infinite recursion. As I've mentioned in the answer. You /would/ solve all my problems if you told me how to make a deep copy of the value that `symbol-function` returns. – abo-abo Aug 20 '13 at 15:53
  • HAHA, damn... sorry for underestimating you. But still, I don't have this problem you mentioned. Specifically the following code works fine for me (no recursion): `(setq hi (symbol-function 'newline-and-indent)) (defalias 'newline-and-indent (lambda () (interactive) (funcall hi))) (newline-and-indent)` – Malabarba Aug 20 '13 at 19:33
  • It works. Thanks. I wasn't using `funcall` before. Somehow it didn't occur to me. – abo-abo Aug 20 '13 at 19:47
1

The standard way to accomplish what you seem to be asking for is

(autoload 'coffee-newline-and-indent "coffee-mode") ; (or whatever)
(define-key evil-mode-map (kbd "RET") 'coffee-newline-and-indent)

EDIT: to enable coffee-newline-and-indent only in coffee-mode:

(define-key evil-mode-map (kbd "RET")
  (lambda ()
    (interactive)
    (if (eq major-mode 'coffee-mode)
        (coffee-newline-and-indent)
      (newline-and-indent))))
sds
  • 58,617
  • 29
  • 161
  • 278
0

Try the following:

(define-key evil-mode-map (kbd "RET") nil)

I know it looks overly simple, but if evil-mode works the way I think it does then it should work.

  1. This will wipe the ret key from your evil-mode-map, which will let the binding of coffee-mode-map shine through.
  2. In non-coffee buffers, the ret key will still work, because it's still bind in the global map.
Malabarba
  • 4,473
  • 2
  • 30
  • 49
0

I found the solution.

Evil-mode actually uses coffee-indent-line. The problem comes from coffee-indent-line which doesn't indent correctly. Evil-mode works correctly after patching it to behave like coffee-newline-and-indent:

(defadvice coffee-indent-line (after wants-indent activate)
  (let ((tabs-needed (- (/ (coffee-previous-indent) coffee-tab-width) 1)))
    (when (> tabs-needed 0)
      (insert-tab tabs-needed)))
  (when(coffee-line-wants-indent)
    (insert-tab)))
mtgred
  • 1,449
  • 14
  • 17
0

if you want to remap a func, but only if some major mode is active - create a func which defines an alias and run the func (A) - another func (B) calls (A) - finally, a major mode can advice the func A to set the correct func. It has to test major mode.

let's say A is define-my-indent-f then it says (defalias my-indent 'newline-and-indent) the func b runs A then run command my-indent. finally coffe mode does defadice A to say (if eq major mode coffee defalais my-indent 'coffe-newline-and-indent)

of course this is super heavy to define, but then - each major mode can add its piece - only loaded major mode will advice

sltbmnq
  • 51
  • 1
  • 1