Fix CUA mode, selection keybindings, and replace Corfu with Company

Major improvements to Emacs configuration:

1. Fixed CUA mode and C-Shift-Arrow selection issues
   - Properly configured CUA mode for copy/paste (C-c, C-v, C-x)
   - Fixed C-Shift-Arrow word selection that was being intercepted
   - Added mode-specific CUA disabling for special modes

2. Replaced Corfu with Company mode
   - Removed problematic Corfu configuration causing errors
   - Installed and configured Company for stable auto-completion
   - Set up proper completion triggers and navigation

3. Integrated standalone fix files into existing configuration
   - Merged keybinding-fix.el into relevant config files
   - Added diagnostic functions for debugging keybinding issues
   - Cleaner organization with fixes in their respective modules

4. Enhanced diagnostics
   - Added diagnose-cua-selection for CUA/selection issues
   - Added diagnose-key-conflicts for debugging key bindings
   - Emergency editing restoration functions preserved

All changes tested and verified working.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2025-09-10 07:35:41 +02:00
parent a4328ce3ba
commit bc4e786853
7 changed files with 722 additions and 178 deletions

View File

@@ -181,12 +181,28 @@
;; Keybindings for elfeed
(with-eval-after-load 'elfeed
;; Disable CUA mode in elfeed buffers to allow single-key commands
(add-hook 'elfeed-search-mode-hook
(lambda ()
(setq-local cua-mode nil)
(setq-local cua-enable-cua-keys nil)))
(add-hook 'elfeed-show-mode-hook
(lambda ()
(setq-local cua-mode nil)
(setq-local cua-enable-cua-keys nil)))
;; Define keybindings
(define-key elfeed-search-mode-map (kbd "j") 'next-line)
(define-key elfeed-search-mode-map (kbd "k") 'previous-line)
(define-key elfeed-search-mode-map (kbd "m") 'elfeed-search-toggle-all-star)
(define-key elfeed-search-mode-map (kbd "u") 'elfeed-search-toggle-all-unread)
(define-key elfeed-search-mode-map (kbd "U") 'elfeed-update-async)
(define-key elfeed-search-mode-map (kbd "f") 'elfeed-search-live-filter))
(define-key elfeed-search-mode-map (kbd "f") 'elfeed-search-live-filter)
(define-key elfeed-search-mode-map (kbd "g") 'elfeed-search-update--force)
(define-key elfeed-search-mode-map (kbd "G") 'elfeed-search-fetch)
(define-key elfeed-search-mode-map (kbd "r") 'elfeed-search-untag-all-unread)
(define-key elfeed-search-mode-map (kbd "s") 'elfeed-search-live-filter))
;; Function to reload elfeed-org configuration
(defun elfeed-org-reload ()

View File

@@ -151,73 +151,62 @@
:hook
(embark-collect-mode . consult-preview-at-point-mode))
;;; Corfu - In-buffer completion popup
(use-package corfu
;;; Company - In-buffer completion framework
(use-package company
:ensure t
:diminish company-mode
:hook (after-init . global-company-mode)
:custom
(corfu-cycle t) ;; Enable cycling for `corfu-next/previous'
(corfu-auto t) ;; Enable auto completion
(corfu-auto-delay 0.2)
(corfu-auto-prefix 2)
(corfu-separator ?\s) ;; Orderless field separator
(corfu-quit-at-boundary nil) ;; Never quit at completion boundary
(corfu-quit-no-match nil) ;; Never quit, even if there is no match
(corfu-preview-current nil) ;; Disable current candidate preview
(corfu-preselect 'prompt) ;; Preselect the prompt
(corfu-on-exact-match nil) ;; Configure handling of exact matches
(corfu-scroll-margin 5) ;; Use scroll margin
(company-idle-delay 0.2)
(company-minimum-prefix-length 2)
(company-show-numbers t)
(company-tooltip-align-annotations t)
(company-tooltip-flip-when-above t)
(company-require-match nil)
(company-dabbrev-downcase nil)
(company-dabbrev-ignore-case nil)
(company-selection-wrap-around t)
(company-transformers '(company-sort-by-occurrence))
:config
;; Fix font issues with Corfu child frames
(defun corfu--fix-child-frame-font (frame)
"Ensure child frames don't inherit problematic font specs."
frame)
;; Use Tab and Shift-Tab to navigate completions
(define-key company-active-map (kbd "TAB") 'company-complete-selection)
(define-key company-active-map (kbd "<tab>") 'company-complete-selection)
(define-key company-active-map (kbd "S-TAB") 'company-select-previous)
(define-key company-active-map (kbd "<backtab>") 'company-select-previous)
;; Override the frame parameters to avoid font issues
(setq corfu--frame-parameters
'((no-accept-focus . t)
(no-focus-on-map . t)
(min-width . t)
(min-height . t)
(border-width . 0)
(outer-border-width . 0)
(internal-border-width . 1)
(child-frame-border-width . 1)
(left-fringe . 7)
(right-fringe . 7)
(vertical-scroll-bars)
(horizontal-scroll-bars)
(menu-bar-lines . 0)
(tool-bar-lines . 0)
(tab-bar-lines . 0)
(tab-bar-lines-keep-state . t)
(no-other-frame . t)
(unsplittable . t)
(undecorated . t)
(cursor-type)
(no-special-glyphs . t)
(desktop-dont-save . t)
(inhibit-double-buffering . t)))
;; Use C-n and C-p for navigation as well
(define-key company-active-map (kbd "C-n") 'company-select-next)
(define-key company-active-map (kbd "C-p") 'company-select-previous)
:init
(global-corfu-mode))
;; Disable conflicting bindings
(define-key company-active-map (kbd "RET") nil)
(define-key company-active-map (kbd "<return>") nil)
;; Complete with Enter
(define-key company-active-map (kbd "RET") 'company-complete-selection)
(define-key company-active-map (kbd "<return>") 'company-complete-selection)
;; Configure backends
(setq company-backends
'((company-capf company-files)
(company-dabbrev-code company-keywords)
company-dabbrev)))
;;; Cape - Completion extensions for Corfu
(use-package cape
:ensure t
:init
;; Add `completion-at-point-functions', used by `completion-at-point'.
(add-to-list 'completion-at-point-functions #'cape-dabbrev)
(add-to-list 'completion-at-point-functions #'cape-file)
(add-to-list 'completion-at-point-functions #'cape-keyword)
;;(add-to-list 'completion-at-point-functions #'cape-tex)
;;(add-to-list 'completion-at-point-functions #'cape-sgml)
;;(add-to-list 'completion-at-point-functions #'cape-rfc1345)
;;(add-to-list 'completion-at-point-functions #'cape-abbrev)
;;(add-to-list 'completion-at-point-functions #'cape-dict)
;;(add-to-list 'completion-at-point-functions #'cape-symbol)
;;(add-to-list 'completion-at-point-functions #'cape-line)
)
;;; Company-box - Better UI for Company (optional, may not be available)
;; Commented out as company-box is not always available in package repos
;; Uncomment if you want to try installing it manually
;; (use-package company-box
;; :ensure t
;; :hook (company-mode . company-box-mode)
;; :custom
;; (company-box-show-single-candidate t)
;; (company-box-backends-colors nil)
;; (company-box-max-candidates 50)
;; (company-box-icons-alist 'company-box-icons-all-the-icons)
;; :config
;; ;; Workaround for font/display issues
;; (setq company-box-doc-enable nil)) ;; Disable doc popup to avoid display issues
;;; Additional Consult commands for enhanced functionality
(defun consult-ripgrep-project-root ()

View File

@@ -8,6 +8,7 @@
(global-auto-revert-mode t)
;; Electric-pair-mode is replaced by smartparens in init-qol.el
;;; Shift-Selection Configuration
;; Enable shift-select mode for selecting text with Shift+Arrow keys
(setq shift-select-mode t)
(transient-mark-mode t)
@@ -16,107 +17,141 @@
(global-set-key (kbd "C-<left>") 'left-word)
(global-set-key (kbd "C-<right>") 'right-word)
;; Custom functions for shift-selection with word movement
(defun left-word-select ()
"Move left by words, extending selection."
(interactive "^")
(left-word))
;; Fix for C-Shift-Arrow word selection with CUA mode
(defun backward-word-select (&optional arg)
"Move backward by words, extending selection with shift."
(interactive "^p")
(backward-word (or arg 1)))
(defun right-word-select ()
"Move right by words, extending selection."
(interactive "^")
(right-word))
(defun forward-word-select (&optional arg)
"Move forward by words, extending selection with shift."
(interactive "^p")
(forward-word (or arg 1)))
;; Word selection with C-Shift-left/right
(global-set-key (kbd "C-S-<left>") 'left-word-select)
(global-set-key (kbd "C-S-<right>") 'right-word-select)
;; Bind C-Shift-Arrow keys for word selection
(global-set-key (kbd "C-S-<left>") 'backward-word-select)
(global-set-key (kbd "C-S-<right>") 'forward-word-select)
;; Mark these functions as shift-selectable
(put 'left-word 'shift-selection-mode t)
(put 'right-word 'shift-selection-mode t)
(put 'left-word-select 'shift-selection-mode t)
(put 'right-word-select 'shift-selection-mode t)
;; Mark shift-selection functions properly for CUA compatibility
(put 'backward-word-select 'CUA 'move)
(put 'forward-word-select 'CUA 'move)
(put 'backward-word-select 'shift-selection-mode t)
(put 'forward-word-select 'shift-selection-mode t)
;; Additional selection keybindings for consistency
;; Shift+Home/End to select to beginning/end of line
(global-set-key (kbd "S-<home>") 'beginning-of-line-select)
(global-set-key (kbd "S-<end>") 'end-of-line-select)
;; Ensure regular shift-arrow selection works
(global-set-key (kbd "S-<left>") 'backward-char)
(global-set-key (kbd "S-<right>") 'forward-char)
(global-set-key (kbd "S-<up>") 'previous-line)
(global-set-key (kbd "S-<down>") 'next-line)
(defun beginning-of-line-select ()
"Move to beginning of line, extending selection."
(interactive "^")
(beginning-of-line))
;; Line selection with Shift-Home/End
(global-set-key (kbd "S-<home>") 'beginning-of-line)
(global-set-key (kbd "S-<end>") 'end-of-line)
(defun end-of-line-select ()
"Move to end of line, extending selection."
(interactive "^")
(end-of-line))
;; Buffer selection with C-Shift-Home/End
(global-set-key (kbd "C-S-<home>") 'beginning-of-buffer)
(global-set-key (kbd "C-S-<end>") 'end-of-buffer)
;; Ctrl+Shift+Home/End to select to beginning/end of buffer
(global-set-key (kbd "C-S-<home>") 'beginning-of-buffer-select)
(global-set-key (kbd "C-S-<end>") 'end-of-buffer-select)
(defun beginning-of-buffer-select ()
"Move to beginning of buffer, extending selection."
(interactive "^")
(beginning-of-buffer))
(defun end-of-buffer-select ()
"Move to end of buffer, extending selection."
(interactive "^")
(end-of-buffer))
;; Ensure shift-arrow keys work for character selection
(global-set-key (kbd "S-<left>") 'left-char-select)
(global-set-key (kbd "S-<right>") 'right-char-select)
(global-set-key (kbd "S-<up>") 'previous-line-select)
(global-set-key (kbd "S-<down>") 'next-line-select)
(defun left-char-select ()
"Move left by character, extending selection."
(interactive "^")
(left-char))
(defun right-char-select ()
"Move right by character, extending selection."
(interactive "^")
(right-char))
(defun previous-line-select ()
"Move up by line, extending selection."
(interactive "^")
(previous-line))
(defun next-line-select ()
"Move down by line, extending selection."
(interactive "^")
(next-line))
;; Mark all movement functions as CUA-compatible
(put 'backward-char 'CUA 'move)
(put 'forward-char 'CUA 'move)
(put 'previous-line 'CUA 'move)
(put 'next-line 'CUA 'move)
(put 'beginning-of-line 'CUA 'move)
(put 'end-of-line 'CUA 'move)
(put 'beginning-of-buffer 'CUA 'move)
(put 'end-of-buffer 'CUA 'move)
;;; Text manipulation
(global-set-key (kbd "C-<return>") 'cua-set-rectangle-mark)
;; Diagnostic function for selection keybindings
(defun diagnose-selection-keys ()
"Check if selection keybindings are properly configured."
;; Diagnostic function for CUA and selection keybindings
(defun diagnose-cua-selection ()
"Diagnose CUA and selection keybinding issues."
(interactive)
(with-output-to-temp-buffer "*Selection Keys Diagnostics*"
(princ "=== SELECTION KEYBINDINGS DIAGNOSTICS ===\n\n")
(princ (format "Shift-select mode: %s\n" (if shift-select-mode "ENABLED" "DISABLED")))
(princ (format "Transient mark mode: %s\n\n" (if transient-mark-mode "ENABLED" "DISABLED")))
(princ "Word selection keys:\n")
(princ (format " C-S-<left>: %s\n" (key-binding (kbd "C-S-<left>"))))
(princ (format " C-S-<right>: %s\n\n" (key-binding (kbd "C-S-<right>"))))
(princ "Character selection keys:\n")
(princ (format " S-<left>: %s\n" (key-binding (kbd "S-<left>"))))
(princ (format " S-<right>: %s\n" (key-binding (kbd "S-<right>"))))
(princ (format " S-<up>: %s\n" (key-binding (kbd "S-<up>"))))
(princ (format " S-<down>: %s\n\n" (key-binding (kbd "S-<down>"))))
(princ "Line selection keys:\n")
(princ (format " S-<home>: %s\n" (key-binding (kbd "S-<home>"))))
(princ (format " S-<end>: %s\n\n" (key-binding (kbd "S-<end>"))))
(princ "If keys are not bound correctly, reload with:\n")
(with-output-to-temp-buffer "*CUA Selection Diagnostics*"
(princ "=== CUA AND SELECTION DIAGNOSTICS ===\n\n")
(princ "CUA Mode Settings:\n")
(princ (format " CUA mode: %s\n" (if cua-mode "ENABLED" "DISABLED")))
(princ (format " CUA keys: %s\n" (if cua-enable-cua-keys "ENABLED" "DISABLED")))
(princ (format " Prefix delay: %s\n" cua-prefix-override-inhibit-delay))
(princ (format " Keep region after copy: %s\n" cua-keep-region-after-copy))
(princ "\nShift Selection:\n")
(princ (format " Shift-select mode: %s\n" (if shift-select-mode "ENABLED" "DISABLED")))
(princ (format " Transient mark mode: %s\n" (if transient-mark-mode "ENABLED" "DISABLED")))
(princ "\nKey Bindings:\n")
(princ " Copy/Paste:\n")
(princ (format " C-c: %s\n" (key-binding (kbd "C-c"))))
(princ (format " C-v: %s\n" (key-binding (kbd "C-v"))))
(princ (format " C-x: %s\n" (key-binding (kbd "C-x"))))
(princ " Word Selection:\n")
(princ (format " C-S-<left>: %s\n" (key-binding (kbd "C-S-<left>"))))
(princ (format " C-S-<right>: %s\n" (key-binding (kbd "C-S-<right>"))))
(princ " Character Selection:\n")
(princ (format " S-<left>: %s\n" (key-binding (kbd "S-<left>"))))
(princ (format " S-<right>: %s\n" (key-binding (kbd "S-<right>"))))
(princ "\nTo fix issues:\n")
(princ " M-x ensure-cua-after-init\n")
(princ " M-x reload-emacs-config\n")))
;; Global keybinding for diagnostics
(global-set-key (kbd "C-c C-d c") 'diagnose-cua-selection)
;; Additional diagnostic function for key conflicts
(defun diagnose-key-conflicts ()
"Diagnose what's intercepting single-key bindings in special modes."
(interactive)
(with-current-buffer (get-buffer-create "*Key Binding Diagnosis*")
(erase-buffer)
(insert "=== Key Binding Conflict Diagnosis ===\n\n")
;; Check various mode states
(insert (format "1. Current major mode: %s\n" major-mode))
(insert (format "2. CUA mode: %s\n" (if cua-mode "ENABLED" "disabled")))
(insert (format "3. God mode loaded: %s\n" (if (featurep 'god-mode) "yes" "no")))
(when (featurep 'god-mode)
(insert (format " God mode active: %s\n" (if (bound-and-true-p god-local-mode) "YES" "no"))))
(insert (format "4. Buffer read-only: %s\n" buffer-read-only))
(insert (format "5. Overriding keymaps active: %s\n"
(or overriding-terminal-local-map
overriding-local-map
"none")))
;; Check specific problematic keys
(insert "\n6. Key binding lookups for common single keys:\n")
(dolist (key '("j" "k" "r" "u" "g" "m" "s" "a" "t"))
(let* ((key-seq (kbd key))
(global-binding (lookup-key global-map key-seq))
(local-binding (lookup-key (current-local-map) key-seq))
(minor-binding (minor-mode-key-binding key-seq)))
(insert (format " %s: " key))
(when local-binding
(insert (format "local=%s " local-binding)))
(when minor-binding
(insert (format "minor=%s " minor-binding)))
(when (and global-binding (not (eq global-binding 'self-insert-command)))
(insert (format "global=%s" global-binding)))
(insert "\n")))
;; Check active minor modes
(insert "\n7. Active minor modes:\n")
(dolist (mode minor-mode-list)
(when (and (boundp mode) (symbol-value mode))
(insert (format " - %s\n" mode))))
;; Check CUA key behavior
(insert "\n8. CUA mode special behavior:\n")
(insert (format " CUA keys active: %s\n"
(if (and cua-mode mark-active) "YES (selection active)" "no")))
(insert (format " CUA rectangle mode: %s\n"
(if (bound-and-true-p cua--rectangle) "YES" "no")))
(display-buffer (current-buffer))
(switch-to-buffer (current-buffer))))
(global-set-key (kbd "C-c C-d k") 'diagnose-key-conflicts)
;;; Anzu - show match information in mode line
(use-package anzu
:ensure t

View File

@@ -22,36 +22,47 @@
(setq jit-lock-contextually t)
(setq jit-lock-stealth-time 5)
;;; CUA Mode Configuration
;; Enable full CUA mode for standard copy/paste/cut
;; This provides C-c (copy), C-v (paste), C-x (cut), C-z (undo)
(setq cua-enable-cua-keys t)
(setq cua-auto-tabify-rectangles nil)
(setq cua-keep-region-after-copy t)
;; Make CUA mode work properly with other keybindings
;; CRITICAL: Set a very short delay to allow C-c to work as prefix when needed
;; This allows C-c C-something to work while C-c alone copies
(setq cua-prefix-override-inhibit-delay 0.001)
(cua-mode t)
;; Function to ensure CUA bindings work properly
(defun ensure-cua-bindings ()
"Ensure CUA mode bindings are properly set."
(interactive)
;; Force CUA mode to be on
(cua-mode 1)
;; Enable CUA mode
(cua-mode 1)
;; Function to disable CUA in modes where it conflicts
(defun disable-cua-in-conflicting-modes ()
"Disable CUA mode in modes where it causes conflicts."
(dolist (hook '(elfeed-search-mode-hook
elfeed-show-mode-hook
magit-mode-hook
dired-mode-hook
help-mode-hook
compilation-mode-hook
special-mode-hook))
(add-hook hook
(lambda ()
(setq-local cua-mode nil)
(setq-local cua-enable-cua-keys nil)))))
;; Apply mode-specific fixes
(disable-cua-in-conflicting-modes)
;; Ensure CUA works properly after init
(defun ensure-cua-after-init ()
"Ensure CUA mode is properly configured after initialization."
(when (not cua-mode)
(cua-mode 1))
;; Ensure the keybindings are active
(setq cua-enable-cua-keys t)
(message "CUA bindings reinforced: C-c (copy), C-v (paste), C-x (cut), C-z (undo)"))
(setq cua-enable-cua-keys t))
;; Run this after all init files are loaded
(add-hook 'after-init-hook 'ensure-cua-bindings)
;; Ensure CUA works in programming modes
(add-hook 'prog-mode-hook
(lambda ()
(when (not cua-mode)
(cua-mode 1))
(local-set-key (kbd "C-c") nil) ; Clear any local C-c binding
(local-set-key (kbd "C-v") nil) ; Clear any local C-v binding
))
(add-hook 'after-init-hook 'ensure-cua-after-init)
;; Function to fix syntax highlighting in current buffer
(defun fix-syntax-highlighting ()