From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!.POSTED!not-for-mail From: Stefan Monnier Newsgroups: gmane.emacs.devel Subject: Re: One character key bindings in editing buffers Date: Mon, 30 Jul 2018 13:49:49 -0400 Message-ID: References: NNTP-Posting-Host: blaine.gmane.org Mime-Version: 1.0 Content-Type: text/plain X-Trace: blaine.gmane.org 1532972891 6594 195.159.176.226 (30 Jul 2018 17:48:11 GMT) X-Complaints-To: usenet@blaine.gmane.org NNTP-Posting-Date: Mon, 30 Jul 2018 17:48:11 +0000 (UTC) User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/27.0.50 (gnu/linux) To: emacs-devel@gnu.org Original-X-From: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Mon Jul 30 19:48:07 2018 Return-path: Envelope-to: ged-emacs-devel@m.gmane.org Original-Received: from lists.gnu.org ([208.118.235.17]) by blaine.gmane.org with esmtp (Exim 4.84_2) (envelope-from ) id 1fkCH8-0001bR-30 for ged-emacs-devel@m.gmane.org; Mon, 30 Jul 2018 19:48:06 +0200 Original-Received: from localhost ([::1]:54999 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fkCJE-0005B3-JV for ged-emacs-devel@m.gmane.org; Mon, 30 Jul 2018 13:50:16 -0400 Original-Received: from eggs.gnu.org ([2001:4830:134:3::10]:45834) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fkCJ4-0005At-DX for emacs-devel@gnu.org; Mon, 30 Jul 2018 13:50:07 -0400 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1fkCJ0-0000lY-F5 for emacs-devel@gnu.org; Mon, 30 Jul 2018 13:50:06 -0400 Original-Received: from [195.159.176.226] (port=52644 helo=blaine.gmane.org) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1fkCJ0-0000ki-3u for emacs-devel@gnu.org; Mon, 30 Jul 2018 13:50:02 -0400 Original-Received: from list by blaine.gmane.org with local (Exim 4.84_2) (envelope-from ) id 1fkCGm-00019q-OY for emacs-devel@gnu.org; Mon, 30 Jul 2018 19:47:44 +0200 X-Injected-Via-Gmane: http://gmane.org/ Original-Lines: 92 Original-X-Complaints-To: usenet@blaine.gmane.org Cancel-Lock: sha1:G7o5Hiw9STA0CiGf34XIfUKDVss= X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 195.159.176.226 X-BeenThere: emacs-devel@gnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: "Emacs development discussions." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Original-Sender: "Emacs-devel" Xref: news.gmane.org gmane.emacs.devel:228008 Archived-At: > The idea is when typing in an editing buffer one very rarely > types only a single character without others preceding or > following it, so if only a single character is typed then it can > execute a command. If other characters are also typed then it > behaves as usual and inserts that character. Sounds like a good idea for a package, indeed (no way this can make it to a default behavior, OTOH). I just have some comments on the code below. > (defun char-hotkey () > (interactive) > (if (and char-hotkey-mode > (not char-hotkey-typing) > (sit-for 0.5)) > (call-interactively (assoc-default last-command-event char-hotkey-commands)) > (call-interactively 'self-insert-command))) > > (defun char-hotkey-wait-for-end () > (setq char-hotkey-typing t) > (when (or (not (or (equal this-command 'self-insert-command) > (equal this-command 'char-hotkey))) > (sit-for 0.5)) > (setq char-hotkey-typing nil))) I recommend you try and avoid sit-for as much as possible (e.g. because it delays running other post-command-hooks). E.g. in char-hotkey-wait-for-end, better just set some global var to the current time, and then in char-hotkey compare that to the current time to see if 0.5s have elapsed. > (define-minor-mode char-hotkey-mode > "Char hotkey." > :lighter " CH" > > (if char-hotkey-mode > (progn > (dolist (command char-hotkey-commands) > (local-set-key (char-to-string (car command)) 'char-hotkey)) > (add-hook 'post-command-hook 'char-hotkey-wait-for-end nil t)) > > (dolist (command char-hotkey-commands) > (local-set-key (char-to-string (car command)) 'self-insert-command)) > (remove-hook 'post-command-hook 'char-hotkey-wait-for-end t))) Over the years, I've grown to like minor modes to start by unconditionally turning themselves off (i.e. cleaning up): E.g. (define-minor-mode char-hotkey-mode "Char hotkey." :lighter " CH" (dolist (command char-hotkey-commands) (local-set-key (char-to-string (car command)) 'self-insert-command)) (remove-hook 'post-command-hook #'char-hotkey-wait-for-end t) (when char-hotkey-mode (dolist (command char-hotkey-commands) (local-set-key (char-to-string (car command)) 'char-hotkey)) (add-hook 'post-command-hook #'char-hotkey-wait-for-end nil t))) Also, I'd recommend you use command remapping here: (define-minor-mode char-hotkey-mode "Char hotkey." :lighter " CH" (local-set-key [remap self-insert-command] nil) (remove-hook 'post-command-hook #'char-hotkey-wait-for-end t) (when char-hotkey-mode (local-set-key [remap self-insert-command] 'char-hotkey) (add-hook 'post-command-hook #'char-hotkey-wait-for-end nil t))) Also, you can use the minor-mode map feature, so the key-bindings are automatically (de)activated: (defvar char-hotkey-mode-map (let ((map (make-sparse-keymap))) (define-key map [remap self-insert-command] 'char-hotkey) map)) (define-minor-mode char-hotkey-mode "Char hotkey." :lighter " CH" (remove-hook 'post-command-hook #'char-hotkey-wait-for-end t) (when char-hotkey-mode (add-hook 'post-command-hook #'char-hotkey-wait-for-end nil t))) -- Stefan