Search code examples
stringemacselispsubstringstring-matching

Check if a string ends with a suffix in Emacs Lisp


Is there a function that checks that a string ends with a certain substring? Python has endswith:

>>> "victory".endswith("tory")
True

Solution

  • Just install s.el string manipulation library and use its s-suffix? predicate:

    (s-suffix? "turn." "...when it ain't your turn.") ; => t
    

    But if you refuse you to use this library, you have to write your own function. There is string-prefix-p, which is an analog to Python's str.startswith, in subr.el, and it is just a wrapper around compare-strings. According to Emacs 24.3 changelog:

    ** New function `string-prefix-p'.
    (This was actually added in Emacs 23.2 but was not advertised at the time.)
    

    string-suffix-p was added only in Emacs 24.4, so for earlier versions i wrote:

    (defun string-suffix-p (str1 str2 &optional ignore-case)
      (let ((begin2 (- (length str2) (length str1)))
            (end2 (length str2)))
        (when (< begin2 0) (setq begin2 0))
        (eq t (compare-strings str1 nil nil
                               str2 begin2 end2
                               ignore-case))))
    

    (when (< begin2 0) (setq begin2 0)) is a workaround, because if you pass negative numbers to compare-strings, it barfs with *** Eval error *** Wrong type argument: wholenump, -1.

    If you byte compile the function, it works faster than yves Baumes solution, even though string-match is a C function.

    ELISP> (setq str1 "miss."
                 str2 "Ayo, lesson here, Bey. You come at the king, you best not miss.")
    ELISP> (benchmark-run 1000000 (string-suffix-p str1 str2))
    (4.697675135000001 31 2.789847821000066)
    ELISP> (byte-compile 'string-suffix-p)
    ELISP> (benchmark-run 1000000 (string-suffix-p str1 str2))
    (0.43636462600000003 0 0.0)
    ELISP> (benchmark-run 1000000 (string-match "miss\.$" str2))
    (1.3447664240000001 0 0.0)