Emacs用文字列操作ライブラリ s.el の使い方

Emacs用文字列操作ライブラリ [s.el](https://github.com/magnars/s.el) の使い方の練習です。
自分用およびRuby脳な人にもわかりやすいように Ruby だとどんな感じになるかも合わせて書いています。

## 左スペース除去 (s-trim-left)

```el:EmacsLisp
(s-trim-left " a ")    ; => "a "
```

```ruby:Ruby
" a ".lstrip    # => "a "
```

## 右スペース除去 (s-trim-right)

```el:EmacsLisp
(s-trim-right " a ")    ; => " a"
```

```ruby:Ruby
" a ".rstrip    # => " a"
```

## 左右スペース除去 (s-trim)

```el:EmacsLisp
(s-trim " a ")    ; => "a"
```

```ruby:Ruby
" a ".strip    # => "a"
```

## 2つ以上のスペースを1つに置換 (s-collapse-whitespace)

```el:EmacsLisp
(s-collapse-whitespace "  a  b  c  ")    ; => " a b c "
```

```ruby:Ruby
"  a  b  c  ".squeeze(" ")    # => " a b c "
```

## 区切り文字で分割 (s-split)

```el:EmacsLisp
(s-split "," "a,b,c")    ; => ("a" "b" "c")
```

```ruby:Ruby
"a,b,c".split(/,/)    # => ["a", "b", "c"]
```

## 区切り文字でN個だけ分割 (s-split-up-to)

```el:EmacsLisp
(s-split-up-to "," "a,b,c" 1)    ; => ("a" "b,c")
```

```ruby:Ruby
"a,b,c".split(/,/, 2)    # => ["a", "b,c"]
```

## 行毎に分割 (s-lines)

```el:EmacsLisp
(s-lines "a\nb\nc")    ; => ("a" "b" "c")
```

```ruby:Ruby
"a\nb\nc".split(/\n/)    # => ["a", "b", "c"]
```

## 区切り文字を間に入れて結合 (s-join)

```el:EmacsLisp
(s-join "," '("a" "b" "c"))    ; => "a,b,c"
```

```ruby:Ruby
["a", "b", "c"].join(",")    # => "a,b,c"
```

## 文字列の結合 (s-concat)

```el:EmacsLisp
(s-concat "a" "b" "c")    ; => "abc"
```

```ruby:Ruby
"a" "b" "c"    # => "abc"
```

## 前に結合 (s-prepend)

```el:EmacsLisp
(s-prepend "_" "foo")    ; => "_foo"
```

```ruby:Ruby
"_" + "foo"    # => "_foo"
```

## 後ろに結合 (s-append)

```el:EmacsLisp
(s-append "_" "foo")    ; => "foo_"
```

```ruby:Ruby
"foo" + "_"    # => "foo_"
```

## 文字列の繰り返し (s-repeat)

```el:EmacsLisp
(s-repeat 3 "a")    ; => "aaa"
```

```ruby:Ruby
"a" * 3    # => "aaa"
```

## プレフィクス除去 (s-chop-prefix)

```el:EmacsLisp
(s-chop-prefix "a" "ax")    ; => "x"
```

```ruby:Ruby
"ax".sub(/\Aa/, "")    # => "x"
```

## 複数のプレフィクス除去 (s-chop-prefixes)

```el:EmacsLisp
(s-chop-prefixes '("a" "b") "abx")    ; => "x"
```

```ruby:Ruby
["a", "b"].inject("abx") { |a, e| a.sub(/\A#{e}/, "") }    # => "x"
```

## サフィックス除去 (s-chop-suffix)

```el:EmacsLisp
(s-chop-suffix "a" "xa")    ; => "x"
```

```ruby:Ruby
"xa".sub(/a\z/, "")    # => "x"
```

## 複数のサフィックス除去 (s-chop-suffixes)

```el:EmacsLisp
(s-chop-suffixes '("a" "b") "xba")    ; => "x"
```

```ruby:Ruby
["a", "b"].inject("xba") { |a, e| a.sub(/#{e}\z/, "") }    # => "x"
```

## 共通のプレフィクスを抽出 (s-shared-start)

```el:EmacsLisp
(s-shared-start "axb" "ayb")    ; => "a"
```

```ruby:Ruby
a = "axb"
b = "ayb"
it = b.each_char
i = a.chars.find_index { |e| e != it.next }
i ? a[0...i] : ""    # => "a"
```

## 共通のサフィックスを抽出 (s-shared-end)

```el:EmacsLisp
(s-shared-end "axb" "ayb")    ; => "b"
```

```ruby:Ruby
a = "axb"
b = "ayb"
it = b.chars.reverse.each
i = a.chars.reverse.find_index { |e| e != it.next }
i ? a.chars.last(i).join : ""    # => "b"
```

## 行末の改行除去 (s-chomp)

```el:EmacsLisp
(s-chomp "a\r\n")    ; => "a"
```

```ruby:Ruby
"a\r\n".chomp    # => "a"
```

## ちょんぎる (s-truncate)

```el:EmacsLisp
(s-truncate 5 "0123456789")    ; => "01..."
```

```ruby:ActiveSupport
"0123456789".truncate(5)    # => "01..."
```

## 指定横幅に収まるように整形 (s-word-wrap)

```el:EmacsLisp
(s-word-wrap 4 "a b c")    ; => "a b\nc"
```

```ruby:Ruby
require "nkf"
NKF.nkf("-f#{4.pred} -w", "a b c").rstrip    # => "a b\nc"

# マルチバイト未対応だけど
require "action_view"
include ActionView::Helpers::TextHelper
word_wrap("a b c", line_width: 4)    # => "a b\nc"
```

## 中央寄せ (s-center)

```el:EmacsLisp
(s-center 5 "a")    ; => "  a  "
```

```ruby:Ruby
"a".center(5)    # => "  a  "
```

## 左寄せ (s-pad-right)

```el:EmacsLisp
(s-pad-right 5 " " "a")    ; => "a    "
```

```ruby:Ruby
"a".ljust(5)    # => "a    "
```

## 右寄せ (s-pad-left)

```el:EmacsLisp
(s-pad-left 5 " " "a")    ; => "    a"
```

```ruby:Ruby
"a".rjust(5)    # => "    a"
```

## 先頭N文字 (s-left)

```el:EmacsLisp
(s-left 2 "012")    ; => "01"
```

```ruby:Ruby
"012"[0...2]    # => "01"
```

## 後ろのN文字 (s-right)

```el:EmacsLisp
(s-right 2 "012")    ; => "12"
```

```ruby:Ruby
"012"[-2..-1]    # => "12"
```

## サフィックス確認 (s-ends-with?)

```el:EmacsLisp
(s-ends-with? "c" "abc")    ; => t
```

```ruby:Ruby
"abc".end_with?("c")    # => true
```

## プレフィクス確認 (s-starts-with?)

```el:EmacsLisp
(s-starts-with? "a" "abc")    ; => t
```

```ruby:Ruby
"abc".start_with?("a")    # => true
```

## 文字列が含まれる？ (s-contains?)

```el:EmacsLisp
(s-contains? "b" "abc")    ; => t
```

```ruby:Ruby
"abc".include?("b")    # => true
```

## 文字列が一致する？ (s-equals?)

```el:EmacsLisp
(s-equals? "a" "a")    ; => t
```

```ruby:Ruby
"a" == "a"    # => true
```

## 文字列をコードの大小で比較 (s-less?)

```el:EmacsLisp
(s-less? "a" "b")    ; => t
```

```ruby:Ruby
"a" < "b"    # => true
```

## 正規表現がマッチする？ (s-matches?)

```el:EmacsLisp
(s-matches? "\\w+" "foo")    ; => t
```

```ruby:Ruby
"foo".match?(/\w+/)    # => true
```

## なんもない？ (s-blank?)

```el:EmacsLisp
(s-blank? "")    ; => t
```

```ruby:ActiveSupport
"".blank?    # => true
```

## なんかある？ (s-present?)

```el:EmacsLisp
(s-present? "x")    ; => t
```

```ruby:ActiveSupport
"x".present?    # => true
```

## なんかあればそれ (s-presence)

```el:EmacsLisp
(s-presence "x")    ; => "x"
```

```ruby:ActiveSupport
"x".presence    # => "x"
```

## 全部小文字？ (s-lowercase?)

```el:EmacsLisp
(s-lowercase? "foo")    ; => t
```

```ruby:Ruby
"foo".match?(/\A[[:lower:]]*\z/)    # => true
```

## 全部大文字？ (s-uppercase?)

```el:EmacsLisp
(s-uppercase? "FOO")    ; => t
```

```ruby:Ruby
"FOO".match?(/\A[[:upper:]]*\z/)    # => true
```

## 大文字と小文字の両方含まれる？ (s-mixedcase?)

```el:EmacsLisp
(s-mixedcase? "aBc")    ; => t
```

```ruby:Ruby
str = "aBc"    # => "aBc"
str.match?(/[[:upper:]]/) && str.match?(/[[:lower:]]/)    # => true
```

## 最初だけ大文字？ (s-capitalized?)

```el:EmacsLisp
(s-capitalized? "Foo")    ; => t
```

```ruby:Ruby
"Foo".match?(/\A[[:upper:]][[:lower:]]/)    # => true
```

## 全部数文字？ (s-numeric?)

```el:EmacsLisp
(s-numeric? "123")    ; => t
```

```ruby:Ruby
"123".match?(/\A\d+\z/)    # => true
```

## 文字列置換 (s-replace)

```el:EmacsLisp
(s-replace "a" "x" "abab")    ; => "xbxb"
```

```ruby:Ruby
"abab".gsub(/a/, "x")    # => "xbxb"
```

## 複数指定できる文字列置換 (s-replace-all)

```el:EmacsLisp
(s-replace-all '(("a" . "x") ("b" . "y")) "abab")    ; => "xyxy"
```

```ruby:Ruby
{"a" => "x", "b" => "y"}.inject("abab") { |s, (a, b)| s.gsub(a, b) }    # => "xyxy"
```

## 小文字にする (s-downcase)

```el:EmacsLisp
(s-downcase "Foo")    ; => "foo"
```

```ruby:Ruby
"Foo".downcase    # => "foo"
```

## 大文字にする (s-upcase)

```el:EmacsLisp
(s-upcase "Foo")    ; => "FOO"
```

```ruby:Ruby
"Foo".upcase    # => "FOO"
```

## 先頭だけ大文字にする (s-capitalize)

```el:EmacsLisp
(s-capitalize "foo_bar")    ; => "Foo_bar"
```

```ruby:Ruby
"foo_bar".capitalize    # => "Foo_bar"
```

## 単語の先頭を大文字にする (s-titleize)

```el:EmacsLisp
(s-titleize "foo bar")    ; => "Foo Bar"
```

```ruby:ActiveSupport
"foo bar".titleize    # => "Foo Bar"
```

## 複数の関数を適用 (s-with)

```el:EmacsLisp
(s-with "abc" s-upcase s-reverse)    ; => "CBA"
```

```ruby:Ruby
[:upcase, :reverse].reduce("abc", &:send)    # => "CBA"
```

## 文字列内の位置を返す (s-index-of)

```el:EmacsLisp
(s-index-of "bc" "abcd")    ; => 1
```

```ruby:Ruby
"abcd".index("bc")    # => 1
```

## 反転 (s-reverse)

```el:EmacsLisp
(s-reverse "abc")    ; => "cba"
```

```ruby:Ruby
"abc".reverse    # => "cba"
```

## 複数のマッチした部分を返す (s-match-strings-all)

```el:EmacsLisp
(s-match-strings-all "\\w\\(\\w\\)" "a1 a2")    ; => (("a1" "1") ("a2" "2"))
```

```ruby:Ruby
"a1 a2".scan(/(\w(\w+))/)    # => [["a1", "1"], ["a2", "2"]]
```

## マッチした部分を返す (s-match)

```el:EmacsLisp
(s-match "\\w\\(\\w+\\)" "a1 a2")    ; => ("a1" "1")
```

```ruby:Ruby
"a1 a2".match(/\w(\w+)/).to_a    # => ["a1", "1"]
```

## マッチした部分の前で分離 (s-slice-at)

```el:EmacsLisp
(s-slice-at "a" "a1a2a3")    ; => ("a1" "a2" "a3")
```

```ruby:Ruby
"a1a2a3".split(/(?=a)/)    # => ["a1", "a2", "a3"]
```

## 単語っぽいのを拾う (s-split-words)

```el:EmacsLisp
; どんなルールだこれ
(s-split-words "ABCde ABC1 AbCd")    ; => ("AB" "Cde" "AB" "C1" "Ab" "Cd")
```

```ruby:Ruby
s = "ABCde ABC1 AbCd"
s = s.gsub(/([[:upper:]])([[:upper:]][\d[:lower:]])/, '\1 \2')    # => "AB Cde AB C1 AbCd"
s = s.gsub(/([[:lower:]])([[:upper:]])/, '\1 \2')    # => "AB Cde AB C1 Ab Cd"
s.split(/[^[:word:]]+/)    # => ["AB", "Cde", "AB", "C1", "Ab", "Cd"]
```

## ローワーキャメルケース化 (s-lower-camel-case)

```el:EmacsLisp
(s-lower-camel-case "foo-bar")    ; => "fooBar"
```

```ruby:ActiveSupport
"foo-bar".underscore.camelize(:lower)    # => "fooBar"
```

## アッパーキャメルケース化 (s-upper-camel-case)

```el:EmacsLisp
(s-upper-camel-case "foo-bar")    ; => "FooBar"
```

```ruby:ActiveSupport
"foo-bar".underscore.camelize    # => "FooBar"
```

## スネークケース化 (s-snake-case)

```el:EmacsLisp
(s-snake-case "foo-bar")    ; => "foo_bar"
```

```ruby:ActiveSupport
"foo-bar".underscore    # => "foo_bar"
```

## ケバブケース化 (s-dashed-words)

```el:EmacsLisp
(s-dashed-words "FooBar")    ; => "foo-bar"
```

```ruby:ActiveSupport
"FooBar".underscore.dasherize    # => "foo-bar"
```

## 先頭の単語の最初だけ大文字 (s-capitalized-words)

```el:EmacsLisp
(s-capitalized-words "FOO BAR")    ; => "Foo bar"
```

```ruby:Ruby
words = "FOO BAR".split(/\s+/)
[words.first.capitalize, words.drop(1).collect(&:downcase)].join(" ")    # => "Foo bar"
```

## 単語の先頭だけ大文字 (s-titleized-words)

```el:EmacsLisp
(s-titleized-words "foo bar")    ; => "Foo Bar"
```

```ruby:Ruby
"foo bar".split(/\s+/).collect(&:capitalize) * " "    # => "Foo Bar"
```

## 先頭の文字だけ集める (s-word-initials)

```el:EmacsLisp
(s-word-initials "foo bar")    ; => "fb"
```

```ruby:Ruby
"foo bar".scan(/(\w)\w*/).join    # => "fb"
```

## 書式にキーワードを埋めて展開 (s-format)

```el:EmacsLisp
;; alist
(s-format "${a}" 'aget '(("a" . "x") ("b" . "y")))    ; => "x"
;; sequence
(s-format "$0" 'elt ["x" "y"])    ; => "x"
;; hash
(setq v (make-hash-table :test 'equal))
(puthash "a" "x" v)
(puthash "b" "y" v)
(s-format "${a}" 'gethash v)    ; => "x"
```

```ruby:Ruby
"%{a}" % {a: "x", b: "y"}    # => "x"
"%1$s" % ["x", "y"]    # => "x"
```

## 変数名を埋めて評価 (s-lex-format)

```el:EmacsLisp
(setq a '(1 2 3))
(s-lex-format "a = ${a}")    ; => "a = (1 2 3)"
```

```ruby:Ruby
a = [1, 2, 3]
"a = #{a}"    # => "a = [1, 2, 3]"
```

## 変数を埋める書式をコードに変換 (s-lex-fmt|expand)

```el:EmacsLisp
(setq a '(1 . 2))    ; => (1 . 2)
(setq v (s-lex-fmt|expand "${a}"))    ; => (s-format "${a}" (quote aget) (list (cons "a" (format (if s-lex-value-as-lisp "%S" "%s") a))))
(eval v)    ; => "(1 . 2)"
```

## マッチした個数を返す (s-count-matches)

```el:EmacsLisp
(s-count-matches "\\w+" "a b c")    ; => 3
```

```ruby:Ruby
"a b c".scan(/\w+/).count    # => 3
```

## 前後に文字列を追加 (s-wrap)

```el:EmacsLisp
(s-wrap "foo" "(" ")")    ; => "(foo)"
```

```ruby:Ruby
"(" + "foo" + ")"    # => "(foo)"
```