ergoemacs / ergoemacs-mode

ergoemacs-mode
ergoemacs.github.io/
GNU General Public License v3.0
293 stars 35 forks source link

ergoemacs does not handle "DEL" key correctly with selected text #329

Closed lotodore closed 9 years ago

lotodore commented 9 years ago

When selecting text using Shift + Arrow Keys, and then removing it using the DEL key, the expected behaviour is that only the selected text is deleted. This works fine in Emacs with default config (Emacs 24.3.1).

However, with ergoemacs-mode 5.14.7.3, the DEL key also deletes the character below the cursor, which is too much and leads to very strange results. Backspace key has correct behaviour.

I could reproduce this with a minimal .emacs config file like this:

(require 'package)
(add-to-list 'package-archives
             '("melpa" . "http://melpa.milkbox.net/packages/") t)
(package-initialize)

(require 'ergoemacs-mode)
(ergoemacs-mode 1)

Could you please fix this issue?

mattfidler commented 9 years ago

I can reproduce lt, but I"m unsure why its happening. I will try to fix it.

mattfidler commented 9 years ago

It is broken in the "stable" release too... (v5.14.7.3)

mattfidler commented 9 years ago

This should be fixed now.

lotodore commented 9 years ago

Thank you for the quick fix. I'm using the stable "melpa" package, and have no idea about compiling lisp files... Is there any simple way for me to test this fix?

mattfidler commented 9 years ago

You can replace the code for the function to see if it works.

(require 'package)
(add-to-list 'package-archives
             '("melpa" . "http://melpa.milkbox.net/packages/") t)
(package-initialize)

(require 'ergoemacs-mode)
(defun ergoemacs-read-key-call (function &optional record-flag keys)
  "`ergoemacs-mode' replacement for `call-interactively'.

This will call the function with the standard `call-interactively' unless:

- `ergoemacs-describe-key' is non-nil.  In this case,
   `describe-function' is called instead.

-  The function name matches \"self-insert\", then it will send the keys
   by `unread-command-events'.

In addition, when the function is called:

- Add the function count to `keyfreq-table' when `keyfreq-mode'
  is enabled.

- Remove `ergoemacs-this-command' count from `keyfreq-table' when
  `keyfreq-mode' is enabled.

- set `this-command' to the function called.

"
  (setq ergoemacs-deactivate-mark nil)
  (when (and ergoemacs-read-key-last-help (boundp 'guide-key-mode) guide-key-mode)
    (setq ergoemacs-read-key-last-help nil)
    (guide-key/close-guide-buffer))
  (cond
   ((ergoemacs-smart-function-p function)
    (error "Ergoemacs-mode is confused, and exiting out of an infinite loop (refused to call %s)" function))
   (ergoemacs-test-fn
    (setq ergoemacs-test-fn function))
   (ergoemacs-describe-key
    (let ((pt (point))
          (buf (current-buffer))
          (keys '())
          test)
      (unwind-protect
          (save-excursion
            (describe-function function)
            (set-buffer (help-buffer))
            (let ((inhibit-read-only t))
              (goto-char (point-min))
              (insert (format "%s runs the command "
                              (ergoemacs-pretty-key (key-description keys))))
              (when (search-forward " is" nil t)
                (replace-match ", which is"))
              (fill-paragraph)
              (when (search-forward "bound to" nil t)
                (delete-region
                 (point)
                 (if (re-search-forward "\\.\n\n") (point) (point)))
                (with-current-buffer buf
                  (goto-char pt)
                  (ergoemacs-with-global
                   (dolist (global-key (where-is-internal function))
                     (setq test (gethash global-key ergoemacs-original-keys-to-shortcut-keys))
                     (when test
                       (dolist (global-key test)
                         (unless (eq (elt global-key 0) 'menu-bar)
                           (push (ergoemacs-pretty-key (key-description global-key))
                                 keys))))))
                  (let (ergoemacs-modal ergoemacs-repeat-keys ergoemacs-read-input-keys
                                        ergoemacs-shortcut-keys ergoemacs-no-shortcut-keys)
                    (dolist (global-key (where-is-internal function))
                      (unless (eq (elt global-key 0) 'menu-bar)
                        (push (ergoemacs-pretty-key (key-description global-key))
                            keys)))))
                (insert (mapconcat (lambda(x) x) keys ", "))
                (insert ".\n\n"))))
        (setq ergoemacs-describe-key nil))))
   ((ignore-errors (string-match "self-insert" (symbol-name function)))
    (setq ergoemacs-single-command-keys keys)
    (setq last-input-event keys)
    (setq prefix-arg current-prefix-arg)
    (setq unread-command-events (append (listify-key-sequence keys) unread-command-events))
    (ergoemacs-defer-post-command-hook)
    (reset-this-command-lengths))
   (t
    (dolist (var ergoemacs-this-command-fake)
      ;; should include `this-command' and `this-original-command'
      (set var function))
    (let ((this-command-keys-shift-translated
           (or this-command-keys-shift-translated
               (if ergoemacs-shift-translated t nil))))
      ;; Try to maintain shift-selection.
      (when (and ergoemacs-shift-translated
                 (ergoemacs-is-movement-command-p function))
        (cond
         ((and shift-select-mode ergoemacs-force-shift-select-mark-active
               (not mark-active))
          ;; Mark was active, then it was deactivated, now activate again.
          (unless (and mark-active
                       (eq (car-safe transient-mark-mode) 'only))
            (setq transient-mark-mode
                  (cons 'only
                        (unless (eq transient-mark-mode 'lambda)
                          transient-mark-mode))
                  mark-active t)))
         (t ;; Mark was not active, activate mark.
          (handle-shift-selection))))
      (when (featurep 'keyfreq)
        (when keyfreq-mode
          (let ((command ergoemacs-this-command) count)
            (setq count (gethash (cons major-mode command) keyfreq-table))
            (cond
             ((not count))
             ((= count 1)
              (remhash (cons major-mode command) keyfreq-table))
             (count
              (puthash (cons major-mode command) (- count 1)
                       keyfreq-table)))
            ;; Add local-fn to counter.
            (setq count (gethash (cons major-mode function) keyfreq-table))
            (puthash (cons major-mode function) (if count (+ count 1) 1)
                     keyfreq-table))))
      (let (deactivate-mark
            (ergoemacs-single-command-keys keys))
    (remove-hook 'ergoemacs-pre-command-hook 'ergoemacs-pre-command-hook)
    (remove-hook 'ergoemacs-pre-command-hook 'ergoemacs-pre-command-hook t)
        (run-hooks 'ergoemacs-pre-command-hook)
        (call-interactively this-command record-flag keys)
        (setq ergoemacs-deactivate-mark deactivate-mark)
        (when deactivate-mark
          (setq ergoemacs-mark-active nil))))))
  (when ergoemacs-deactivate-mark
    (setq deactivate-mark ergoemacs-deactivate-mark
          ergoemacs-mark-active nil)
    (setq ergoemacs-deactivate-mark nil)))
(ergoemacs-mode 1)
lotodore commented 9 years ago

Thanks again.

The fix works great for me.

mattfidler commented 9 years ago

The next stable release will include this bug fix (so you won't need to include the function.)