diff options
author | Andreas Rumpf <rumpf_a@web.de> | 2017-03-07 10:58:43 +0100 |
---|---|---|
committer | Andreas Rumpf <rumpf_a@web.de> | 2017-03-07 10:58:43 +0100 |
commit | 9ed322323ee6f396595aa93aa6c244b3a5637d50 (patch) | |
tree | 1d748968a699e359f11b6b5513476f5f13dc6f89 /compiler/prefixmatches.nim | |
parent | d9ad6465af0aad25c4dba928f0cc9499cff6017b (diff) | |
download | Nim-9ed322323ee6f396595aa93aa6c244b3a5637d50.tar.gz |
nimsuggest: better ordering of symbols (part 1)
Diffstat (limited to 'compiler/prefixmatches.nim')
-rw-r--r-- | compiler/prefixmatches.nim | 86 |
1 files changed, 86 insertions, 0 deletions
diff --git a/compiler/prefixmatches.nim b/compiler/prefixmatches.nim new file mode 100644 index 000000000..2630225de --- /dev/null +++ b/compiler/prefixmatches.nim @@ -0,0 +1,86 @@ +# +# +# The Nim Compiler +# (c) Copyright 2017 Andreas Rumpf +# +# See the file "copying.txt", included in this +# distribution, for details about the copyright. +# + +from strutils import toLowerAscii + +type + PrefixMatch* {.pure.} = enum + None, ## no prefix detected + Prefix, ## prefix does match the symbol + Substr, ## prefix is a substring of the symbol + Abbrev ## prefix is an abbreviation of the symbol + +proc prefixMatch*(p, s: string): PrefixMatch = + template eq(a, b): bool = a.toLowerAscii == b.toLowerAscii + if p.len > s.len: return PrefixMatch.None + var i = 0 + let L = s.len + # check for prefix/contains: + while i < L: + if s[i] == '_': inc i + if eq(s[i], p[0]): + var ii = i+1 + var jj = 1 + while ii < L and jj < p.len: + if p[jj] == '_': inc jj + if s[ii] == '_': inc ii + if not eq(s[ii], p[jj]): break + inc ii + inc jj + + if jj >= p.len: + if i == 0: return PrefixMatch.Prefix + else: return PrefixMatch.Substr + inc i + # check for abbrev: + if eq(s[0], p[0]): + i = 1 + var j = 1 + while i < s.len: + if s[i] == '_' and i < s.len-1: + if j < p.len and eq(p[j], s[i+1]): inc j + else: return PrefixMatch.None + if s[i] in {'A'..'Z'} and s[i-1] notin {'A'..'Z'}: + if j < p.len and eq(p[j], s[i]): inc j + else: return PrefixMatch.None + inc i + return PrefixMatch.Abbrev + return PrefixMatch.None + +when isMainModule: + import macros + + macro check(val, body: untyped): untyped = + result = newStmtList() + expectKind body, nnkStmtList + for b in body: + expectKind b, nnkPar + expectLen b, 2 + let p = b[0] + let s = b[1] + result.add quote do: + echo prefixMatch(`p`, `s`) == `val` + + check PrefixMatch.Prefix: + ("abc", "abc") + ("a", "abc") + ("xyz", "X_yzzzZe") + + check PrefixMatch.Substr: + ("b", "abc") + ("abc", "fooabcabc") + ("abC", "foo_AB_c") + + check PrefixMatch.Abbrev: + ("abc", "AxxxBxxxCxxx") + ("xyz", "X_yabcZe") + + check PrefixMatch.None: + ("foobar", "afkslfjd_as") + ("xyz", "X_yuuZuuZe") |