diff --git a/doc/lispref/minibuf.texi b/doc/lispref/minibuf.texi index 3cc206d2e1d..ad44472fa5d 100644 --- a/doc/lispref/minibuf.texi +++ b/doc/lispref/minibuf.texi @@ -965,6 +965,9 @@ too short). Both of those begin with the string @samp{foobar}. @result{} "foobar" @end group @end smallexample + + See also the functions @code{string-try-completion} and +@code{string-common-prefix} in @ref{Creating Strings}. @end defun @defun all-completions string collection &optional predicate diff --git a/doc/lispref/strings.texi b/doc/lispref/strings.texi index 93025574893..101366b942d 100644 --- a/doc/lispref/strings.texi +++ b/doc/lispref/strings.texi @@ -248,6 +248,50 @@ equivalent to 0. Thus, @w{@code{(substring-no-properties properties removed. @end defun +@cindex common prefix of a collection of strings +@defun string-common-prefix collection &optional ignore-case +This function returns the longest initial substring common to all +members of @var{collection}. It returns an empty string when there is +no common prefix or @var{collection} is nil. If @var{collection} +contains exactly one string then it returns that string. + +@example +(string-common-prefix '("foobar" "foozot")) + @result{} "foo" +@end example + +If @var{ignore-case} is non-nil, letter case is ignored when matching +the substrings, but no guarantee is made about the letter-case of the +return value, except that it comes from one of the members of +@var{collection}. + +@var{collection} may be a list of strings or any other value supported +by @code{try-completion} (@pxref{Basic Completion}). +@end defun + +@cindex string completion +@defun string-try-completion string collection &optional predicate +This function returns the longest common substring of all possible +completions of @var{string} in @var{collection}. + +This is like @code{try-completion} (@pxref{Basic Completion}) except +that it always returns a string. + +If no possible completions match, the function returns an empty string; +if there's just one exact match, it returns that string; otherwise it +returns the longest initial substring common to all possible completions +that begin with @var{string}. + +@example +(string-try-completion "foo" '("foobar" "foozot" "gazonk")) + @result{} "foo" +(string-try-completion "foo" '("foo")) + @result{} "foo" +(string-try-completion "foo" nil) + @result{} "" +@end example +@end defun + @defun concat &rest sequences @cindex copying strings @cindex concatenating strings diff --git a/etc/NEWS b/etc/NEWS index 1f29fe5f0b4..2e6aa01cf40 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -2427,6 +2427,16 @@ It offers a more concise way to create a completion table with metadata. +++ ** 'all-completions' and 'unintern' no longer support old calling conventions. ++++ +** New functions 'string-try-completion' and 'string-common-prefix'. +The former is like 'try-completion', except it always returns a string. +The latter returns the longest initial substring common to all members +of a collection of strings (essentially completing an empty string). + ++++ +** New function. +This + +++ ** New symbol property 'find-function-type-alist' used by 'find-function' etc. Macros that define an object in a way that makes the object's name and diff --git a/lisp/emacs-lisp/shortdoc.el b/lisp/emacs-lisp/shortdoc.el index 2e826399261..c783c0838d2 100644 --- a/lisp/emacs-lisp/shortdoc.el +++ b/lisp/emacs-lisp/shortdoc.el @@ -385,8 +385,16 @@ A FUNC form can have any number of `:no-eval' (or `:no-value'), :eval (reverse "foo")) (substring-no-properties :eval (substring-no-properties (propertize "foobar" 'face 'bold) 0 3)) + (string-common-prefix + :eval (string-common-prefix '("foobar" "foozot"))) + (string-try-completion + :eval (string-try-completion "foo" '("foobar" "foozot" "gazonk")) + :eval (string-try-completion "foo" '("foo")) + :eval (string-try-completion "foo" nil)) (try-completion - :eval (try-completion "foo" '("foobar" "foozot" "gazonk"))) + :eval (try-completion "foo" '("foobar" "foozot" "gazonk")) + :eval (try-completion "foo" '("foo")) + :eval (try-completion "foo" nil)) "Unicode Strings" (string-glyph-split :eval (string-glyph-split "Hello, πŸ‘ΌπŸ»πŸ§‘πŸΌβ€πŸ€β€πŸ§‘πŸ»")) diff --git a/lisp/subr.el b/lisp/subr.el index 729f8b3e09b..ca60540ed8d 100644 --- a/lisp/subr.el +++ b/lisp/subr.el @@ -6002,6 +6002,45 @@ attention to letter-case differences." (eq t (compare-strings suffix nil nil string start-pos nil ignore-case))))) +(defun string-common-prefix (collection &optional ignore-case) + "Return the longest common prefix from a COLLECTION of strings. + +If IGNORE-CASE is non-nil, letter case is ignored when matching the +substrings, but no guarantee is made about the letter-case of the return +value, except that it comes from one of the members of COLLECTION. + +This function returns the longest initial substring common to all +members of COLLECTION. It returns \"\" when there is no common prefix +or COLLECTION is nil. If COLLECTION contains exactly one string then it +returns that string. + +COLLECTION may be a list of strings or any other value supported by +`try-completion'. + +See also `string-try-completion'." + (let ((completion-ignore-case ignore-case) + (completion-regexp-list nil)) + ;; `try-completion' is not affected by `completion-styles'. + (string-try-completion "" collection))) + +(defun string-try-completion (string collection &optional predicate) + "Return longest common substring of all completions of STRING in COLLECTION. + +This is like `try-completion' except that it always returns a string: + +If no possible completions match, the function returns \"\"; if there's +just one exact match, it returns that string; otherwise it returns the +longest initial substring common to all possible completions that begin +with STRING. + +See also `string-common-prefix'." + (let ((prefix (try-completion string collection predicate))) + (if (stringp prefix) + prefix + (if (eq t prefix) + string + "")))) + (defun bidi-string-mark-left-to-right (str) "Return a string that can be safely inserted in left-to-right text.