* bug#74438: 29.1; global-mark-ring does not work as described
@ 2024-11-19 20:24 Sean McAfee
2024-11-20 10:18 ` Nikolay Kudryavtsev
0 siblings, 1 reply; 13+ messages in thread
From: Sean McAfee @ 2024-11-19 20:24 UTC (permalink / raw)
To: 74438
[-- Attachment #1: Type: text/plain, Size: 16442 bytes --]
Starting from emacs -Q:
- Go to a new buffer named "foo".
- Set the mark with C-SPC.
- Go to a new buffer named "bar".
- Set the mark with C-SPC.
- Go back to buffer foo.
- Set the mark with C-SPC.
- Check the value of the global-mark-ring variable, as with C-h v
or giving its name to the eval-expression command.
The first marker in the ring is the one in buffer bar, not in
buffer foo, even though buffer foo is where the mark was most
recently set. This behavior contradicts what is described here:
https://www.gnu.org/software/emacs/manual/html_node/emacs/Global-Mark-Ring.html
To wit: "Each time you set a mark, this is recorded in the global mark
ring in addition to the current buffer’s own mark ring, if you have
switched buffers since the previous mark setting."
I've tracked the reason for this to the push-mark-command function,
which does not push the mark unless it's not at the same place as point,
or if it's given a true argument. set-mark-command calls
push-mark-command, but passes nil to it unless, puzzlingly, the
command's name is not "set-mark-command".
For a bit of background, what I want to do is to set the mark at the
beginning of a sexp (actually JSON) in one buffer, then go to the start
of another sexp in a different buffer, and run a command that compares
the two sexps, using the marker at the front of the global mark ring to
find the first sexp. But this is unreliable since setting the mark does
not necessarily update the global mark ring. Workarounds I've
considered include:
- Call push-mark-command manually with M-x, or bind it to a key
sequence, and call it with a prefix argument.
- Alias set-mark-command as a new command with a different name, and use
that instead.
- Use a custom marker, updated from a custom command.
Obviously, none of these are as convenient as using the global mark
ring. And in any event, there's still a bug in Emacs, even if only a
documentation bug.
In GNU Emacs 29.1 (build 1, aarch64-apple-darwin21.6.0, NS
appkit-2113.60 Version 12.6.6 (Build 21G646)) of 2023-08-16 built on
armbob.lan
Windowing system distributor 'Apple', version 10.3.2487
System Description: macOS 14.7.1
Configured using:
'configure --with-ns '--enable-locallisppath=/Library/Application
Support/Emacs/${version}/site-lisp:/Library/Application
Support/Emacs/site-lisp' --with-modules 'CFLAGS=-DFD_SETSIZE=10000
-DDARWIN_UNLIMITED_SELECT' --with-x-toolkit=no'
Configured features:
ACL GLIB GMP GNUTLS JPEG JSON LIBXML2 MODULES NOTIFY KQUEUE NS PDUMPER
PNG RSVG SQLITE3 THREADS TIFF TOOLKIT_SCROLL_BARS TREE_SITTER ZLIB
Important settings:
value of $LANG: en_US.UTF-8
locale-coding-system: utf-8-unix
Major mode: ELisp/l
Minor modes in effect:
recentf-mode: t
emms-mode-line-mode: t
emms-playing-time-display-mode: t
emms-playing-time-mode: t
tracking-mode: t
volatile-highlights-mode: t
projectile-mode: t
elisp-slime-nav-mode: t
global-git-commit-mode: t
magit-auto-revert-mode: t
auto-revert-mode: t
shell-dirtrack-mode: t
server-mode: t
global-flycheck-mode: t
flycheck-mode: t
minibuffer-depth-indicate-mode: t
ido-vertical-mode: t
global-undo-tree-mode: t
undo-tree-mode: t
paredit-mode: t
override-global-mode: t
desktop-save-mode: t
winner-mode: t
electric-pair-mode: t
savehist-mode: t
ido-everywhere: t
tooltip-mode: t
global-eldoc-mode: t
eldoc-mode: t
show-paren-mode: t
electric-indent-mode: t
mouse-wheel-mode: t
global-prettify-symbols-mode: t
prettify-symbols-mode: t
menu-bar-mode: t
file-name-shadow-mode: t
global-font-lock-mode: t
font-lock-mode: t
blink-cursor-mode: t
line-number-mode: t
transient-mark-mode: t
auto-composition-mode: t
auto-encryption-mode: t
auto-compression-mode: t
Load-path shadows:
~/emacs/copilot.el/copilot hides ~/emacs/copilot
~/emacs/inf-ruby/inf-ruby hides
/Users/sean/.emacs.d/elpa/inf-ruby-20240925.49/inf-ruby
/Users/sean/.emacs.d/elpa/transient-20241023.1537/transient hides
/Applications/Emacs 3.app/Contents/Resources/lisp/transient
/Users/sean/.emacs.d/elpa/use-package-20230426.2324/use-package-jump hides
/Applications/Emacs
3.app/Contents/Resources/lisp/use-package/use-package-jump
/Users/sean/.emacs.d/elpa/use-package-20230426.2324/use-package-ensure
hides /Applications/Emacs
3.app/Contents/Resources/lisp/use-package/use-package-ensure
/Users/sean/.emacs.d/elpa/use-package-20230426.2324/use-package-core hides
/Applications/Emacs
3.app/Contents/Resources/lisp/use-package/use-package-core
/Users/sean/.emacs.d/elpa/use-package-20230426.2324/use-package-delight
hides /Applications/Emacs
3.app/Contents/Resources/lisp/use-package/use-package-delight
/Users/sean/.emacs.d/elpa/use-package-20230426.2324/use-package-diminish
hides /Applications/Emacs
3.app/Contents/Resources/lisp/use-package/use-package-diminish
/Users/sean/.emacs.d/elpa/use-package-20230426.2324/use-package hides
/Applications/Emacs 3.app/Contents/Resources/lisp/use-package/use-package
/Users/sean/.emacs.d/elpa/use-package-20230426.2324/use-package-bind-key
hides /Applications/Emacs
3.app/Contents/Resources/lisp/use-package/use-package-bind-key
/Users/sean/.emacs.d/elpa/bind-key-20230203.2004/bind-key hides
/Applications/Emacs 3.app/Contents/Resources/lisp/use-package/bind-key
/Users/sean/.emacs.d/elpa/use-package-20230426.2324/use-package-lint hides
/Applications/Emacs
3.app/Contents/Resources/lisp/use-package/use-package-lint
/Users/sean/.emacs.d/elpa/flim-20240221.1353/sasl hides /Applications/Emacs
3.app/Contents/Resources/lisp/net/sasl
/Users/sean/.emacs.d/elpa/seq-2.24/seq hides /Applications/Emacs
3.app/Contents/Resources/lisp/emacs-lisp/seq
/Users/sean/.emacs.d/elpa/eldoc-1.15.0/eldoc hides /Applications/Emacs
3.app/Contents/Resources/lisp/emacs-lisp/eldoc
Features:
(shadow mail-extr emacsbug japan-util kkc ja-dic-utl quail url-cache
pulse vc-annotate expand-region subword-mode-expansions
text-mode-expansions cc-mode-expansions the-org-mode-expansions
ruby-mode-expansions python-el-fgallina-expansions js2-mode-expansions
js-mode-expansions html-mode-expansions css-mode-expansions
er-basic-expansions expand-region-core expand-region-custom
mc-edit-lines goto-addr ag find-dired tabify org-datetree org-capture
sh-script display-line-numbers delsel tramp-sh completion docker-tramp
tramp-cache tramp tramp-loaddefs trampver tramp-integration files-x
tramp-compat elnode db web time-stamp fakir dotassoc kv noflet cl-indent
cl-print magit-bookmark bookmark shortdoc help-fns radix-tree recentf
tree-widget misearch multi-isearch executable vc-hg vc-bzr vc-src
vc-sccs vc-svn vc-cvs vc-rcs log-view bug-reference magit-extras
face-remap emojify apropos tar-mode arc-mode archive-mode ht
network-stream slack slack-company slack-unread slack-websocket
slack-thread-event slack-room-event slack-star-event
slack-reaction-event slack-reply-event slack-typing slack-slash-commands
slack-message-event slack-event slack-dialog-edit-element-buffer
slack-dialog-buffer slack-dialog slack-stars-buffer
slack-search-result-buffer slack-thread-message-compose-buffer
slack-file-list-buffer slack-file-info-buffer slack-all-threads-buffer
slack-message-buffer slack-user-profile-buffer slack-pinned-items-buffer
slack-pinned-item slack-thread-message-buffer slack-room-info-buffer
slack-room-buffer slack-message-share-buffer slack-message-edit-buffer
slack-room-message-compose-buffer slack-message-compose-buffer
slack-message-attachment-preview-buffer slack-action slack-star
slack-reminder slack-search slack-message-reaction slack-message-editor
slack-message-sender slack-message-notification alert log4e
notifications gntp slack-buffer slack-message-formatter slack-thread
slack-im slack-channel slack-group slack-conversations
slack-create-message slack-attachment slack-selectable slack-bot-message
slack-user-message slack-file slack-message slack-message-faces
slack-unescape slack-block slack-mrkdwn slack-usergroup slack-reaction
slack-modeline slack-room slack-counts slack-user slack-bot
slack-dnd-status slack-emoji slack-image slack-request slack-log lui
flyspell ispell slack-team slack-team-ws slack-util websocket diary-lib
diary-loaddefs json-mode json-snatcher css-mode color sql view
java-ts-mode yaml-ts-mode restclient smartparens-python python cap-words
superword subword smartparens-scala scala-mode
scala-mode-prettify-symbols scala-mode-imenu scala-mode-map
scala-mode-fontlock scala-mode-indent scala-mode-paragraph
scala-mode-syntax scala-mode-lib kotlin-mode kotlin-mode-indent
kotlin-mode-lexer org-bullets oc-basic org-element org-persist org-id
org-refile avl-tree ol-eww eww xdg url-queue mm-url ol-rmail ol-mhe
ol-irc ol-info ol-gnus nnselect gnus-art mm-uu mml2015 mm-view mml-smime
smime dig gnus-sum shr pixel-fill kinsoku url-file svg gnus-group
gnus-undo gnus-start gnus-dbus gnus-cloud nnimap nnmail mail-source utf7
nnoo parse-time gnus-spec gnus-int gnus-range gnus-win ol-docview
doc-view jka-compr image-mode exif ol-bibtex bibtex iso8601 ol-bbdb
ol-w3m ol-doi org-link-doi smartparens-org org org-macro org-pcomplete
org-list org-footnote org-faces org-entities noutline outline
ob-emacs-lisp org-table org-loaddefs cal-menu calendar cal-loaddefs
ruby-ts-mode gnus-dired perl6-detect copilot editorconfig
editorconfig-core editorconfig-core-handle editorconfig-fnmatch jsonrpc
ert ewoc debug backtrace warnings emms-idapi-browser emms-idapi
emms-idapi-musicbrainz emms-mpris dbus emms-librefm-stream xml
emms-librefm-scrobbler emms-playlist-limit emms-i18n emms-history
emms-score emms-stream-info emms-metaplaylist-mode emms-bookmarks
emms-cue emms-mode-line-icon emms-browser sort emms-volume
emms-volume-sndioctl emms-volume-mixerctl emms-volume-pulse
emms-volume-amixer emms-playlist-sort emms-last-played emms-player-xine
emms-player-mpd tq emms-lyrics emms-url emms-streams emms-show-all
emms-tag-editor emms-tag-tracktag emms-mark emms-mode-line emms-cache
emms-info-native emms-info-native-spc emms-info-native-mp3
emms-info-native-ogg emms-info-native-opus emms-info-native-flac
emms-info-native-vorbis bindat emms-info-exiftool emms-info-tinytag
emms-info-metaflac emms-info-opusinfo emms-info-ogginfo
emms-info-mp3info emms-playlist-mode emms-player-vlc emms-player-mpv
emms-playing-time emms-info emms-later-do emms-player-mplayer
emms-player-simple emms-source-playlist emms-source-file locate
emms-setup emms emms-compat scribd-sentry scribd-airflow scribd-github
request scribd-devkube scribd-aws ob-ruby ob ob-tangle ol org-src ob-ref
ob-lob ob-table ob-exp ob-comint ob-core org-cycle org-fold
org-fold-core ob-eval org-keys oc org-compat org-version org-macs hmac
csv let-alist smartparens-config smartparens-javascript smartparens-text
smartparens-ruby smartparens-html smartparens-c smartparens loadhist
robe url-http url-auth url-gw nsm inf-ruby ruby-mode smie git-link
yasnippet git-timemachine vc-git whitespace dash-functional gnutls
tracking shorten ibuf-macs chruby treesit-auto xref-js2 vc vc-dispatcher
js2-mode js c-ts-common treesit cc-mode cc-fonts cc-guess cc-menus
cc-cmds cc-styles cc-align cc-engine cc-vars cc-defs dired-filter f
dired-hacks-utils dired-aux dired-x shell-pop term disp-table ehelp
beginend volatile-highlights iedit iedit-lib
mc-hide-unmatched-lines-mode mc-mark-more tagedit s sgml-mode facemenu
dom mc-cycle-cursors multiple-cursors-core rect dtrt-indent advice
projectile lisp-mnt grep ibuf-ext ibuffer ibuffer-loaddefs
elisp-slime-nav etags fileloop generator xref project magit-submodule
magit-blame magit-stash magit-reflog magit-bisect magit-push magit-pull
magit-fetch magit-clone magit-remote magit-commit magit-sequence
magit-notes magit-worktree magit-tag magit-merge magit-branch
magit-reset magit-files magit-refs magit-status magit magit-repos
magit-apply magit-wip magit-log which-func imenu magit-diff smerge-mode
diff-mode git-commit log-edit message sendmail yank-media puny dired
dired-loaddefs rfc822 mml mml-sec epa derived mm-decode mm-bodies
mm-encode mail-parse rfc2231 rfc2047 rfc2045 ietf-drums mailabbrev
gmm-utils mailheader pcvs-util add-log magit-core magit-autorevert
autorevert filenotify magit-margin magit-transient magit-process
with-editor shell pcomplete server magit-mode transient benchmark
magit-git magit-base magit-section format-spec cursor-sensor crm compat
compat-30 ido-completing-read+ memoize cus-edit pp icons minibuf-eldef
flycheck find-func diminish gnus nnheader gnus-util time-date mail-utils
range mm-util mail-prsvr wid-edit autoinsert misc hl-line cus-load
mb-depth ido-vertical-mode undo-tree diff ack compile
text-property-search paredit edmacro kmacro dash cl-extra help-mode
use-package use-package-ensure use-package-delight use-package-diminish
use-package-bind-key bind-key easy-mmode use-package-core desktop
frameset finder-inf winner elec-pair savehist hippie-exp comint ansi-osc
ansi-color ring thingatpt ido cl company-autoloads counsel-autoloads
csv-autoloads cyberpunk-theme-autoloads dired-filter-autoloads
dired-launch-autoloads dired-ranger-autoloads
dired-hacks-utils-autoloads docker-autoloads dtrt-indent-autoloads
editorconfig-autoloads ein-autoloads anaphora-autoloads emms-autoloads
enh-ruby-mode-autoloads expand-region-autoloads fix-word
flycheck-autoloads folding-autoloads ghub-autoloads git-link-autoloads
git-timemachine-autoloads epg rfc6068 epg-config gnu-elpa-keyring-update
go-mode-autoloads helm-swoop-autoloads helm-autoloads
helm-core-autoloads async-autoloads htmlize-autoloads
ido-completing-read+-autoloads inf-ruby-autoloads json-mode-autoloads
lsp-metals-autoloads dap-mode-autoloads lsp-docker-autoloads
lsp-treemacs-autoloads lsp-ui-autoloads lsp-mode-autoloads f-autoloads
magit-autoloads pcase magit-section-autoloads markdown-mode-autoloads
multiple-cursors-autoloads paredit-autoloads pcre2el-autoloads
pdf-tools-autoloads rx polymode-autoloads popup-autoloads
projectile-autoloads protobuf-mode-autoloads sbt-mode-autoloads
scala-mode-autoloads semi-autoloads flim-autoloads apel-autoloads
shell-pop-autoloads log4e-autoloads circe-autoloads oauth2-autoloads
smartparens-autoloads swift-mode-autoloads swiper-autoloads
ivy-autoloads terraform-mode-autoloads hcl-mode-autoloads
transient-autoloads treemacs-autoloads posframe-autoloads
treepy-autoloads treesit-auto-autoloads volatile-highlights-autoloads
dash-autoloads web-mode-autoloads wfnames-autoloads
with-editor-autoloads info compat-autoloads xref-js2-autoloads
js2-mode-autoloads yaml-mode-autoloads yasnippet-autoloads
zenburn-theme-autoloads package browse-url url url-proxy url-privacy
url-expand url-methods url-history url-cookie generate-lisp-file
url-domsuf url-util mailcap url-handlers url-parse auth-source cl-seq
eieio eieio-core cl-macs password-cache json subr-x map byte-opt gv
bytecomp byte-compile url-vars cl-loaddefs cl-lib rmc iso-transl tooltip
cconv eldoc paren electric uniquify ediff-hook vc-hooks lisp-float-type
elisp-mode mwheel term/ns-win ns-win ucs-normalize mule-util
term/common-win tool-bar dnd fontset image regexp-opt fringe
tabulated-list replace newcomment text-mode lisp-mode prog-mode register
page tab-bar menu-bar rfn-eshadow isearch easymenu timer select
scroll-bar mouse jit-lock font-lock syntax font-core term/tty-colors
frame minibuffer nadvice seq simple cl-generic indonesian philippine
cham georgian utf-8-lang misc-lang vietnamese tibetan thai tai-viet lao
korean japanese eucjp-ms cp51932 hebrew greek romanian slovak czech
european ethiopic indian cyrillic chinese composite emoji-zwj charscript
charprop case-table epa-hook jka-cmpr-hook help abbrev obarray oclosure
cl-preloaded button loaddefs theme-loaddefs faces cus-face macroexp
files window text-properties overlay sha1 md5 base64 format env
code-pages mule custom widget keymap hashtable-print-readable backquote
threads kqueue cocoa ns multi-tty make-network-process emacs)
Memory information:
((conses 16 7653353 1099840)
(symbols 48 86385 1)
(strings 32 645539 137118)
(string-bytes 1 21255905)
(vectors 16 363777)
(vector-slots 8 11459569 492070)
(floats 8 4731 140)
(intervals 56 408064 16183)
(buffers 984 303))
[-- Attachment #2: Type: text/html, Size: 18335 bytes --]
^ permalink raw reply [flat|nested] 13+ messages in thread
* bug#74438: 29.1; global-mark-ring does not work as described
2024-11-19 20:24 bug#74438: 29.1; global-mark-ring does not work as described Sean McAfee
@ 2024-11-20 10:18 ` Nikolay Kudryavtsev
2024-11-20 14:35 ` Eli Zaretskii
2024-11-20 19:16 ` Sean McAfee
0 siblings, 2 replies; 13+ messages in thread
From: Nikolay Kudryavtsev @ 2024-11-20 10:18 UTC (permalink / raw)
To: Sean McAfee, 74438
[-- Attachment #1: Type: text/plain, Size: 933 bytes --]
Emacs won't allow you to set multiple marks in the same position, it's
just going to activate the current mark. Hence your reproduction recipe
can be simplified to:
1. C-x C-f foo
2. C-SPC => Mark set
3. C-SPC => Mark deactivated
4. C-SPC => Mark activated
5. C-SPC => Mark deactivated
6. C-SPC => Mark activated
See how you're not getting "Mark set" any time after the first message?
Maybe a couple of sentences should be added to the manual regarding this
behavior, because mark ring is often a source of confusion for the new
users.
Also note that the manual recommends you deactivate the mark before
trying to jump to it:
https://www.gnu.org/software/emacs/manual/html_node/emacs/Setting-Mark.html
"Instead of setting the mark in order to operate on a region, you can
also use it to remember a position in the buffer (by typing ‘C-<SPC>
C-<SPC>’), and later jump back there (by typing ‘C-u C-<SPC>’)."
[-- Attachment #2: Type: text/html, Size: 1428 bytes --]
^ permalink raw reply [flat|nested] 13+ messages in thread
* bug#74438: 29.1; global-mark-ring does not work as described
2024-11-20 10:18 ` Nikolay Kudryavtsev
@ 2024-11-20 14:35 ` Eli Zaretskii
2024-11-21 7:51 ` Nikolay Kudryavtsev
2024-11-20 19:16 ` Sean McAfee
1 sibling, 1 reply; 13+ messages in thread
From: Eli Zaretskii @ 2024-11-20 14:35 UTC (permalink / raw)
To: Nikolay Kudryavtsev; +Cc: 74438, eefacm
> From: Nikolay Kudryavtsev <nikolay.kudryavtsev@gmail.com>
> Date: Wed, 20 Nov 2024 13:18:00 +0300
>
> Emacs won't allow you to set multiple marks in the same position, it's just going to activate the current mark.
> Hence your reproduction recipe can be simplified to:
>
> 1 C-x C-f foo
> 2 C-SPC => Mark set
> 3 C-SPC => Mark deactivated
> 4 C-SPC => Mark activated
> 5 C-SPC => Mark deactivated
> 6 C-SPC => Mark activated
>
> See how you're not getting "Mark set" any time after the first message?
Yes, technically, it doesn't set a mark, it just activates the
existing mark. And the global-mark-ring section says that Emacs
pushes a mark on the ring when it sets the mark in some buffer. Which
is not what happens here.
> Maybe a couple of sentences should be added to the manual regarding this behavior, because mark ring is
> often a source of confusion for the new users.
If you can tell what are the confusions, I could work on clarifying
them.
^ permalink raw reply [flat|nested] 13+ messages in thread
* bug#74438: 29.1; global-mark-ring does not work as described
2024-11-20 14:35 ` Eli Zaretskii
@ 2024-11-21 7:51 ` Nikolay Kudryavtsev
2024-11-21 9:49 ` Eli Zaretskii
0 siblings, 1 reply; 13+ messages in thread
From: Nikolay Kudryavtsev @ 2024-11-21 7:51 UTC (permalink / raw)
To: Eli Zaretskii; +Cc: 74438, eefacm
[-- Attachment #1: Type: text/plain, Size: 199 bytes --]
Probably just needs a sentence to this end somewhere in "The Mark Ring"
node, akin to this:
If you set the mark at a position, you cannot immediately set
another mark at the same position.
[-- Attachment #2: Type: text/html, Size: 414 bytes --]
^ permalink raw reply [flat|nested] 13+ messages in thread
* bug#74438: 29.1; global-mark-ring does not work as described
2024-11-21 7:51 ` Nikolay Kudryavtsev
@ 2024-11-21 9:49 ` Eli Zaretskii
0 siblings, 0 replies; 13+ messages in thread
From: Eli Zaretskii @ 2024-11-21 9:49 UTC (permalink / raw)
To: Nikolay Kudryavtsev; +Cc: 74438, eefacm
> From: Nikolay Kudryavtsev <nikolay.kudryavtsev@gmail.com>
> Date: Thu, 21 Nov 2024 10:51:14 +0300
> Cc: eefacm@gmail.com, 74438@debbugs.gnu.org
>
> Probably just needs a sentence to this end somewhere in "The Mark Ring" node, akin to this:
>
> If you set the mark at a position, you cannot immediately set another mark at the same position.
Thanks. I mentioned this where set-mark-command is described, as that
seemed like a better place. I also added a node to Global Mark Ring
that merely activating a mark doesn't record it in the global ring.
^ permalink raw reply [flat|nested] 13+ messages in thread
* bug#74438: 29.1; global-mark-ring does not work as described
2024-11-20 10:18 ` Nikolay Kudryavtsev
2024-11-20 14:35 ` Eli Zaretskii
@ 2024-11-20 19:16 ` Sean McAfee
2024-11-21 8:09 ` Nikolay Kudryavtsev
1 sibling, 1 reply; 13+ messages in thread
From: Sean McAfee @ 2024-11-20 19:16 UTC (permalink / raw)
To: 74438
[-- Attachment #1: Type: text/plain, Size: 718 bytes --]
On Wed, Nov 20, 2024 at 2:18 AM Nikolay Kudryavtsev <
nikolay.kudryavtsev@gmail.com> wrote:
> Emacs won't allow you to set multiple marks in the same position, it's
> just going to activate the current mark.
>
I don't want to set multiple marks in the same position though. I just
want to be able to know in which buffer I most recently set a mark. I
expected that the first element in global-mark-ring would tell me, but it
doesn't, not reliably, because if the mark already happens to be at the
place I run set-mark-command, the ring is not updated, and the first
element may refer to some other buffer. That may be the "correct" behavior
by some standard, but it doesn't match the documentation.
[-- Attachment #2: Type: text/html, Size: 1081 bytes --]
^ permalink raw reply [flat|nested] 13+ messages in thread
* bug#74438: 29.1; global-mark-ring does not work as described
2024-11-20 19:16 ` Sean McAfee
@ 2024-11-21 8:09 ` Nikolay Kudryavtsev
2024-11-21 19:49 ` Sean McAfee
0 siblings, 1 reply; 13+ messages in thread
From: Nikolay Kudryavtsev @ 2024-11-21 8:09 UTC (permalink / raw)
To: Sean McAfee, 74438
Using the mark ring for programming purposes is generally seen as a faux
pas, see the docstrings for push-mark and set-mark, which explicitly
warn against this.
If you still insist, then nothing is really stopping you from short
circuiting this behavior by say doing a forward-char, set-mark,
backward-char, set-mark again.
But I also don't understand why do you need buffer 1 mark to be at the
front of the ring, because it's gonna reliably be as the second element
in it anyway.
^ permalink raw reply [flat|nested] 13+ messages in thread
* bug#74438: 29.1; global-mark-ring does not work as described
2024-11-21 8:09 ` Nikolay Kudryavtsev
@ 2024-11-21 19:49 ` Sean McAfee
2024-11-21 20:32 ` Nikolay Kudryavtsev
0 siblings, 1 reply; 13+ messages in thread
From: Sean McAfee @ 2024-11-21 19:49 UTC (permalink / raw)
To: 74438
[-- Attachment #1: Type: text/plain, Size: 2216 bytes --]
On Thu, Nov 21, 2024 at 12:09 AM Nikolay Kudryavtsev <
nikolay.kudryavtsev@gmail.com> wrote:
> Using the mark ring for programming purposes is generally seen as a faux
> pas, see the docstrings for push-mark and set-mark, which explicitly
> warn against this.
>
I've read those warnings, which seem to be about using the mark to keep
track of positions within a single function execution. Here I'm writing a
command that wants to use information recorded by a previous command, which
seems like a legitimate use to me.
> If you still insist, then nothing is really stopping you from short
> circuiting this behavior by say doing a forward-char, set-mark,
> backward-char, set-mark again.
>
I could do that, but conceptually I just want to set the mark, and I don't
want to have to perpetually keep in mind that when I set the mark in this
one specific context, I need to go through an extended routine like that.
> But I also don't understand why do you need buffer 1 mark to be at the
> front of the ring, because it's gonna reliably be as the second element
> in it anyway.
>
But it won't; it could be anywhere in the global mark ring.
- Go to a new buffer foo and press C-SPC; now buffer foo is first in the
global mark ring.
- Go to a new buffer bar and press C-SPC; now buffer foo is second in the
ring.
- Go to a new buffer baz and press C-SPC; now buffer foo is third in the
ring.
- Go back to buffer foo and press C-SPC; buffer foo is still third in the
ring.
And buffer foo won't be in the ring at all if more than
global-mark-ring-max buffers are visited in this way.
Anyway, it seems like a consensus is emerging that it's the documentation
and not the code that needs to be updated. At least I've thought of a way
to get the info I need without changing my workflow. Something like:
(defvar last-global-mark (make-marker))
(defun my-set-mark-command (arg)
(interactive "P")
(set-mark-command arg)
(unless (equal arg '(4))
(set-marker last-global-mark (point))))
(global-set-key [remap set-mark-command] #'my-set-mark-command)
I wish it weren't necessary, but at least it's not very long.
[-- Attachment #2: Type: text/html, Size: 3173 bytes --]
^ permalink raw reply [flat|nested] 13+ messages in thread
* bug#74438: 29.1; global-mark-ring does not work as described
2024-11-21 19:49 ` Sean McAfee
@ 2024-11-21 20:32 ` Nikolay Kudryavtsev
2024-11-21 21:03 ` Sean McAfee
0 siblings, 1 reply; 13+ messages in thread
From: Nikolay Kudryavtsev @ 2024-11-21 20:32 UTC (permalink / raw)
To: Sean McAfee, 74438
I still don't understand why do you need more than one mark for your use
case?
You are comparing two sexps. You put the foo buffer sexp position into
the mark ring. Now you go to the bar buffer and select the sexp there.
Why do you need to put the bar into the mark ring? Why do you need the
second foo mark? You can just use the first(and only) foo mark and be
done with it.
^ permalink raw reply [flat|nested] 13+ messages in thread
* bug#74438: 29.1; global-mark-ring does not work as described
2024-11-21 20:32 ` Nikolay Kudryavtsev
@ 2024-11-21 21:03 ` Sean McAfee
2024-11-22 12:39 ` Nikolay Kudryavtsev
0 siblings, 1 reply; 13+ messages in thread
From: Sean McAfee @ 2024-11-21 21:03 UTC (permalink / raw)
To: 74438
[-- Attachment #1: Type: text/plain, Size: 1616 bytes --]
On Thu, Nov 21, 2024 at 12:32 PM Nikolay Kudryavtsev <
nikolay.kudryavtsev@gmail.com> wrote:
> I still don't understand why do you need more than one mark for your use
> case?
>
> You are comparing two sexps. You put the foo buffer sexp position into
> the mark ring. Now you go to the bar buffer and select the sexp there.
> Why do you need to put the bar into the mark ring? Why do you need the
> second foo mark? You can just use the first(and only) foo mark and be
> done with it.
>
Er...yeah. That's exactly what I want to do. Not sure how I gave a
different impression.
Here's what I have now, minus some defensive coding to keep it short:
;; Helper function:
(defun write-sexp-at (pos dest-file)
(write-region pos (save-excursion (goto-char pos) (forward-sexp)
(point)) dest-file))
(defun json-diff ()
(interactive)
(let ((file-a (make-temp-file "json-diff"))
(file-b (make-temp-file "json-diff")))
(with-current-buffer (marker-buffer last-global-mark)
(write-sexp-at (marker-position last-global-mark) file-a))
(write-sexp-at (point) file-b)
(shell-command (format "~/bin/json-diff %s %s" file-a file-b))))
Originally I tried using (car global-mark-ring) instead of
last-global-mark, but that doesn't work, per my original bug report. I
also tried saying (mark t) instead of (marker-position (car
global-mark-ring)). That would have returned the correct position, but it
doesn't matter because (marker-buffer (car global-mark-ring)) can't be
relied upon to return the right buffer.
[-- Attachment #2: Type: text/html, Size: 2211 bytes --]
^ permalink raw reply [flat|nested] 13+ messages in thread
* bug#74438: 29.1; global-mark-ring does not work as described
2024-11-21 21:03 ` Sean McAfee
@ 2024-11-22 12:39 ` Nikolay Kudryavtsev
2024-11-22 18:48 ` Sean McAfee
0 siblings, 1 reply; 13+ messages in thread
From: Nikolay Kudryavtsev @ 2024-11-22 12:39 UTC (permalink / raw)
To: Sean McAfee, 74438
Sorry, but your code does not demonstrate at what points you're pushing
the mark(s). If you get the file-a marker before doing any write
operations, you should be safe:
(defun json-diff ()
(interactive)
(let ((buffer-a (find-file (make-temp-file "json-diff"))))
(with-current-buffer buffer-a (push-mark))
;; At this point we presumably no longer have the mark for buffer-a
for some reason
(let ((first-mark (car global-mark-ring)))
(with-current-buffer (marker-buffer first-mark)
(message (format "Working with %s at %s" (buffer-file-name
(current-buffer)) (marker-position first-mark)))))))
But be aware that you're never really safe if you're relying on the mark
ring here. If json-diff is an interactive command, nothing is stopping
the user from pushing another mark to the ring in between of specifying
file-a and file-b. Even worse if you're trying to get something from the
previous command(as you said in the letter before), because you can
never be sure what the previous command was and what it did.
Also, I don't know where did you get the last-global-mark thing, it's
not something that's in the Emacs 29 or 30's core.
^ permalink raw reply [flat|nested] 13+ messages in thread
* bug#74438: 29.1; global-mark-ring does not work as described
2024-11-22 12:39 ` Nikolay Kudryavtsev
@ 2024-11-22 18:48 ` Sean McAfee
2024-11-22 21:16 ` Nikolay Kudryavtsev
0 siblings, 1 reply; 13+ messages in thread
From: Sean McAfee @ 2024-11-22 18:48 UTC (permalink / raw)
To: 74438
[-- Attachment #1: Type: text/plain, Size: 1069 bytes --]
On Fri, Nov 22, 2024 at 4:39 AM Nikolay Kudryavtsev <
nikolay.kudryavtsev@gmail.com> wrote:
> But be aware that you're never really safe if you're relying on the mark
> ring here. If json-diff is an interactive command, nothing is stopping
> the user from pushing another mark to the ring in between of specifying
> file-a and file-b.
Yes. The command is intended to be used after setting a mark at the start
of a JSON sexp and moving to the start of a JSON sexp somewhere else, and
doing nothing else in between.
> Also, I don't know where did you get the last-global-mark thing, it's
> not something that's in the Emacs 29 or 30's core.
>
Indeed not. It's from the workaround I described in this thread just
yesterday.
Welp, I'm done. I've invested more effort into this bug report than I ever
thought would be necessary. It's the second time in a row that I've
reported a bug to a free software project and had it devolve into me having
to defend my use case. Fix the code or the docs, or don't. I'll just use
my workaround.
[-- Attachment #2: Type: text/html, Size: 1650 bytes --]
^ permalink raw reply [flat|nested] 13+ messages in thread
* bug#74438: 29.1; global-mark-ring does not work as described
2024-11-22 18:48 ` Sean McAfee
@ 2024-11-22 21:16 ` Nikolay Kudryavtsev
0 siblings, 0 replies; 13+ messages in thread
From: Nikolay Kudryavtsev @ 2024-11-22 21:16 UTC (permalink / raw)
To: Sean McAfee, 74438
Don't get me wrong, I'm not trying to attack your use case in any way,
just trying to help you solve it in the most efficient way possible.
Also trying to make sure that your use-case is really affected by this
behavior. Because if I now understand correctly, this should only affect
you if you are breaking the "doing nothing else in between" constraint.
Anyway, I feel like you can easily get rid of the "doing nothing else in
between" limitation if you rework your code to just work with a
particular register.
^ permalink raw reply [flat|nested] 13+ messages in thread
end of thread, other threads:[~2024-11-22 21:16 UTC | newest]
Thread overview: 13+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-11-19 20:24 bug#74438: 29.1; global-mark-ring does not work as described Sean McAfee
2024-11-20 10:18 ` Nikolay Kudryavtsev
2024-11-20 14:35 ` Eli Zaretskii
2024-11-21 7:51 ` Nikolay Kudryavtsev
2024-11-21 9:49 ` Eli Zaretskii
2024-11-20 19:16 ` Sean McAfee
2024-11-21 8:09 ` Nikolay Kudryavtsev
2024-11-21 19:49 ` Sean McAfee
2024-11-21 20:32 ` Nikolay Kudryavtsev
2024-11-21 21:03 ` Sean McAfee
2024-11-22 12:39 ` Nikolay Kudryavtsev
2024-11-22 18:48 ` Sean McAfee
2024-11-22 21:16 ` Nikolay Kudryavtsev
Code repositories for project(s) associated with this public inbox
https://git.savannah.gnu.org/cgit/emacs.git
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).