Subject: 30.1; [PATCH] Add functions `string-common-prefix' and `string-try-completion'

From: Phil Sainty <[email-masked]>
Date: Mon, 09 Jun 2025 00:03:46 +1200

This is a spin-off from bug#78658 -- and following on from
https://debbugs.gnu.org/cgi/bugreport.cgi?bug=78658#65 in particular --
to add friendlier alternatives to `try-completion' for efficiently
obtaining a common string prefix or completion from a collection of
strings outside of the context of minibuffer completion.

E.g. when you simply want to know the longest common prefix from a
list of strings without having to deal with any completion variables
or edge-case return values.

Unlike `try-completion' which may return nil or t, the new functions
always return a string, simplifying their usage and (on account of
the "string-*" naming) making the functionality more discoverable
for programmers working with strings.

The function `string-try-completion' provides the general case and
is just like `try-completion' except for always returning a string.

The function `string-common-prefix' is the simpler case wanted for
bug#78658, taking fewer arguments and binding the variables
`completion-regexp-list' and `completion-ignore-case'.

I've pushed a branch scratch/string-common-prefix with the following
commit for review:
https://cgit.git.savannah.gnu.org/cgit/emacs.git/commit/?h=scratch/string-common-prefix&id=accfe19887f3573dd55f5272f92899afa1e2f446

(Plus a fixup commit removing the unintended additional NEWS entry.)

-Phil

In GNU Emacs 30.1 (build 2, x86_64-pc-linux-gnu, X toolkit, cairo
  version 1.16.0, Xaw scroll bars) of 2025-02-25 built on phil-lp
Repository revision: 8ac894e2246f25d2a2a97d866b10e6e0b0fede5a
Repository branch: HEAD
Windowing system distributor 'The X.Org Foundation', version 
11.0.12101004
System Description: Ubuntu 22.04.5 LTS

Configured using:
  'configure --prefix=/home/phil/emacs/30.x.nc/usr/local
  --with-native-compilation=aot --with-x-toolkit=lucid --without-sound
  '--program-transform-name=s/^ctags$/ctags_emacs/''

Configured features:
CAIRO DBUS FREETYPE GIF GLIB GMP GNUTLS GPM GSETTINGS HARFBUZZ JPEG
LCMS2 LIBSELINUX LIBXML2 MODULES NATIVE_COMP NOTIFY INOTIFY PDUMPER PNG
RSVG SECCOMP SQLITE3 THREADS TIFF TOOLKIT_SCROLL_BARS TREE_SITTER WEBP
X11 XDBE XIM XPM LUCID ZLIB

Important settings:
   value of $LC_MONETARY: en_NZ.UTF-8
   value of $LC_NUMERIC: en_NZ.UTF-8
   value of $LC_TIME: en_NZ.UTF-8
   value of $LANG: en_GB.UTF-8
   value of $XMODIFIERS: @im=ibus
   locale-coding-system: utf-8

Major mode: Magit Rev

Minor modes in effect:
   icomplete-mode: t
   magit-wip-initial-backup-mode: t
   magit-wip-before-change-mode: t
   magit-wip-after-apply-mode: t
   magit-wip-after-save-mode: t
   magit-wip-mode: t
   global-git-commit-mode: t
   magit-auto-revert-mode: t
   global-window-tool-bar-mode: t
   window-tool-bar-mode: t
   bug-reference-mode: t
   minibuffer-line-mode: t
   server-mode: t
   savehist-mode: t
   global-anzu-mode: t
   anzu-mode: t
   my-contextual-help-mode: t
   global-so-long-mode: t
   global-visible-mark-mode: t
   visible-mark-mode: t
   repeat-mode: t
   display-battery-mode: t
   my-visible-bell-mode: t
   global-display-fill-column-indicator-mode: t
   minibuffer-depth-indicate-mode: t
   which-key-mode: t
   keep-buffers-mode: t
   global-subword-mode: t
   subword-mode: t
   global-hl-line-mode: t
   display-time-mode: t
   recentf-mode: t
   my-global-keys-local-minor-mode: t
   my-keys-local-minor-mode: t
   windmove-mode: t
   url-handler-mode: t
   auto-compile-on-load-mode: t
   auto-compile-on-save-mode: t
   tooltip-mode: t
   global-eldoc-mode: t
   show-paren-mode: t
   electric-indent-mode: t
   mouse-wheel-mode: t
   tab-bar-history-mode: t
   tab-bar-mode: t
   menu-bar-mode: t
   file-name-shadow-mode: t
   global-font-lock-mode: t
   font-lock-mode: t
   minibuffer-regexp-mode: t
   buffer-read-only: t
   column-number-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:
/home/phil/.emacs.d/el-get/scratch/el-get hides 
/home/phil/.emacs.d/el-get/el-get/el-get
/home/phil/.emacs.d/el-get/avy/avy hides 
/home/phil/.emacs.d/elpa/avy-0.5.0/avy
/home/phil/.emacs.d/el-get/dash/dash hides 
/home/phil/.emacs.d/elpa/dash-2.19.1/dash
/home/phil/.emacs.d/el-get/iedit/iedit hides 
/home/phil/.emacs.d/elpa/iedit-0.9.9.9.9/iedit
/home/phil/.emacs.d/my-lisp/psysh hides 
/home/phil/.emacs.d/elpa/psysh-0.4.9/psysh
/home/phil/.emacs.d/elpa/transient-0.7.9/transient hides 
/home/phil/emacs/30.x.nc/usr/local/share/emacs/30.1/lisp/transient
/home/phil/.emacs.d/el-get/which-key/which-key hides 
/home/phil/emacs/30.x.nc/usr/local/share/emacs/30.1/lisp/which-key

Features:
(shadow sort ecomplete mail-extr emacsbug tramp trampver
tramp-integration tramp-message tramp-compat xdg parse-time iso8601
tramp-loaddefs term disp-table ehelp pcmpl-gnu pcmpl-unix sh-script smie
treesit two-column emacs-news-mode noutline outline cua-rect cua-base
find-dired whitespace reposition wgrep texinfo texinfo-loaddefs
dired-aux jinx magit-extras magit-submodule magit-obsolete 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
ibuf-ext ibuffer ibuffer-loaddefs ucs-normalize shortdoc icomplete
face-remap hippie-exp executable files-x winnow magit-wip magit-log
which-func imenu magit-diff smerge-mode diff git-commit log-edit message
sendmail yank-media puny rfc822 mml mml-sec epa derived epg rfc6068
epg-config gnus-util mm-decode mm-bodies mm-encode mail-parse rfc2231
rfc2047 rfc2045 mm-util ietf-drums mail-prsvr mailabbrev mail-utils
gmm-utils mailheader pcvs-util add-log magit-core magit-autorevert
autorevert filenotify magit-margin magit-transient magit-process
with-editor shell pcomplete magit-mode transient edmacro magit-git
magit-section magit-utils crm dash misearch multi-isearch hi-lock
compare-w project find-func help-fns window-tool-bar tab-line compat
view mule-util holidays holiday-loaddefs cal-julian lunar solar cal-dst
vc-git diff-mode track-changes vc-dispatcher autoinsert bug-reference
goto-addr appt diary-lib diary-loaddefs cal-menu calendar cal-loaddefs
lexbind-mode hl-sexp fic-mode elide-head idle-highlight-mode
completion-preview sockit tabify minibuffer-line server my-org
my-projects my-session savehist desktop frameset my-mail my-libraries
sudo anzu my-version-control my-text my-programming so-long
my-rectangles rect my-utilities browse-kill-ring my-configuration
visible-mark cus-edit pp cus-load dired-details dired-x repeat
highlight-parentheses format-spec battery delight delsel ffap thingatpt
display-fill-column-indicator mb-depth which-key pcase easy-mmode
keep-buffers cap-words superword subword hl-line time recentf
tree-widget wid-edit atomic-chrome websocket bindat let-alist
my-whitespace ws-trim my-externals .loaddefs rainbow-mode notify dbus
xml mo-git-blame cl iedit el-get autoload loaddefs-gen radix-tree
lisp-mnt dired dired-loaddefs my-holidays my-local kmacro my-mahara grep
tks generic-x catalyst redshift-indent my-keybindings framemove advice
windmove my-startup-log time-date adaptive-wrap-autoloads ...)

Memory information:
((conses 16 1246250 374539) (symbols 48 43403 2)
  (strings 32 196192 27442) (string-bytes 1 7837076) (vectors 16 94255)
  (vector-slots 8 1904715 340289) (floats 8 927 9358)
  (intervals 56 128211 16974) (buffers 992 50))