magnars/s.el
{ "createdAt": "2012-10-02T16:22:59Z", "defaultBranch": "master", "description": "The long lost Emacs string manipulation library.", "fullName": "magnars/s.el", "homepage": "", "language": "Emacs Lisp", "name": "s.el", "pushedAt": "2023-04-14T14:35:25Z", "stargazersCount": 1060, "topics": [], "updatedAt": "2025-11-22T17:52:23Z", "url": "https://github.com/magnars/s.el"}The long lost Emacs string manipulation library.
Installation
Section titled “Installation”It’s available on Melpa:
M-x package-install sOr you can just dump s.el in your load path somewhere.
Functions
Section titled “Functions”Tweak whitespace
Section titled “Tweak whitespace”- [s-trim]!(#s-trim-s)
(s) - [s-trim-left]!(#s-trim-left-s)
(s) - [s-trim-right]!(#s-trim-right-s)
(s) - [s-chomp]!(#s-chomp-s)
(s) - [s-collapse-whitespace]!(#s-collapse-whitespace-s)
(s) - [s-word-wrap]!(#s-word-wrap-len-s)
(len s) - [s-center]!(#s-center-len-s)
(len s) - [s-pad-left]!(#s-pad-left-len-padding-s)
(len padding s) - [s-pad-right]!(#s-pad-right-len-padding-s)
(len padding s)
To shorter string
Section titled “To shorter string”- [s-truncate]!(#s-truncate-len-s)
(len s) - [s-left]!(#s-left-len-s)
(len s) - [s-right]!(#s-right-len-s)
(len s) - [s-chop-left]!(#s-chop-left-len-s)
(len s) - [s-chop-right]!(#s-chop-right-len-s)
(len s) - [s-chop-suffix]!(#s-chop-suffix-suffix-s)
(suffix s) - [s-chop-suffixes]!(#s-chop-suffixes-suffixes-s)
(suffixes s) - [s-chop-prefix]!(#s-chop-prefix-prefix-s)
(prefix s) - [s-chop-prefixes]!(#s-chop-prefixes-prefixes-s)
(prefixes s) - [s-shared-start]!(#s-shared-start-s1-s2)
(s1 s2) - [s-shared-end]!(#s-shared-end-s1-s2)
(s1 s2)
To longer string
Section titled “To longer string”- [s-repeat]!(#s-repeat-num-s)
(num s) - [s-concat]!(#s-concat-rest-strings)
(&rest strings) - [s-prepend]!(#s-prepend-prefix-s)
(prefix s) - [s-append]!(#s-append-suffix-s)
(suffix s) - [s-splice]!(#s-splice-needle-n-s)
(needle n s)
To and from lists
Section titled “To and from lists”- [s-lines]!(#s-lines-s)
(s) - [s-match]!(#s-match-regexp-s-optional-start)
(regexp s &optional start) - [s-match-strings-all]!(#s-match-strings-all-regex-string)
(regex string) - [s-matched-positions-all]!(#s-matched-positions-all-regexp-string-optional-subexp-depth)
(regexp string &optional subexp-depth) - [s-slice-at]!(#s-slice-at-regexp-s)
(regexp s) - [s-split]!(#s-split-separator-s-optional-omit-nulls)
(separator s &optional omit-nulls) - [s-split-up-to]!(#s-split-up-to-separator-s-n-optional-omit-nulls)
(separator s n &optional omit-nulls) - [s-join]!(#s-join-separator-strings)
(separator strings)
Predicates
Section titled “Predicates”- [s-equals?]!(#s-equals-s1-s2)
(s1 s2) - [s-less?]!(#s-less-s1-s2)
(s1 s2) - [s-matches?]!(#s-matches-regexp-s-optional-start)
(regexp s &optional start) - [s-blank?]!(#s-blank-s)
(s) - [s-present?]!(#s-present-s)
(s) - [s-ends-with?]!(#s-ends-with-suffix-s-optional-ignore-case)
(suffix s &optional ignore-case) - [s-starts-with?]!(#s-starts-with-prefix-s-optional-ignore-case)
(prefix s &optional ignore-case) - [s-contains?]!(#s-contains-needle-s-optional-ignore-case)
(needle s &optional ignore-case) - [s-lowercase?]!(#s-lowercase-s)
(s) - [s-uppercase?]!(#s-uppercase-s)
(s) - [s-mixedcase?]!(#s-mixedcase-s)
(s) - [s-capitalized?]!(#s-capitalized-s)
(s) - [s-numeric?]!(#s-numeric-s)
(s)
The misc bucket
Section titled “The misc bucket”- [s-replace]!(#s-replace-old-new-s)
(old new s) - [s-replace-all]!(#s-replace-all-replacements-s)
(replacements s) - [s-downcase]!(#s-downcase-s)
(s) - [s-upcase]!(#s-upcase-s)
(s) - [s-capitalize]!(#s-capitalize-s)
(s) - [s-titleize]!(#s-titleize-s)
(s) - [s-with]!(#s-with-s-form-rest-more)
(s form &rest more) - [s-index-of]!(#s-index-of-needle-s-optional-ignore-case)
(needle s &optional ignore-case) - [s-reverse]!(#s-reverse-s)
(s) - [s-presence]!(#s-presence-s)
(s) - [s-format]!(#s-format-template-replacer-optional-extra)
(template replacer &optional extra) - [s-lex-format]!(#s-lex-format-format-str)
(format-str) - [s-count-matches]!(#s-count-matches-regexp-s-optional-start-end)
(regexp s &optional start end) - [s-wrap]!(#s-wrap-s-prefix-optional-suffix)
(s prefix &optional suffix)
Pertaining to words
Section titled “Pertaining to words”- [s-split-words]!(#s-split-words-s)
(s) - [s-lower-camel-case]!(#s-lower-camel-case-s)
(s) - [s-upper-camel-case]!(#s-upper-camel-case-s)
(s) - [s-snake-case]!(#s-snake-case-s)
(s) - [s-dashed-words]!(#s-dashed-words-s)
(s) - [s-capitalized-words]!(#s-capitalized-words-s)
(s) - [s-titleized-words]!(#s-titleized-words-s)
(s) - [s-word-initials]!(#s-word-initials-s)
(s) - [s-blank-str?]!(#s-blank-str-s)
(s)
Documentation and examples
Section titled “Documentation and examples”s-trim (s)
Section titled “s-trim (s)”Remove whitespace at the beginning and end of s.
(s-trim "trim ") ;; => "trim"(s-trim " this") ;; => "this"(s-trim " only trims beg and end ") ;; => "only trims beg and end"s-trim-left (s)
Section titled “s-trim-left (s)”Remove whitespace at the beginning of s.
(s-trim-left "trim ") ;; => "trim "(s-trim-left " this") ;; => "this"s-trim-right (s)
Section titled “s-trim-right (s)”Remove whitespace at the end of s.
(s-trim-right "trim ") ;; => "trim"(s-trim-right " this") ;; => " this"s-chomp (s)
Section titled “s-chomp (s)”Remove one trailing \n, \r or \r\n from s.
(s-chomp "no newlines\n") ;; => "no newlines"(s-chomp "no newlines\r\n") ;; => "no newlines"(s-chomp "some newlines\n\n") ;; => "some newlines\n"s-collapse-whitespace (s)
Section titled “s-collapse-whitespace (s)”Convert all adjacent whitespace characters to a single space.
(s-collapse-whitespace "only one space please") ;; => "only one space please"(s-collapse-whitespace "collapse \n all \t sorts of \r whitespace") ;; => "collapse all sorts of whitespace"s-word-wrap (len s)
Section titled “s-word-wrap (len s)”If s is longer than len, wrap the words with newlines.
(s-word-wrap 10 "This is too long") ;; => "This is\ntoo long"(s-word-wrap 10 "This is way way too long") ;; => "This is\nway way\ntoo long"(s-word-wrap 10 "It-wraps-words-but-does-not-break-them") ;; => "It-wraps-words-but-does-not-break-them"s-center (len s)
Section titled “s-center (len s)”If s is shorter than len, pad it with spaces so it is centered.
(s-center 5 "a") ;; => " a "(s-center 5 "ab") ;; => " ab "(s-center 1 "abc") ;; => "abc"s-pad-left (len padding s)
Section titled “s-pad-left (len padding s)”If s is shorter than len, pad it with padding on the left.
(s-pad-left 3 "0" "3") ;; => "003"(s-pad-left 3 "0" "23") ;; => "023"(s-pad-left 3 "0" "1234") ;; => "1234"s-pad-right (len padding s)
Section titled “s-pad-right (len padding s)”If s is shorter than len, pad it with padding on the right.
(s-pad-right 3 "." "3") ;; => "3.."(s-pad-right 3 "." "23") ;; => "23."(s-pad-right 3 "." "1234") ;; => "1234"s-truncate (len s)
Section titled “s-truncate (len s)”If s is longer than len, cut it down to len - 3 and add … at the end.
(s-truncate 6 "This is too long") ;; => "Thi..."(s-truncate 16 "This is also too long") ;; => "This is also ..."(s-truncate 16 "But this is not!") ;; => "But this is not!"s-left (len s)
Section titled “s-left (len s)”Returns up to the len first chars of s.
(s-left 3 "lib/file.js") ;; => "lib"(s-left 3 "li") ;; => "li"s-right (len s)
Section titled “s-right (len s)”Returns up to the len last chars of s.
(s-right 3 "lib/file.js") ;; => ".js"(s-right 3 "li") ;; => "li"s-chop-left (len s)
Section titled “s-chop-left (len s)”Remove the first len chars from s.
(s-chop-left 3 "lib/file.js") ;; => "/file.js"(s-chop-left 3 "li") ;; => ""s-chop-right (len s)
Section titled “s-chop-right (len s)”Remove the last len chars from s.
(s-chop-right 3 "lib/file.js") ;; => "lib/file"(s-chop-right 3 "li") ;; => ""s-chop-suffix (suffix s)
Section titled “s-chop-suffix (suffix s)”Remove suffix if it is at end of s.
(s-chop-suffix "-test.js" "penguin-test.js") ;; => "penguin"(s-chop-suffix "\n" "no newlines\n") ;; => "no newlines"(s-chop-suffix "\n" "some newlines\n\n") ;; => "some newlines\n"s-chop-suffixes (suffixes s)
Section titled “s-chop-suffixes (suffixes s)”Remove suffixes one by one in order, if they are at the end of s.
(s-chop-suffixes '("_test.js" "-test.js" "Test.js") "penguin-test.js") ;; => "penguin"(s-chop-suffixes '("\r" "\n") "penguin\r\n") ;; => "penguin\r"(s-chop-suffixes '("\n" "\r") "penguin\r\n") ;; => "penguin"s-chop-prefix (prefix s)
Section titled “s-chop-prefix (prefix s)”Remove prefix if it is at the start of s.
(s-chop-prefix "/tmp" "/tmp/file.js") ;; => "/file.js"(s-chop-prefix "/tmp" "/tmp/tmp/file.js") ;; => "/tmp/file.js"s-chop-prefixes (prefixes s)
Section titled “s-chop-prefixes (prefixes s)”Remove prefixes one by one in order, if they are at the start of s.
(s-chop-prefixes '("/tmp" "/my") "/tmp/my/file.js") ;; => "/file.js"(s-chop-prefixes '("/my" "/tmp") "/tmp/my/file.js") ;; => "/my/file.js"s-shared-start (s1 s2)
Section titled “s-shared-start (s1 s2)”Returns the longest prefix s1 and s2 have in common.
(s-shared-start "bar" "baz") ;; => "ba"(s-shared-start "foobar" "foo") ;; => "foo"(s-shared-start "bar" "foo") ;; => ""s-shared-end (s1 s2)
Section titled “s-shared-end (s1 s2)”Returns the longest suffix s1 and s2 have in common.
(s-shared-end "bar" "var") ;; => "ar"(s-shared-end "foo" "foo") ;; => "foo"(s-shared-end "bar" "foo") ;; => ""s-repeat (num s)
Section titled “s-repeat (num s)”Make a string of s repeated num times.
(s-repeat 10 " ") ;; => " "(s-concat (s-repeat 8 "Na") " Batman!") ;; => "NaNaNaNaNaNaNaNa Batman!"s-concat (&rest strings)
Section titled “s-concat (&rest strings)”Join all the string arguments into one string.
(s-concat "abc" "def" "ghi") ;; => "abcdefghi"s-prepend (prefix s)
Section titled “s-prepend (prefix s)”Concatenate prefix and s.
(s-prepend "abc" "def") ;; => "abcdef"s-append (suffix s)
Section titled “s-append (suffix s)”Concatenate s and suffix.
(s-append "abc" "def") ;; => "defabc"s-splice (needle n s)
Section titled “s-splice (needle n s)”Splice needle into s at position n.
0 is the beginning of the string, -1 is the end.
(s-splice "abc" 0 "def") ;; => "abcdef"(s-splice "abc" -1 "def") ;; => "defabc"(s-splice "needle" 2 "A in a haystack.") ;; => "A needle in a haystack."s-lines (s)
Section titled “s-lines (s)”Splits s into a list of strings on newline characters.
(s-lines "abc\ndef\nghi") ;; => '("abc" "def" "ghi")(s-lines "abc\rdef\rghi") ;; => '("abc" "def" "ghi")(s-lines "abc\r\ndef\r\nghi") ;; => '("abc" "def" "ghi")s-match (regexp s &optional start)
Section titled “s-match (regexp s &optional start)”When the given expression matches the string, this function returns a list of the whole matching string and a string for each matched subexpressions. If it did not match the returned value is an empty list (nil).
When start is non-nil the search will start at that index.
(s-match "^def" "abcdefg") ;; => nil(s-match "^abc" "abcdefg") ;; => '("abc")(s-match "^/.*/\\([a-z]+\\)\\.\\([a-z]+\\)" "/some/weird/file.html") ;; => '("/some/weird/file.html" "file" "html")s-match-strings-all (regex string)
Section titled “s-match-strings-all (regex string)”Return a list of matches for regex in string.
Each element itself is a list of matches, as per
match-string. Multiple matches at the same position will be
ignored after the first.
(s-match-strings-all "{\\([^}]+\\)}" "x is {x} and y is {y}") ;; => '(("{x}" "x") ("{y}" "y"))(s-match-strings-all "ab." "abXabY") ;; => '(("abX") ("abY"))(s-match-strings-all "\\<" "foo bar baz") ;; => '(("") ("") (""))s-matched-positions-all (regexp string &optional subexp-depth)
Section titled “s-matched-positions-all (regexp string &optional subexp-depth)”Return a list of matched positions for regexp in string.
subexp-depth is 0 by default.
(s-matched-positions-all "l+" "{{Hello}} World, {{Emacs}}!" 0) ;; => '((4 . 6) (13 . 14))(s-matched-positions-all "{{\\(.+?\\)}}" "{{Hello}} World, {{Emacs}}!" 0) ;; => '((0 . 9) (17 . 26))(s-matched-positions-all "{{\\(.+?\\)}}" "{{Hello}} World, {{Emacs}}!" 1) ;; => '((2 . 7) (19 . 24))s-slice-at (regexp s)
Section titled “s-slice-at (regexp s)”Slices s up at every index matching regexp.
(s-slice-at "-" "abc") ;; => '("abc")(s-slice-at "-" "abc-def") ;; => '("abc" "-def")(s-slice-at "[.#]" "abc.def.ghi#id") ;; => '("abc" ".def" ".ghi" "#id")s-split (separator s &optional omit-nulls)
Section titled “s-split (separator s &optional omit-nulls)”Split s into substrings bounded by matches for regexp separator.
If omit-nulls is non-nil, zero-length substrings are omitted.
This is a simple wrapper around the built-in split-string.
(s-split "|" "a|bc|12|3") ;; => '("a" "bc" "12" "3")(s-split ":" "a,c,d") ;; => '("a,c,d")(s-split "\n" "z\nefg\n") ;; => '("z" "efg" "")s-split-up-to (separator s n &optional omit-nulls)
Section titled “s-split-up-to (separator s n &optional omit-nulls)”Split s up to n times into substrings bounded by matches for regexp separator.
If omit-nulls is non-nil, zero-length substrings are omitted.
See also s-split.
(s-split-up-to "\\s-*-\\s-*" "Author - Track-number-one" 1) ;; => '("Author" "Track-number-one")(s-split-up-to "\\s-*-\\s-*" "Author - Track-number-one" 2) ;; => '("Author" "Track" "number-one")(s-split-up-to "|" "foo||bar|baz|qux" 3 t) ;; => '("foo" "bar" "baz|qux")s-join (separator strings)
Section titled “s-join (separator strings)”Join all the strings in strings with separator in between.
(s-join "+" '("abc" "def" "ghi")) ;; => "abc+def+ghi"(s-join "\n" '("abc" "def" "ghi")) ;; => "abc\ndef\nghi"s-equals? (s1 s2)
Section titled “s-equals? (s1 s2)”Is s1 equal to s2?
This is a simple wrapper around the built-in string-equal.
(s-equals? "abc" "ABC") ;; => nil(s-equals? "abc" "abc") ;; => ts-less? (s1 s2)
Section titled “s-less? (s1 s2)”Is s1 less than s2?
This is a simple wrapper around the built-in string-lessp.
(s-less? "abc" "abd") ;; => t(s-less? "abd" "abc") ;; => nil(s-less? "abc" "abc") ;; => nils-matches? (regexp s &optional start)
Section titled “s-matches? (regexp s &optional start)”Does regexp match s?
If start is non-nil the search starts at that index.
This is a simple wrapper around the built-in string-match-p.
(s-matches? "^[0-9]+$" "123") ;; => t(s-matches? "^[0-9]+$" "a123") ;; => nil(s-matches? "1" "1a" 1) ;; => nils-blank? (s)
Section titled “s-blank? (s)”Is s nil or the empty string?
(s-blank? "") ;; => t(s-blank? nil) ;; => t(s-blank? " ") ;; => nils-present? (s)
Section titled “s-present? (s)”Is s anything but nil or the empty string?
(s-present? "") ;; => nil(s-present? nil) ;; => nil(s-present? " ") ;; => ts-ends-with? (suffix s &optional ignore-case)
Section titled “s-ends-with? (suffix s &optional ignore-case)”Does s end with suffix?
If ignore-case is non-nil, the comparison is done without paying
attention to case differences.
Alias: s-suffix?
(s-ends-with? ".md" "readme.md") ;; => t(s-ends-with? ".MD" "readme.md") ;; => nil(s-ends-with? ".MD" "readme.md" t) ;; => ts-starts-with? (prefix s &optional ignore-case)
Section titled “s-starts-with? (prefix s &optional ignore-case)”Does s start with prefix?
If ignore-case is non-nil, the comparison is done without paying
attention to case differences.
Alias: s-prefix?. This is a simple wrapper around the built-in
string-prefix-p.
(s-starts-with? "lib/" "lib/file.js") ;; => t(s-starts-with? "LIB/" "lib/file.js") ;; => nil(s-starts-with? "LIB/" "lib/file.js" t) ;; => ts-contains? (needle s &optional ignore-case)
Section titled “s-contains? (needle s &optional ignore-case)”Does s contain needle?
If ignore-case is non-nil, the comparison is done without paying
attention to case differences.
(s-contains? "file" "lib/file.js") ;; => t(s-contains? "nope" "lib/file.js") ;; => nil(s-contains? "^a" "it's not ^a regexp") ;; => ts-lowercase? (s)
Section titled “s-lowercase? (s)”Are all the letters in s in lower case?
(s-lowercase? "file") ;; => t(s-lowercase? "File") ;; => nil(s-lowercase? "filä") ;; => ts-uppercase? (s)
Section titled “s-uppercase? (s)”Are all the letters in s in upper case?
(s-uppercase? "HULK SMASH") ;; => t(s-uppercase? "Bruce no smash") ;; => nil(s-uppercase? "FöB") ;; => nils-mixedcase? (s)
Section titled “s-mixedcase? (s)”Are there both lower case and upper case letters in s?
(s-mixedcase? "HULK SMASH") ;; => nil(s-mixedcase? "Bruce no smash") ;; => t(s-mixedcase? "BRÜCE") ;; => nils-capitalized? (s)
Section titled “s-capitalized? (s)”In s, is the first letter upper case, and all other letters lower case?
(s-capitalized? "Capitalized") ;; => t(s-capitalized? "I am capitalized") ;; => t(s-capitalized? "I Am Titleized") ;; => nils-numeric? (s)
Section titled “s-numeric? (s)”Is s a number?
(s-numeric? "123") ;; => t(s-numeric? "onetwothree") ;; => nil(s-numeric? "7a") ;; => nils-replace (old new s)
Section titled “s-replace (old new s)”Replaces old with new in s.
(s-replace "file" "nope" "lib/file.js") ;; => "lib/nope.js"(s-replace "^a" "\\1" "it's not ^a regexp") ;; => "it's not \\1 regexp"s-replace-all (replacements s)
Section titled “s-replace-all (replacements s)”replacements is a list of cons-cells. Each car is replaced with cdr in s.
(s-replace-all '(("lib" . "test") ("file" . "file_test")) "lib/file.js") ;; => "test/file_test.js"(s-replace-all '(("lib" . "test") ("test" . "lib")) "lib/test.js") ;; => "test/lib.js"s-downcase (s)
Section titled “s-downcase (s)”Convert s to lower case.
This is a simple wrapper around the built-in downcase.
(s-downcase "ABC") ;; => "abc"s-upcase (s)
Section titled “s-upcase (s)”Convert s to upper case.
This is a simple wrapper around the built-in upcase.
(s-upcase "abc") ;; => "ABC"s-capitalize (s)
Section titled “s-capitalize (s)”Convert the first word’s first character to upper case and the rest to lower case in s.
(s-capitalize "abc DEF") ;; => "Abc def"(s-capitalize "abc.DEF") ;; => "Abc.def"s-titleize (s)
Section titled “s-titleize (s)”Convert each word’s first character to upper case and the rest to lower case in s.
This is a simple wrapper around the built-in capitalize.
(s-titleize "abc DEF") ;; => "Abc Def"(s-titleize "abc.DEF") ;; => "Abc.Def"s-with (s form &rest more)
Section titled “s-with (s form &rest more)”Threads s through the forms. Inserts s as the last item
in the first form, making a list of it if it is not a list
already. If there are more forms, inserts the first form as the
last item in second form, etc.
(s-with " hulk smash " s-trim s-upcase) ;; => "HULK SMASH"(s-with "My car is a Toyota" (s-replace "car" "name") (s-replace "a Toyota" "Bond") (s-append ", James Bond")) ;; => "My name is Bond, James Bond"(s-with "abc \ndef \nghi" s-lines (mapcar 's-trim) (s-join "-") s-reverse) ;; => "ihg-fed-cba"s-index-of (needle s &optional ignore-case)
Section titled “s-index-of (needle s &optional ignore-case)”Returns first index of needle in s, or nil.
If ignore-case is non-nil, the comparison is done without paying
attention to case differences.
(s-index-of "abc" "abcdef") ;; => 0(s-index-of "CDE" "abcdef" t) ;; => 2(s-index-of "n.t" "not a regexp") ;; => nils-reverse (s)
Section titled “s-reverse (s)”Return the reverse of s.
(s-reverse "abc") ;; => "cba"(s-reverse "ab xyz") ;; => "zyx ba"(s-reverse "") ;; => ""s-presence (s)
Section titled “s-presence (s)”Return s if it’s s-present?, otherwise return nil.
(s-presence nil) ;; => nil(s-presence "") ;; => nil(s-presence "foo") ;; => "foo"s-format (template replacer &optional extra)
Section titled “s-format (template replacer &optional extra)”Format template with the function replacer.
replacer takes an argument of the format variable and optionally
an extra argument which is the extra value from the call to
s-format.
Several standard s-format helper functions are recognized and
adapted for this:
(s-format "${name}" 'gethash hash-table)(s-format "${name}" 'aget alist)(s-format "$0" 'elt sequence)The replacer function may be used to do any other kind of
transformation.
(s-format "help ${name}! I'm ${malady}" 'aget '(("name" . "nic") ("malady" . "on fire"))) ;; => "help nic! I'm on fire"(s-format "hello ${name}, nice day" (lambda (var-name) "nic")) ;; => "hello nic, nice day"(s-format "hello $0, nice $1" 'elt '("nic" "day")) ;; => "hello nic, nice day"s-lex-format (format-str)
Section titled “s-lex-format (format-str)”s-format with the current environment.
format-str may use the s-format variable reference to refer to
any variable:
(let ((x 1)) (s-lex-format “x is: ${x}”))
The values of the variables are interpolated with “%s” unless
the variable s-lex-value-as-lisp is t and then they are
interpolated with “%S”.
(let ((x 1)) (s-lex-format "x is ${x}")) ;; => "x is 1"(let ((str1 "this") (str2 "that")) (s-lex-format "${str1} and ${str2}")) ;; => "this and that"(let ((foo "Hello\\nWorld")) (s-lex-format "${foo}")) ;; => "Hello\\nWorld"s-count-matches (regexp s &optional start end)
Section titled “s-count-matches (regexp s &optional start end)”Count occurrences of regexp in `s’.
start, inclusive, and end, exclusive, delimit the part of s
to match.
(s-count-matches "a" "aba") ;; => 2(s-count-matches "a" "aba" 0 2) ;; => 1(s-count-matches "\\w\\{2\\}[0-9]+" "ab1bab2frobinator") ;; => 2s-wrap (s prefix &optional suffix)
Section titled “s-wrap (s prefix &optional suffix)”Wrap string s with prefix and optionally suffix.
Return string s with prefix prepended. If suffix is present, it
is appended, otherwise prefix is used as both prefix and
suffix.
(s-wrap "foo" "\"") ;; => "\"foo\""(s-wrap "foo" "(" ")") ;; => "(foo)"(s-wrap "foo" "bar") ;; => "barfoobar"s-split-words (s)
Section titled “s-split-words (s)”Split s into list of words.
(s-split-words "under_score") ;; => '("under" "score")(s-split-words "some-dashed-words") ;; => '("some" "dashed" "words")(s-split-words "evenCamelCase") ;; => '("even" "Camel" "Case")s-lower-camel-case (s)
Section titled “s-lower-camel-case (s)”Convert s to lowerCamelCase.
(s-lower-camel-case "some words") ;; => "someWords"(s-lower-camel-case "dashed-words") ;; => "dashedWords"(s-lower-camel-case "under_scored_words") ;; => "underScoredWords"s-upper-camel-case (s)
Section titled “s-upper-camel-case (s)”Convert s to UpperCamelCase.
(s-upper-camel-case "some words") ;; => "SomeWords"(s-upper-camel-case "dashed-words") ;; => "DashedWords"(s-upper-camel-case "under_scored_words") ;; => "UnderScoredWords"s-snake-case (s)
Section titled “s-snake-case (s)”Convert s to snake_case.
(s-snake-case "some words") ;; => "some_words"(s-snake-case "dashed-words") ;; => "dashed_words"(s-snake-case "camelCasedWords") ;; => "camel_cased_words"s-dashed-words (s)
Section titled “s-dashed-words (s)”Convert s to dashed-words.
(s-dashed-words "some words") ;; => "some-words"(s-dashed-words "under_scored_words") ;; => "under-scored-words"(s-dashed-words "camelCasedWords") ;; => "camel-cased-words"s-capitalized-words (s)
Section titled “s-capitalized-words (s)”Convert s to Capitalized words.
(s-capitalized-words "some words") ;; => "Some words"(s-capitalized-words "under_scored_words") ;; => "Under scored words"(s-capitalized-words "camelCasedWords") ;; => "Camel cased words"s-titleized-words (s)
Section titled “s-titleized-words (s)”Convert s to Titleized Words.
(s-titleized-words "some words") ;; => "Some Words"(s-titleized-words "under_scored_words") ;; => "Under Scored Words"(s-titleized-words "camelCasedWords") ;; => "Camel Cased Words"s-word-initials (s)
Section titled “s-word-initials (s)”Convert s to its initials.
(s-word-initials "some words") ;; => "sw"(s-word-initials "under_scored_words") ;; => "usw"(s-word-initials "camelCasedWords") ;; => "cCW"s-blank-str? (s)
Section titled “s-blank-str? (s)”Is s nil or the empty string or string only contains whitespace?
(s-blank-str? " \t \r ") ;; => t(s-blank-str? " ") ;; => t(s-blank-str? "\t\r") ;; => tWhat’s with the built-in wrappers?
Section titled “What’s with the built-in wrappers?”Imagine looking through the function list and seeing s-ends-with?, but
s-starts-with? is nowhere to be found. Why? Well, because Emacs already has
string-prefix-p. Now you’re starting out slightly confused, then have to go
somewhere else to dig for the command you were looking for.
The wrapping functions serve as both documentation for existing functions and makes for a consistent API.
Other string related libraries
Section titled “Other string related libraries”-
inflections package provides functions for strings pluralization and singularization.
-
levenshtein package provides a function to calculate the Levenshtein distance between two strings.
-
string-utils is another general string manipulation library.
Changelist
Section titled “Changelist”From 1.11.0 to 1.12.0
Section titled “From 1.11.0 to 1.12.0”- Alias all functions ending in
?(Tianxiang Xiong) - Add
s-blank-str?(Aborn Jiang) - Several bugfixes
From 1.10.0 to 1.11.0
Section titled “From 1.10.0 to 1.11.0”- Add
s-matched-positions-all(ono hiroko)
From 1.9.0 to 1.10.0
Section titled “From 1.9.0 to 1.10.0”- Add
s-wrap(Johan Andersson) - Add
s-split-up-to(Matus Goljer) - Fix
s-reversefor Unicode combining characters. (Christopher Wellons)
From 1.8.0 to 1.9.0
Section titled “From 1.8.0 to 1.9.0”- Add
s-count-matches(Lars Andersen)
From 1.7.0 to 1.8.0
Section titled “From 1.7.0 to 1.8.0”- Add
s-present?ands-present?(Johan Andersson) - Better handling of international characters
From 1.6.0 to 1.7.0
Section titled “From 1.6.0 to 1.7.0”- Add
s-word-initials(Sylvain Rousseau) - Better handling of camel cased strings (@Bruce-Connor)
From 1.5.0 to 1.6.0
Section titled “From 1.5.0 to 1.6.0”- Add
s-pad-leftands-pad-right - Bugfixes for
s-format(Nic Ferrier)
From 1.4.0 to 1.5.0
Section titled “From 1.4.0 to 1.5.0”- Add
s-all-match-strings(Geoff Gole) - Add
s-lex-format(Nic Ferrier)
From 1.3.1 to 1.4.0
Section titled “From 1.3.1 to 1.4.0”- Add
s-capitalized? - Add
s-replace-all - Add
s-slice-at - Add
s-splitalias forsplit-string(Rüdiger Sonderfeld) - Add
s-less?predicate (Rüdiger Sonderfeld) - Add START parameter to
s-matches?(Rüdiger Sonderfeld) - Bugfixes
From 1.3.0 to 1.3.1
Section titled “From 1.3.0 to 1.3.1”- Add
s-numeric? - Add
s-match(Arthur Andersen) - Add
s-format(Nic Ferrier) - Move .el files out of root to avoid problems with require.
From 1.2.1 to 1.3.0
Section titled “From 1.2.1 to 1.3.0”-
Breaking change:
s-capitalizenow converts the first word’s first character to upper case and the rest to lower case.s-titleizeworks like the olds-capitalizeand capitalizes each word. (Johan Andersson) -
s-capitalized-wordsands-titleized-wordsmirror this change.
Contributors
Section titled “Contributors”- Arthur Andersen contributed
s-match - Rolando contributed
s-shared-startands-shared-end - Johan Andersson contributed
s-presence,s-present?and fixeds-titleizevss-capitalize - Nic Ferrier added
s-formatands-lex-format - Rüdiger Sonderfeld contributed
s-less?,s-splitand several bugfixes. - Geoff Gole contributed
s-all-match-strings - Sylvain Rousseau contributed
s-word-initials - Lars Andersen contributed
s-count-matches - ono hiroko contributed
s-matched-positions-all
Thanks!
Contribute
Section titled “Contribute”Yes, please do. Pure functions in the string manipulation realm only,
please. There’s a suite of tests in dev/examples.el, so remember to add
tests for your function, or I might break it later.
You’ll find the repo at:
https://github.com/magnars/s.elRun the tests with
./run-tests.shCreate the docs with
./create-docs.shI highly recommend that you install these as a pre-commit hook, so that the tests are always running and the docs are always in sync:
cp pre-commit.sh .git/hooks/pre-commitOh, and don’t edit README.md directly, it is auto-generated.
Change readme-template.md or examples-to-docs.el instead.
License
Section titled “License”Copyright (C) 2012-2022 Magnar Sveen
Authors: Magnar Sveen magnars@gmail.com Maintainer: Jason Milkins jasonm23@gmail.com Keywords: strings
This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with this program. If not, see http://www.gnu.org/licenses/.