mirror of https://github.com/adamdruppe/arsd.git
ketmar string patch
This commit is contained in:
parent
5f7dcb8e44
commit
b9614e483d
178
simpledisplay.d
178
simpledisplay.d
|
@ -3653,14 +3653,25 @@ struct KeyEvent {
|
||||||
if (!this.key) return null;
|
if (!this.key) return null;
|
||||||
|
|
||||||
// put modifiers
|
// put modifiers
|
||||||
if (this.modifierState&ModifierState.ctrl) put("C-");
|
if (this.modifierState&ModifierState.ctrl) put("Ctrl+");
|
||||||
if (this.modifierState&ModifierState.alt) put("M-");
|
if (this.modifierState&ModifierState.alt) put("Alt+");
|
||||||
if (this.modifierState&ModifierState.windows) put("H-");
|
if (this.modifierState&ModifierState.windows) put("Win+");
|
||||||
if (this.modifierState&ModifierState.shift) put("S-");
|
if (this.modifierState&ModifierState.shift) put("Shift+");
|
||||||
|
|
||||||
foreach (string kn; __traits(allMembers, Key)) {
|
foreach (string kn; __traits(allMembers, Key)) {
|
||||||
if (this.key == __traits(getMember, Key, kn)) {
|
if (this.key == __traits(getMember, Key, kn)) {
|
||||||
put(kn);
|
// HACK!
|
||||||
|
static if (kn == "N0") put("0");
|
||||||
|
else static if (kn == "N1") put("1");
|
||||||
|
else static if (kn == "N2") put("2");
|
||||||
|
else static if (kn == "N3") put("3");
|
||||||
|
else static if (kn == "N4") put("4");
|
||||||
|
else static if (kn == "N5") put("5");
|
||||||
|
else static if (kn == "N6") put("6");
|
||||||
|
else static if (kn == "N7") put("7");
|
||||||
|
else static if (kn == "N8") put("8");
|
||||||
|
else static if (kn == "N9") put("9");
|
||||||
|
else put(kn);
|
||||||
return dest[0..dpos];
|
return dest[0..dpos];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3671,101 +3682,92 @@ struct KeyEvent {
|
||||||
|
|
||||||
string toStr() () { return cast(string)toStrBuf!true(null); } // it is safe to cast here
|
string toStr() () { return cast(string)toStrBuf!true(null); } // it is safe to cast here
|
||||||
|
|
||||||
// sorry for pasta, but i don't want to create new struct in `opEquals()`
|
/** Parse string into key name with modifiers. It accepts things like:
|
||||||
|
*
|
||||||
|
* C-H-1 -- emacs style (ctrl, and windows, and 1)
|
||||||
|
*
|
||||||
|
* Ctrl+Win+1 -- windows style
|
||||||
|
*
|
||||||
|
* Ctrl-Win-1 -- '-' is a valid delimiter too
|
||||||
|
*
|
||||||
|
* Ctrl Win 1 -- and space
|
||||||
|
*
|
||||||
|
* and even "Win + 1 + Ctrl".
|
||||||
|
*/
|
||||||
static KeyEvent parse (const(char)[] name) nothrow @trusted @nogc {
|
static KeyEvent parse (const(char)[] name) nothrow @trusted @nogc {
|
||||||
KeyEvent res;
|
auto nanchor = name; // keep it anchored, 'cause `name` may have NO_INTERIOR set
|
||||||
while (name.length && name.ptr[0] <= ' ') name = name[1..$];
|
|
||||||
|
// remove trailing spaces
|
||||||
while (name.length && name[$-1] <= ' ') name = name[0..$-1];
|
while (name.length && name[$-1] <= ' ') name = name[0..$-1];
|
||||||
uint mods = 0;
|
|
||||||
while (name.length > 1 && name.ptr[1] == '-') {
|
// tokens delimited by blank, '+', or '-'
|
||||||
switch (name.ptr[0]) {
|
// null on eol
|
||||||
case 'C': case 'c': mods |= ModifierState.ctrl; break;
|
const(char)[] getToken () nothrow @trusted @nogc {
|
||||||
case 'M': case 'm': mods |= ModifierState.alt; break;
|
// remove leading spaces and delimiters
|
||||||
case 'H': case 'h': mods |= ModifierState.windows; break;
|
while (name.length && (name[0] <= ' ' || name[0] == '+' || name[0] == '-')) name = name[1..$];
|
||||||
case 'S': case 's': mods |= ModifierState.shift; break;
|
if (name.length == 0) return null; // oops, no more tokens
|
||||||
default: return res; // alas
|
// get token
|
||||||
|
size_t epos = 0;
|
||||||
|
while (epos < name.length && name[epos] > ' ' && name[epos] != '+' && name[epos] != '-') ++epos;
|
||||||
|
assert(epos > 0 && epos <= name.length);
|
||||||
|
auto res = name[0..epos];
|
||||||
|
name = name[epos..$];
|
||||||
|
return res;
|
||||||
}
|
}
|
||||||
name = name[2..$];
|
|
||||||
|
static bool strEquCI (const(char)[] s0, const(char)[] s1) pure nothrow @trusted @nogc {
|
||||||
|
if (s0.length != s1.length) return false;
|
||||||
|
foreach (immutable ci, char c0; s0) {
|
||||||
|
if (c0 >= 'A' && c0 <= 'Z') c0 += 32; // poor man's tolower
|
||||||
|
char c1 = s1[ci];
|
||||||
|
if (c1 >= 'A' && c1 <= 'Z') c1 += 32; // poor man's tolower
|
||||||
|
if (c0 != c1) return false;
|
||||||
}
|
}
|
||||||
if (name.length == 0) return res;
|
return true;
|
||||||
res.modifierState = mods;
|
}
|
||||||
//HACK
|
|
||||||
if (name.length == 1 && name.ptr[0] >= '0' && name.ptr[0] <= '9') {
|
KeyEvent res;
|
||||||
final switch (name.ptr[0]) {
|
res.key = cast(Key)0; // just in case
|
||||||
case '0': name = "N0"; break;
|
tokenloop: for (;;) {
|
||||||
case '1': name = "N1"; break;
|
auto tk = getToken();
|
||||||
case '2': name = "N2"; break;
|
if (tk is null) break;
|
||||||
case '3': name = "N3"; break;
|
if (strEquCI(tk, "C") || strEquCI(tk, "Ctrl")) { res.modifierState |= ModifierState.ctrl; continue tokenloop; }
|
||||||
case '4': name = "N4"; break;
|
if (strEquCI(tk, "M") || strEquCI(tk, "Alt")) { res.modifierState |= ModifierState.alt; continue tokenloop; }
|
||||||
case '5': name = "N5"; break;
|
if (strEquCI(tk, "H") || strEquCI(tk, "Win") || strEquCI(tk, "Windows")) { res.modifierState |= ModifierState.windows; continue tokenloop; }
|
||||||
case '6': name = "N6"; break;
|
if (strEquCI(tk, "S") || strEquCI(tk, "Shift")) { res.modifierState |= ModifierState.shift; continue tokenloop; }
|
||||||
case '7': name = "N7"; break;
|
// try key name
|
||||||
case '8': name = "N8"; break;
|
if (res.key == 0) {
|
||||||
case '9': name = "N9"; break;
|
// little hack
|
||||||
|
if (tk.length == 1 && tk[0] >= '0' && tk[0] <= '9') {
|
||||||
|
final switch (tk[0]) {
|
||||||
|
case '0': tk = "N0"; break;
|
||||||
|
case '1': tk = "N1"; break;
|
||||||
|
case '2': tk = "N2"; break;
|
||||||
|
case '3': tk = "N3"; break;
|
||||||
|
case '4': tk = "N4"; break;
|
||||||
|
case '5': tk = "N5"; break;
|
||||||
|
case '6': tk = "N6"; break;
|
||||||
|
case '7': tk = "N7"; break;
|
||||||
|
case '8': tk = "N8"; break;
|
||||||
|
case '9': tk = "N9"; break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
foreach (string kn; __traits(allMembers, Key)) {
|
foreach (string kn; __traits(allMembers, Key)) {
|
||||||
if (kn.length == name.length) {
|
if (strEquCI(tk, kn)) { res.key = __traits(getMember, Key, kn); continue tokenloop; }
|
||||||
// case-insensitive comapre
|
|
||||||
bool ok = true;
|
|
||||||
foreach (immutable ci, char c0; kn) {
|
|
||||||
if (c0 >= 'A' && c0 <= 'Z') c0 += 32; // poor man's tolower
|
|
||||||
char c1 = name.ptr[ci];
|
|
||||||
if (c1 >= 'A' && c1 <= 'Z') c1 += 32; // poor man's tolower
|
|
||||||
if (c0 != c1) { ok = false; break; }
|
|
||||||
}
|
|
||||||
if (ok) { res.key = __traits(getMember, Key, kn); return res; }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return res; // at least modifier state, lol
|
// unknown or duplicate key name, get out of here
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return res; // something
|
||||||
}
|
}
|
||||||
|
|
||||||
bool opEquals() (const(char)[] name) const nothrow @trusted @nogc {
|
bool opEquals() (const(char)[] name) const nothrow @trusted @nogc {
|
||||||
while (name.length && name.ptr[0] <= ' ') name = name[1..$];
|
auto ke = KeyEvent.parse(name);
|
||||||
while (name.length && name[$-1] <= ' ') name = name[0..$-1];
|
if (this.key != ke.key) return false;
|
||||||
if (!this.key) return (name.length == 0);
|
// check modifiers
|
||||||
uint mods = 0;
|
ke.modifierState &= (ModifierState.ctrl|ModifierState.alt|ModifierState.shift|ModifierState.windows);
|
||||||
while (name.length > 1 && name.ptr[1] == '-') {
|
return ((this.modifierState&(ModifierState.ctrl|ModifierState.alt|ModifierState.shift|ModifierState.windows)) == ke.modifierState);
|
||||||
switch (name.ptr[0]) {
|
|
||||||
case 'C': case 'c': mods |= ModifierState.ctrl; break;
|
|
||||||
case 'M': case 'm': mods |= ModifierState.alt; break;
|
|
||||||
case 'H': case 'h': mods |= ModifierState.windows; break;
|
|
||||||
case 'S': case 's': mods |= ModifierState.shift; break;
|
|
||||||
default: return false; // alas
|
|
||||||
}
|
|
||||||
name = name[2..$];
|
|
||||||
}
|
|
||||||
if (name.length == 0) return false;
|
|
||||||
if ((this.modifierState&(ModifierState.ctrl|ModifierState.alt|ModifierState.shift|ModifierState.windows)) != mods) return false;
|
|
||||||
//HACK
|
|
||||||
if (name.length == 1 && name.ptr[0] >= '0' && name.ptr[0] <= '9') {
|
|
||||||
final switch (name.ptr[0]) {
|
|
||||||
case '0': name = "N0"; break;
|
|
||||||
case '1': name = "N1"; break;
|
|
||||||
case '2': name = "N2"; break;
|
|
||||||
case '3': name = "N3"; break;
|
|
||||||
case '4': name = "N4"; break;
|
|
||||||
case '5': name = "N5"; break;
|
|
||||||
case '6': name = "N6"; break;
|
|
||||||
case '7': name = "N7"; break;
|
|
||||||
case '8': name = "N8"; break;
|
|
||||||
case '9': name = "N9"; break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
foreach (string kn; __traits(allMembers, Key)) {
|
|
||||||
if (kn.length == name.length) {
|
|
||||||
// case-insensitive comapre
|
|
||||||
bool ok = true;
|
|
||||||
foreach (immutable ci, char c0; kn) {
|
|
||||||
if (c0 >= 'A' && c0 <= 'Z') c0 += 32; // poor man's tolower
|
|
||||||
char c1 = name.ptr[ci];
|
|
||||||
if (c1 >= 'A' && c1 <= 'Z') c1 += 32; // poor man's tolower
|
|
||||||
if (c0 != c1) { ok = false; break; }
|
|
||||||
}
|
|
||||||
if (ok && this.key == __traits(getMember, Key, kn)) return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue