Emacs用文字列操作ライブラリ s.el の使い方の練習です。
自分用およびRuby脳な人にもわかりやすいように Ruby だとどんな感じになるかも合わせて書いています。
左スペース除去 (s-trim-left)
EmacsLisp
(s-trim-left " a ") ; => "a "
Ruby
" a ".lstrip # => "a "
右スペース除去 (s-trim-right)
EmacsLisp
(s-trim-right " a ") ; => " a"
Ruby
" a ".rstrip # => " a"
左右スペース除去 (s-trim)
EmacsLisp
(s-trim " a ") ; => "a"
Ruby
" a ".strip # => "a"
2つ以上のスペースを1つに置換 (s-collapse-whitespace)
EmacsLisp
(s-collapse-whitespace " a b c ") ; => " a b c "
Ruby
" a b c ".squeeze(" ") # => " a b c "
区切り文字で分割 (s-split)
EmacsLisp
(s-split "," "a,b,c") ; => ("a" "b" "c")
Ruby
"a,b,c".split(/,/) # => ["a", "b", "c"]
区切り文字でN個だけ分割 (s-split-up-to)
EmacsLisp
(s-split-up-to "," "a,b,c" 1) ; => ("a" "b,c")
Ruby
"a,b,c".split(/,/, 2) # => ["a", "b,c"]
行毎に分割 (s-lines)
EmacsLisp
(s-lines "a\nb\nc") ; => ("a" "b" "c")
Ruby
"a\nb\nc".split(/\n/) # => ["a", "b", "c"]
区切り文字を間に入れて結合 (s-join)
EmacsLisp
(s-join "," '("a" "b" "c")) ; => "a,b,c"
Ruby
["a", "b", "c"].join(",") # => "a,b,c"
文字列の結合 (s-concat)
EmacsLisp
(s-concat "a" "b" "c") ; => "abc"
Ruby
"a" "b" "c" # => "abc"
前に結合 (s-prepend)
EmacsLisp
(s-prepend "_" "foo") ; => "_foo"
Ruby
"_" + "foo" # => "_foo"
後ろに結合 (s-append)
EmacsLisp
(s-append "_" "foo") ; => "foo_"
Ruby
"foo" + "_" # => "foo_"
文字列の繰り返し (s-repeat)
EmacsLisp
(s-repeat 3 "a") ; => "aaa"
Ruby
"a" * 3 # => "aaa"
プレフィクス除去 (s-chop-prefix)
EmacsLisp
(s-chop-prefix "a" "ax") ; => "x"
Ruby
"ax".sub(/\Aa/, "") # => "x"
複数のプレフィクス除去 (s-chop-prefixes)
EmacsLisp
(s-chop-prefixes '("a" "b") "abx") ; => "x"
Ruby
["a", "b"].inject("abx") { |a, e| a.sub(/\A#{e}/, "") } # => "x"
サフィックス除去 (s-chop-suffix)
EmacsLisp
(s-chop-suffix "a" "xa") ; => "x"
Ruby
"xa".sub(/a\z/, "") # => "x"
複数のサフィックス除去 (s-chop-suffixes)
EmacsLisp
(s-chop-suffixes '("a" "b") "xba") ; => "x"
Ruby
["a", "b"].inject("xba") { |a, e| a.sub(/#{e}\z/, "") } # => "x"
共通のプレフィクスを抽出 (s-shared-start)
EmacsLisp
(s-shared-start "axb" "ayb") ; => "a"
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)
EmacsLisp
(s-shared-end "axb" "ayb") ; => "b"
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)
EmacsLisp
(s-chomp "a\r\n") ; => "a"
Ruby
"a\r\n".chomp # => "a"
ちょんぎる (s-truncate)
EmacsLisp
(s-truncate 5 "0123456789") ; => "01..."
ActiveSupport
"0123456789".truncate(5) # => "01..."
指定横幅に収まるように整形 (s-word-wrap)
EmacsLisp
(s-word-wrap 4 "a b c") ; => "a b\nc"
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)
EmacsLisp
(s-center 5 "a") ; => " a "
Ruby
"a".center(5) # => " a "
左寄せ (s-pad-right)
EmacsLisp
(s-pad-right 5 " " "a") ; => "a "
Ruby
"a".ljust(5) # => "a "
右寄せ (s-pad-left)
EmacsLisp
(s-pad-left 5 " " "a") ; => " a"
Ruby
"a".rjust(5) # => " a"
先頭N文字 (s-left)
EmacsLisp
(s-left 2 "012") ; => "01"
Ruby
"012"[0...2] # => "01"
後ろのN文字 (s-right)
EmacsLisp
(s-right 2 "012") ; => "12"
Ruby
"012"[-2..-1] # => "12"
サフィックス確認 (s-ends-with?)
EmacsLisp
(s-ends-with? "c" "abc") ; => t
Ruby
"abc".end_with?("c") # => true
プレフィクス確認 (s-starts-with?)
EmacsLisp
(s-starts-with? "a" "abc") ; => t
Ruby
"abc".start_with?("a") # => true
文字列が含まれる? (s-contains?)
EmacsLisp
(s-contains? "b" "abc") ; => t
Ruby
"abc".include?("b") # => true
文字列が一致する? (s-equals?)
EmacsLisp
(s-equals? "a" "a") ; => t
Ruby
"a" == "a" # => true
文字列をコードの大小で比較 (s-less?)
EmacsLisp
(s-less? "a" "b") ; => t
Ruby
"a" < "b" # => true
正規表現がマッチする? (s-matches?)
EmacsLisp
(s-matches? "\\w+" "foo") ; => t
Ruby
"foo".match?(/\w+/) # => true
なんもない? (s-blank?)
EmacsLisp
(s-blank? "") ; => t
ActiveSupport
"".blank? # => true
なんかある? (s-present?)
EmacsLisp
(s-present? "x") ; => t
ActiveSupport
"x".present? # => true
なんかあればそれ (s-presence)
EmacsLisp
(s-presence "x") ; => "x"
ActiveSupport
"x".presence # => "x"
全部小文字? (s-lowercase?)
EmacsLisp
(s-lowercase? "foo") ; => t
Ruby
"foo".match?(/\A[[:lower:]]*\z/) # => true
全部大文字? (s-uppercase?)
EmacsLisp
(s-uppercase? "FOO") ; => t
Ruby
"FOO".match?(/\A[[:upper:]]*\z/) # => true
大文字と小文字の両方含まれる? (s-mixedcase?)
EmacsLisp
(s-mixedcase? "aBc") ; => t
Ruby
str = "aBc" # => "aBc"
str.match?(/[[:upper:]]/) && str.match?(/[[:lower:]]/) # => true
最初だけ大文字? (s-capitalized?)
EmacsLisp
(s-capitalized? "Foo") ; => t
Ruby
"Foo".match?(/\A[[:upper:]][[:lower:]]/) # => true
全部数文字? (s-numeric?)
EmacsLisp
(s-numeric? "123") ; => t
Ruby
"123".match?(/\A\d+\z/) # => true
文字列置換 (s-replace)
EmacsLisp
(s-replace "a" "x" "abab") ; => "xbxb"
Ruby
"abab".gsub(/a/, "x") # => "xbxb"
複数指定できる文字列置換 (s-replace-all)
EmacsLisp
(s-replace-all '(("a" . "x") ("b" . "y")) "abab") ; => "xyxy"
Ruby
{"a" => "x", "b" => "y"}.inject("abab") { |s, (a, b)| s.gsub(a, b) } # => "xyxy"
小文字にする (s-downcase)
EmacsLisp
(s-downcase "Foo") ; => "foo"
Ruby
"Foo".downcase # => "foo"
大文字にする (s-upcase)
EmacsLisp
(s-upcase "Foo") ; => "FOO"
Ruby
"Foo".upcase # => "FOO"
先頭だけ大文字にする (s-capitalize)
EmacsLisp
(s-capitalize "foo_bar") ; => "Foo_bar"
Ruby
"foo_bar".capitalize # => "Foo_bar"
単語の先頭を大文字にする (s-titleize)
EmacsLisp
(s-titleize "foo bar") ; => "Foo Bar"
ActiveSupport
"foo bar".titleize # => "Foo Bar"
複数の関数を適用 (s-with)
EmacsLisp
(s-with "abc" s-upcase s-reverse) ; => "CBA"
Ruby
[:upcase, :reverse].reduce("abc", &:send) # => "CBA"
文字列内の位置を返す (s-index-of)
EmacsLisp
(s-index-of "bc" "abcd") ; => 1
Ruby
"abcd".index("bc") # => 1
反転 (s-reverse)
EmacsLisp
(s-reverse "abc") ; => "cba"
Ruby
"abc".reverse # => "cba"
複数のマッチした部分を返す (s-match-strings-all)
EmacsLisp
(s-match-strings-all "\\w\\(\\w\\)" "a1 a2") ; => (("a1" "1") ("a2" "2"))
Ruby
"a1 a2".scan(/(\w(\w+))/) # => [["a1", "1"], ["a2", "2"]]
マッチした部分を返す (s-match)
EmacsLisp
(s-match "\\w\\(\\w+\\)" "a1 a2") ; => ("a1" "1")
Ruby
"a1 a2".match(/\w(\w+)/).to_a # => ["a1", "1"]
マッチした部分の前で分離 (s-slice-at)
EmacsLisp
(s-slice-at "a" "a1a2a3") ; => ("a1" "a2" "a3")
Ruby
"a1a2a3".split(/(?=a)/) # => ["a1", "a2", "a3"]
単語っぽいのを拾う (s-split-words)
EmacsLisp
; どんなルールだこれ
(s-split-words "ABCde ABC1 AbCd") ; => ("AB" "Cde" "AB" "C1" "Ab" "Cd")
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)
EmacsLisp
(s-lower-camel-case "foo-bar") ; => "fooBar"
ActiveSupport
"foo-bar".underscore.camelize(:lower) # => "fooBar"
アッパーキャメルケース化 (s-upper-camel-case)
EmacsLisp
(s-upper-camel-case "foo-bar") ; => "FooBar"
ActiveSupport
"foo-bar".underscore.camelize # => "FooBar"
スネークケース化 (s-snake-case)
EmacsLisp
(s-snake-case "foo-bar") ; => "foo_bar"
ActiveSupport
"foo-bar".underscore # => "foo_bar"
ケバブケース化 (s-dashed-words)
EmacsLisp
(s-dashed-words "FooBar") ; => "foo-bar"
ActiveSupport
"FooBar".underscore.dasherize # => "foo-bar"
先頭の単語の最初だけ大文字 (s-capitalized-words)
EmacsLisp
(s-capitalized-words "FOO BAR") ; => "Foo bar"
Ruby
words = "FOO BAR".split(/\s+/)
[words.first.capitalize, words.drop(1).collect(&:downcase)].join(" ") # => "Foo bar"
単語の先頭だけ大文字 (s-titleized-words)
EmacsLisp
(s-titleized-words "foo bar") ; => "Foo Bar"
Ruby
"foo bar".split(/\s+/).collect(&:capitalize) * " " # => "Foo Bar"
先頭の文字だけ集める (s-word-initials)
EmacsLisp
(s-word-initials "foo bar") ; => "fb"
Ruby
"foo bar".scan(/(\w)\w*/).join # => "fb"
書式にキーワードを埋めて展開 (s-format)
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
"%{a}" % {a: "x", b: "y"} # => "x"
"%1$s" % ["x", "y"] # => "x"
変数名を埋めて評価 (s-lex-format)
EmacsLisp
(setq a '(1 2 3))
(s-lex-format "a = ${a}") ; => "a = (1 2 3)"
Ruby
a = [1, 2, 3]
"a = #{a}" # => "a = [1, 2, 3]"
変数を埋める書式をコードに変換 (s-lex-fmt|expand)
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)
EmacsLisp
(s-count-matches "\\w+" "a b c") ; => 3
Ruby
"a b c".scan(/\w+/).count # => 3
前後に文字列を追加 (s-wrap)
EmacsLisp
(s-wrap "foo" "(" ")") ; => "(foo)"
Ruby
"(" + "foo" + ")" # => "(foo)"