From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!not-for-mail From: Alexander Shukaev Newsgroups: gmane.emacs.help Subject: `define-key' in `defadvice' takes effect only after second invocation Date: Wed, 2 Sep 2015 22:06:22 +0200 Message-ID: NNTP-Posting-Host: plane.gmane.org Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 X-Trace: ger.gmane.org 1441224398 4439 80.91.229.3 (2 Sep 2015 20:06:38 GMT) X-Complaints-To: usenet@ger.gmane.org NNTP-Posting-Date: Wed, 2 Sep 2015 20:06:38 +0000 (UTC) To: help-gnu-emacs Original-X-From: help-gnu-emacs-bounces+geh-help-gnu-emacs=m.gmane.org@gnu.org Wed Sep 02 22:06:37 2015 Return-path: Envelope-to: geh-help-gnu-emacs@m.gmane.org Original-Received: from lists.gnu.org ([208.118.235.17]) by plane.gmane.org with esmtp (Exim 4.69) (envelope-from ) id 1ZXEIl-0002DJ-U6 for geh-help-gnu-emacs@m.gmane.org; Wed, 02 Sep 2015 22:06:36 +0200 Original-Received: from localhost ([::1]:41149 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ZXEIm-0004OL-7y for geh-help-gnu-emacs@m.gmane.org; Wed, 02 Sep 2015 16:06:36 -0400 Original-Received: from eggs.gnu.org ([2001:4830:134:3::10]:34793) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ZXEIb-0004NJ-05 for help-gnu-emacs@gnu.org; Wed, 02 Sep 2015 16:06:26 -0400 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ZXEIZ-0003q8-Q1 for help-gnu-emacs@gnu.org; Wed, 02 Sep 2015 16:06:24 -0400 Original-Received: from mail-lb0-x232.google.com ([2a00:1450:4010:c04::232]:35341) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ZXEIZ-0003po-DO for help-gnu-emacs@gnu.org; Wed, 02 Sep 2015 16:06:23 -0400 Original-Received: by lbpo4 with SMTP id o4so12798570lbp.2 for ; Wed, 02 Sep 2015 13:06:22 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=mime-version:date:message-id:subject:from:to:content-type; bh=F+ejVNhFCh72gE8pOwlGm1ecyggZHPN8yJk/OOIUdSs=; b=o6gNfKOfiTZ/JBP/Btz1/HmMPAP0Pk3vqfv4GLNYEApZFz5N2i5VXP9N4lId56aHIB r6xpcvjHCptL1PBmDGMdvj6ZfDVS7V0YLgNCZIIIKzDioGMPhEOcNd1J2oau9NAROXa5 v3qUtFxTGLI3h57P85sd/0WowyWaDuW7f1nAMoR5sT4sAdOPQ9lLmoE4b0gZ+uvNJ4Fa 5hIcz5svWo4VN0cKn754D2/oMrsDzEXCbfvgoUQITjoU862X5ltHvtzIzULIS2gVTTZL tCj65xVNTJS+az8o7cagMeGRytKisNWwxUmIOlk0G1g1eYlwAlQbb+Fb+0tE/CljFTSM vJoQ== X-Received: by 10.112.146.135 with SMTP id tc7mr17997277lbb.35.1441224382485; Wed, 02 Sep 2015 13:06:22 -0700 (PDT) Original-Received: by 10.112.34.10 with HTTP; Wed, 2 Sep 2015 13:06:22 -0700 (PDT) X-detected-operating-system: by eggs.gnu.org: Error: Malformed IPv6 address (bad octet value). X-Received-From: 2a00:1450:4010:c04::232 X-BeenThere: help-gnu-emacs@gnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: Users list for the GNU Emacs text editor List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: help-gnu-emacs-bounces+geh-help-gnu-emacs=m.gmane.org@gnu.org Original-Sender: help-gnu-emacs-bounces+geh-help-gnu-emacs=m.gmane.org@gnu.org Xref: news.gmane.org gmane.emacs.help:106991 Archived-At: Hello, As a part of my custom Vi layer written on top of Evil, I'm in the process of adding the following (simple package): (require 'devil-common) (require 'devil-core) (require 'devil-states) ;; (defgroup devil-repeat-motion nil "Devil repeat motion." :group 'devil :prefix 'devil-repeat-motion) ;; (defcustom devil-repeat-motion-key (kbd "SPC") "Key used to repeat (last) motion." :group 'devil-repeat-motion :type 'key-sequence) ;; (defcustom devil-repeat-motion-key-reverse (kbd "S-SPC") "Key used to repeat (last) motion in reverse direction." :group 'devil-repeat-motion :type 'key-sequence) ;; ;;;###autoload (defun devil-repeat-motion (key-or-command key-or-command-next key-or-command-previous &optional keymap) "\ Make KEY-OR-COMMAND repeatable." (setq keymap (or keymap evil-motion-state-map)) (let ((command (devil-key-command key-or-command keymap)) (command-next (devil-key-command key-or-command-next keymap)) (command-previous (devil-key-command key-or-command-previous keymap))) (eval `(defadvice ,command (before ,(intern (format "devil-repeat-motion--%s" (symbol-name command))) activate) ,(format "\ Make `%s' repeatable. Repeatable with `%s'. Repeatable with `%s' in reverse direction." command command-next command-previous) (unless (eq last-command #',command) (evil-define-key 'motion devil-repeat-motion-mode-map ,devil-repeat-motion-key #',command-next ,devil-repeat-motion-key-reverse #',command-previous)))) (list command command-next command-previous))) ;; ;;;###autoload (defmacro devil-repeat-motions (&rest ...) "Apply `devil-repeat-motion' to each three consecutive arguments. Return list of results where each element is the return value of the corresponding `devil-repeat-motion' application." (declare (debug t) (indent defun)) (let (body) (while ... (push `(devil-repeat-motion ,(pop ...) ,(pop ...) ,(pop ...)) body)) (setq body (nreverse body)) `(list ,@body))) ;; ;;;###autoload (define-minor-mode devil-repeat-motion-mode "\ Devil repeat motion mode." :global t :group 'devil-repeat-motion :keymap (make-sparse-keymap) :lighter " DRM") ;; (provide 'devil-repeat-motion) I hope this is not too overwhelming to read, but I really need help with the problem. First of all, the code above works as intended. Secondly, let me briefly introduce the idea behind it. Assume one has defined keys for some (Evil) motions in the `evil-motion-state-map' like so: (devil-define-key evil-motion-state-map (kbd "] c") #'evil-find-char (kbd "[ c") #'evil-find-char-backward ;; (kbd "] t") #'evil-find-char-to (kbd "[ t") #'evil-find-char-to-backward ;; (kbd "f") #'evil-repeat-find-char (kbd "F") #'evil-repeat-find-char-reverse) And one wants to make the first four ones repeatable forward and backward with the SPC and S-SPC respectively. So with the above package, one can write (devil-repeat-motions (kbd "] c") (kbd "f") (kbd "F") (kbd "[ c") (kbd "f") (kbd "F") ;; (kbd "] t") (kbd "f") (kbd "F") (kbd "[ t") (kbd "f") (kbd "F"))) Note, that it is also possible to write it like this: (devil-repeat-motions #'evil-find-char #'evil-repeat-find-char #'evil-repeat-find-char-reverse #'evil-find-char-backward #'evil-repeat-find-char #'evil-repeat-find-char-reverse ;; #'evil-find-char-to #'evil-repeat-find-char #'evil-repeat-find-char-reverse #'evil-find-char-to-backward #'evil-repeat-find-char #'evil-repeat-find-char-reverse)) The first variant is just for convenience (works only when keys for commands are already define), while the second one is more general (works anyways). Now to the problem. I start Emacs. I enter `devil-repeat-motion-mode' with, say, M-x devil-repeat-motion-mode RET. I do ] c t (to find the next 't' char forward). This entails advice which binds SPC and S-SPC appropriately (I can see that with both C-h v devil-repeat-motion-mode-map RET and C-h b). But, wait, tapping SPC or S-SPC gives me "SPC is undefined". How come? Now the most interesting. I do ] c t one more time, and now it works! Could anybody explain this behavior to me? I mean, maybe I missed something, and adding binding like this "on fly" requires some additional command to sort of "commit" them to be available immediately or whatever. Thanks a lot, and sorry for lengthy post. Regards, Alexander