Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to make selection with bar cursor the same as in browser

Tags:

emacs

I am new to emacs and trying to gradually learn it by starting from the existing browser/vscode-like text manipulation workflow.

Text selection with a mouse seemed frustrating for me at first. To fix it, I switched to the classical browser "bar" cursor style by placing (setq-default cursor-type 'bar) in the ~/.emacs.

However, it didn't solve the issue with selection, it only changed the cursor visually. In the browser, if I click on a character in the editable text area, my cursor is placed

  • before that character, if I click on the left half of the character
  • after the character, if I click on the right half of the character

In emacs, if I click on a character the cursor is always placed before the character. How I can fix that?

video illustration of clicks in browser vs emacs

like image 357
Curious Avatar asked Sep 06 '25 03:09

Curious


2 Answers

I substitute the implementation of posn-point function (defined in subr.el) with my own with advice-add. So after inserting the following code in the init file (~/.emacs.d/init.el) everything works exactly as expected. It works in emacs 27.2 but will probably break if the original implementation of posn-point or calls into it change.

(setq-default cursor-type 'bar) ;; thin cursor

(defun my-point-bol (point)
  "check if point location at the beginning of line"
  (save-excursion
    (goto-char point)
    (equal (point-at-bol) point)))

(defun my-point-eol (point)
  "check if point location at the end of line"
  (save-excursion
    (goto-char point)
    (equal (point-at-eol) point)))

(defun my-posn-point (orig-posn-point position)
  "Redefenition of standard emacs function that fixes character clicks"
  (let ((point (nth 5 position))
        (dx (car-safe (posn-object-x-y position)))
        (sx (car-safe (posn-object-width-height position)))
        (non-text-pos (posn-object position)))
    (if (and point dx sx (not non-text-pos)
             (>= dx 0) ;; fix clicks at line nubmers
             (not (my-point-eol point))) ;; fix clicks after end of line
        (let ((offset (round (/ (float dx) sx))))
          (+ point offset))
      (funcall orig-posn-point position)))) ;; for some reason doesn't work (reliably) without funcall

(advice-add 'posn-point :around #'my-posn-point)

;; enable firing mouse-movement events on pixel change instead of glyph change
;; it fixes lagging selection during dragging
(setq mouse-fine-grained-tracking t)

The idea of this code originates from the answers to the question https://emacs.stackexchange.com/questions/20279/mouse-pointer-between-characters-and-the-text-cursor-misplacement. Here, I tried to address all bugs that I found there: incorrect handling of the beginning of the line, end of the line, weird cases when the call goes to the original function instead of overloaded one, and dragging mouse selection.

like image 112
Curious Avatar answered Sep 07 '25 23:09

Curious


You might try emacs.stackexchange.com instead for general Emacs help. Mouse pointer between characters and the text cursor misplacement looks like someone who has basically the same problem as you, and there is some informative discussion as well as one code snippet which you may find helpful but I haven't tried.

like image 27
amalloy Avatar answered Sep 07 '25 23:09

amalloy