Module: BitClust::NameUtils

Overview

Utilities for conversion among names, ids and URL fragments.

Constant Summary collapse

LIBNAME_RE =
%r<[\w\-]+(/[\w\-]+)*>
CONST_RE =
/[A-Z]\w*/
CONST_PATH_RE =
/#{CONST_RE}(?:::#{CONST_RE})*/
CLASS_NAME_RE =
/(?:#{CONST_RE}(?:::compatible)?|fatal|ARGF\.class|main)/
CLASS_PATH_RE =
/(?:#{CONST_PATH_RE}(?:::compatible)?|fatal|ARGF\.class|main)/
METHOD_NAME_RE =
/\w+[?!=]?|===|==|=~|<=>|<=|>=|!=|!~|!@|!|\[\]=|\[\]|\*\*|>>|<<|\+@|\-@|[~+\-*\/%&|^<>`]/
TYPEMARK_RE =
/(?:\.|\#|\.\#|::|\$)/
METHOD_SPEC_RE =
/#{CLASS_PATH_RE}#{TYPEMARK_RE}#{METHOD_NAME_RE}/
GVAR_RE =
/\$(?:\w+|-.|\S)/
MID =
/\A#{METHOD_NAME_RE}\z/
NAME_TO_MARK =
{
  :singleton_method => '.',
  :instance_method  => '#',
  :module_function  => '.#',
  :constant         => '::',
  :special_variable => '$'
}
MARK_TO_NAME =
NAME_TO_MARK.invert
NAME_TO_CHAR =
{
  :singleton_method => 's',
  :instance_method  => 'i',
  :module_function  => 'm',
  :constant         => 'c',
  :special_variable => 'v'
}
CHAR_TO_NAME =
NAME_TO_CHAR.invert
MARK_TO_CHAR =
{
  '.'  => 's',
  '#'  => 'i',
  '.#' => 'm',
  '::' => 'c',
  '$'  => 'v'
}
CHAR_TO_MARK =
MARK_TO_CHAR.invert
@@split_method_id =

Signature:

  • Hash[String, untyped]

{}

Class Method Summary collapse

Class Method Details

.build_method_id(libid, cid, t, name) ⇒ Object



124
125
126
# File 'lib/bitclust/nameutils.rb', line 124

def build_method_id(libid, cid, t, name)
  "#{cid}/#{typename2char(t)}.#{encodename_url(name)}.#{libid}"
end

.classid2name(id) ⇒ Object



50
51
52
# File 'lib/bitclust/nameutils.rb', line 50

def classid2name(id)
  id.gsub(/=/, '::')
end

.classname2id(name) ⇒ Object



46
47
48
# File 'lib/bitclust/nameutils.rb', line 46

def classname2id(name)
  name.gsub(/::/, '=')
end

.classname?(str) ⇒ Boolean

Returns:

  • (Boolean)


42
43
44
# File 'lib/bitclust/nameutils.rb', line 42

def classname?(str)
  (/\A#{CLASS_PATH_RE}\z/o =~ str) ? true : false
end

.decodeid(str) ⇒ Object

encoded string -> case-sensitive ID (decode only [A-Z])



253
254
255
# File 'lib/bitclust/nameutils.rb', line 253

def decodeid(str)
  str.gsub(/-[a-z]/ni) {|s| (s[1,1] || raise).upcase }
end

.decodename_fs(str) ⇒ Object



263
264
265
266
267
# File 'lib/bitclust/nameutils.rb', line 263

def decodename_fs(str)
  str.gsub(/=[\da-h]{2}|-[a-z]/ni) {|s|
    (/\A-/ =~ s) ? (s[1,1] || raise).upcase : (s[1,2] || raise).hex.chr
  }
end

.decodename_url(str) ⇒ Object

case-sensitive ID -> string



235
236
237
# File 'lib/bitclust/nameutils.rb', line 235

def decodename_url(str)
  str.gsub(/=[\da-h]{2}/ni) {|s| (s[1,2] || raise).hex.chr }
end

.display_typemark(mark, version) ⇒ Object

bitclust#250: Ruby 4.0 以降のドキュメントでは module function の表記を るりま独自の ".#" から "?." に変える(表示のみ。ソース側は既に "?." 記法に対応済みで、内部的には従来どおり ".#" に変換される)。

これは見た目だけの変換であり、method id・URL・spec 文字列など識別子と して使う ".#" 自体は一切変えない。typemark が '.#' 以外、または version が不明(nil/空)な場合はそのまま返す。バージョン比較は文字列比較では なく Gem::Version で行う("10.0" を文字列比較すると "4.0" より小さく 見えてしまうため)。



219
220
221
222
223
# File 'lib/bitclust/nameutils.rb', line 219

def display_typemark(mark, version)
  return mark unless mark == '.#'
  return mark unless version && !version.empty?
  Gem::Version.new(version) >= Gem::Version.new('4.0') ? '?.' : mark
end

.encodeid(str) ⇒ Object

case-sensitive ID -> encoded string (encode only [A-Z])



248
249
250
# File 'lib/bitclust/nameutils.rb', line 248

def encodeid(str)
  str.gsub(/[A-Z]/n) {|ch| "-#{ch}" }.downcase
end

.encodename_fs(str) ⇒ Object



257
258
259
260
261
# File 'lib/bitclust/nameutils.rb', line 257

def encodename_fs(str)
  str.gsub(/[^a-z0-9_]/n) {|ch|
    (/[A-Z]/n =~ ch) ? "-#{ch}" : sprintf('=%02x', (ch[0] || raise).ord)
  }.downcase
end

.encodename_rdocurl(str) ⇒ Object

string -> encoded string in a rdoc way



240
241
242
243
244
245
# File 'lib/bitclust/nameutils.rb', line 240

def encodename_rdocurl(str)
  str = str.gsub(/[^A-Za-z0-9_.]/n) {|ch|
    sprintf('-%02X', (ch[0] || raise).ord)
  }
  str.sub(/\A-/, '')
end

.encodename_url(str) ⇒ Object

string -> case-sensitive ID



230
231
232
# File 'lib/bitclust/nameutils.rb', line 230

def encodename_url(str)
  str.gsub(/[^A-Za-z0-9_]/n) {|ch| sprintf('=%02x', (ch[0] || raise).ord) }
end

.functionname?(n) ⇒ Boolean

Returns:

  • (Boolean)


225
226
227
# File 'lib/bitclust/nameutils.rb', line 225

def functionname?(n)
  /\A\w+\z/ =~ n ? true : false
end

.gvarname?(str) ⇒ Boolean

Returns:

  • (Boolean)


114
115
116
# File 'lib/bitclust/nameutils.rb', line 114

def gvarname?(str)
  GVAR_RE =~ str ? true : false
end

.html_filename(basename, suffix) ⇒ Object



269
270
271
# File 'lib/bitclust/nameutils.rb', line 269

def html_filename(basename, suffix)
  "#{basename}#{suffix}"
end

.libid2name(id) ⇒ Object



38
39
40
# File 'lib/bitclust/nameutils.rb', line 38

def libid2name(id)
  id.split('.').map {|ent| decodename_url(ent) }.join('/')
end

.libname2id(name) ⇒ Object



34
35
36
# File 'lib/bitclust/nameutils.rb', line 34

def libname2id(name)
  name.split('/').map {|ent| encodename_url(ent) }.join('.')
end

.libname?(str) ⇒ Boolean

Returns:

  • (Boolean)


30
31
32
# File 'lib/bitclust/nameutils.rb', line 30

def libname?(str)
  (/\A#{LIBNAME_RE}\z/o =~ str) ? true : false
end

.method_spec?(str) ⇒ Boolean

Returns:

  • (Boolean)


54
55
56
57
# File 'lib/bitclust/nameutils.rb', line 54

def method_spec?(str)
  return false if str == "ARGF.class"
  (/\A#{METHOD_SPEC_RE}\z/o =~ str) ? true : false
end

.methodid2classid(id) ⇒ Object



89
90
91
92
# File 'lib/bitclust/nameutils.rb', line 89

def methodid2classid(id)
  c, _t, _m, _lib = split_method_id(id)
  c
end

.methodid2libid(id) ⇒ Object



84
85
86
87
# File 'lib/bitclust/nameutils.rb', line 84

def methodid2libid(id)
  _c, _t, _m, lib = split_method_id(id)
  lib
end

.methodid2mname(id) ⇒ Object



109
110
111
112
# File 'lib/bitclust/nameutils.rb', line 109

def methodid2mname(id)
  _c, _t, m, _lib = split_method_id(id)
  decodename_url(m)
end

.methodid2specparts(id) ⇒ Object



79
80
81
82
# File 'lib/bitclust/nameutils.rb', line 79

def methodid2specparts(id)
  c, t, m, lib = split_method_id(id)
  [classid2name(c), typechar2mark(t), decodename_url(m), libid2name(lib)]
end

.methodid2specstring(id) ⇒ Object



74
75
76
77
# File 'lib/bitclust/nameutils.rb', line 74

def methodid2specstring(id)
  c, t, m, _lib = split_method_id(id)
  classid2name(c) + typechar2mark(t) + decodename_url(m)
end

.methodid2typechar(id) ⇒ Object



94
95
96
97
# File 'lib/bitclust/nameutils.rb', line 94

def methodid2typechar(id)
  _c, t, _m, _lib = split_method_id(id)
  t
end

.methodid2typemark(id) ⇒ Object



104
105
106
107
# File 'lib/bitclust/nameutils.rb', line 104

def methodid2typemark(id)
  _c, t, _m, _lib = split_method_id(id)
  typechar2mark(t)
end

.methodid2typename(id) ⇒ Object



99
100
101
102
# File 'lib/bitclust/nameutils.rb', line 99

def methodid2typename(id)
  _c, t, _m, _lib = split_method_id(id)
  typechar2name(t)
end

.methodname?(str) ⇒ Boolean

Returns:

  • (Boolean)


120
121
122
# File 'lib/bitclust/nameutils.rb', line 120

def methodname?(str)
  (MID =~ str) ? true : false
end

.split_method_id(id) ⇒ Object

private module function



131
132
133
134
135
136
# File 'lib/bitclust/nameutils.rb', line 131

def split_method_id(id)
  @@split_method_id[id] ||= begin
    c, rest = id.split("/")
    [c, *rest&.split(%r<[/\.]>, 3)]
  end
end

.split_method_spec(spec) ⇒ Object



59
60
61
62
63
64
65
66
67
68
69
70
71
72
# File 'lib/bitclust/nameutils.rb', line 59

def split_method_spec(spec)
  case spec
  when /\AKernel\$/
    return ['Kernel', '$', $' || raise]
  else
    m = /\A(#{CLASS_PATH_RE})(#{TYPEMARK_RE})(#{METHOD_NAME_RE})\z/o.match(spec) or
        raise ArgumentError, "wrong method spec: #{spec.inspect}"
    cname = m[1] || raise
    # @type var tmark: NameUtils::typemark
    tmark = _ = m[2] || raise
    mname = m[3] || raise
    return [cname, tmark, mname]
  end
end

.typechar2mark(char) ⇒ Object



200
201
202
203
# File 'lib/bitclust/nameutils.rb', line 200

def typechar2mark(char)
  CHAR_TO_MARK[char] or
      raise "must not happen: #{char.inspect}"
end

.typechar2name(char) ⇒ Object



181
182
183
184
# File 'lib/bitclust/nameutils.rb', line 181

def typechar2name(char)
  CHAR_TO_NAME[char] or
      raise "must not happen: #{char.inspect}"
end

.typechar?(c) ⇒ Boolean

Returns:

  • (Boolean)


172
173
174
# File 'lib/bitclust/nameutils.rb', line 172

def typechar?(c)
  CHAR_TO_NAME.key?(_ = c)
end

.typemark2char(mark) ⇒ Object



205
206
207
208
# File 'lib/bitclust/nameutils.rb', line 205

def typemark2char(mark)
  MARK_TO_CHAR[mark] or
      raise "must not happen: #{mark.inspect}"
end

.typemark2name(mark) ⇒ Object



157
158
159
160
# File 'lib/bitclust/nameutils.rb', line 157

def typemark2name(mark)
  MARK_TO_NAME[mark] or
      raise "must not happen: #{mark.inspect}"
end

.typemark?(m) ⇒ Boolean

Returns:

  • (Boolean)


196
197
198
# File 'lib/bitclust/nameutils.rb', line 196

def typemark?(m)
  MARK_TO_CHAR.key?(_ = m)
end

.typename2char(name) ⇒ Object



176
177
178
179
# File 'lib/bitclust/nameutils.rb', line 176

def typename2char(name)
  NAME_TO_CHAR[name] or
      raise "must not happen: #{name.inspect}"
end

.typename2mark(name) ⇒ Object



152
153
154
155
# File 'lib/bitclust/nameutils.rb', line 152

def typename2mark(name)
  NAME_TO_MARK[name] or
      raise "must not happen: #{name.inspect}"
end

.typename?(n) ⇒ Boolean

Returns:

  • (Boolean)


148
149
150
# File 'lib/bitclust/nameutils.rb', line 148

def typename?(n)
  NAME_TO_MARK.key?(_ = n)
end