egedit: do not save cursor movement in undo -- this is my stupid habit, and it comple...
[iv.d.git] / autocomplete.d
blobffc148526c6ebae7fa93e46b9e3954fcc05dfb4a
1 /* Invisible Vector Library
2 * coded by Ketmar // Invisible Vector <ketmar@ketmar.no-ip.org>
3 * Understanding is not required. Only obedience.
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, version 3 of the License ONLY.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 module iv.autocomplete is aliced;
19 import iv.alice;
22 /**
23 * Build list of suitable autocompletions.
25 * Params:
26 * cmd = user-given command prefix
27 * cmdlist = list of all available commands
29 * Returns:
30 * null = no matches (empty array)
31 * array with one item: exactly one match
32 * array with more that one item = [0] is max prefix, then list of autocompletes
34 * Throws:
35 * Out of memory exception
37 string[] autocomplete (string cmd, string[] cmdlist...) @trusted nothrow {
38 if (cmdlist.length == 0) return [cmd];
39 string found; // autoinit
40 usize foundlen, pfxcount; // autoinit
41 // ÐÅÒ×ÙÊ ÐÒÏÈÏÄ: ÓÞÉÔÁÅÍ ÐÒÅÆÉËÓÙ, ÚÁÐÏÍÉÎÁÅÍ ËÏÍÁÎÄÕ Ó ÓÁÍÙÍ ÄÌÉÎÎÙÍ ÐÒÅÆÉËÓÏÍ
42 foreach (immutable s; cmdlist) {
43 if (cmd.length <= s.length) {
44 usize pos = cmd.length;
45 foreach (immutable idx; 0..cmd.length) if (cmd[idx] != s[idx]) { pos = idx; break; }
46 if (pos == cmd.length) {
47 if (s.length > found.length) found = s;
48 ++pfxcount;
52 if (pfxcount == 0) return null; // ÎÅ ÎÁÛÌÉ ×ÏÏÂÝÅ ÎÉÈÅÒÁ, ×ÁÌÉÍ ÏÔÓÀÄÁ, ÐÁÃÁÎÙ!
53 if (pfxcount == 1) return [found]; // ÅÓÔØ ÔÏÌØËÏ ÏÄÉÎ, ÕÎÏÓÉÔÅ
54 // ÎÁÛÌÉ ÄÏÈÅÒÁ, ÜÔÏ ÐÒÉÓËÏÒÂÎÏ
55 // ÉÝÅÍ ÓÁÍÙÊ ÄÌÉÎÎÙÊ ÐÒÅÆÉËÓ ÉÚ ×ÏÚÍÏÖÎÙÈ, ÚÁÏÄÎÏ ÓÏÂÉÒÁÅÍ ×Ó£, ÞÔÏ ÍÏÖÎÏ
56 string[] res = new string[pfxcount+1]; // ÓÀÄÁ ÓÌÏÖÉÍ ×Ó£ ÐÏÄÈÏÄÑÝÅÅ; ÍÙ ÔÏÞÎÏ ÚÎÁÅÍ, ÓËÏÌØËÏ ÉÈ ÂÕÄÅÔ
57 usize respos = 1; // res[0] -- ÓÁÍÙÊ ÄÌÉÎÎÙÊ ÐÒÅÆÉËÓ, ÎÁÞÎ£Í Ó [1]
58 usize slen = cmd.length; // ÔÏÞÎÏ ÎÅ ÂÏÌØÛÅ found.length
59 foreach (immutable s; cmdlist) {
60 if (s.length >= slen) {
61 usize pos = slen;
62 foreach (immutable idx; 0..slen) if (found[idx] != s[idx]) { pos = idx; break; }
63 if (pos == slen) {
64 // ÎÁÛÅ, ÚÁÐÏÍÉÎÁÅÍ É ÐÒÁ×ÉÍ ÐÒÅÆÉËÓ
65 res[respos++] = s;
66 // ÏÂÒÅÚÁÅÍ ÐÏ ÍÉÎÉÍÕÍÕ, ÎÏ ÎÅ ÍÅÎØÛÅ, ÞÅÍ ÎÁÄÏ
67 for (; pos < found.length && pos < s.length; ++pos) if (found[pos] != s[pos]) break;
68 if (pos < found.length) {
69 found = found[0..pos];
70 if (slen > pos) slen = pos;
75 // ÐÅÒ×ÙÍ ÜÌÅÍÅÎÔÏÍ ×ÓÔÁ×ÉÍ ÍÁËÓÉÍÁÌØÎÙÊ ÐÒÅÆÉËÓ
76 res[0] = found;
77 // ×Ó£
78 return res;
82 unittest {
83 import std.stdio;
85 static immutable string[3] clist0 = ["aaz", "aabed", "aand"];
86 //writeln("--------");
87 assert(autocomplete("", clist0) == ["aa", "aaz", "aabed", "aand"]);
88 assert(autocomplete("a", clist0) == ["aa", "aaz", "aabed", "aand"]);
89 assert(autocomplete("aa", clist0) == ["aa", "aaz", "aabed", "aand"]);
90 assert(autocomplete("aab", clist0) == ["aabed"]);
93 static immutable string[3] clist1 = ["az", "abed", "and"];
94 //writeln("--------");
95 assert(autocomplete("", clist1) == ["a", "az", "abed", "and"]);
96 assert(autocomplete("a", clist1) == ["a", "az", "abed", "and"]);
97 assert(autocomplete("aa", clist1) == []);
98 assert(autocomplete("aab", clist1) == []);