diff options
-rw-r--r-- | catgirl.1 | 7 | ||||
-rw-r--r-- | chat.c | 4 | ||||
-rw-r--r-- | chat.h | 4 | ||||
-rw-r--r-- | command.c | 2 | ||||
-rw-r--r-- | edit.c | 52 | ||||
-rw-r--r-- | ui.c | 1 |
6 files changed, 61 insertions, 9 deletions
diff --git a/catgirl.1 b/catgirl.1 index 286d4f9..42569a3 100644 --- a/catgirl.1 +++ b/catgirl.1 @@ -1,4 +1,4 @@ -.Dd March 29, 2020 +.Dd March 30, 2020 .Dt CATGIRL 1 .Os . @@ -392,6 +392,9 @@ Transpose characters. Delete to beginning of line. .It Ic C-w Delete previous word. +.It Ic C-x +Expand a text macro beginning with +.Ql \e . .It Ic C-y Paste previously deleted text. .It Ic M-Enter @@ -403,7 +406,7 @@ Delete next word. .It Ic M-f Move to next word. .It Ic Tab -Complete nick, channel or command. +Complete nick, channel, command or macro. .El . .Ss Window Keys diff --git a/chat.c b/chat.c index 35c0ecd..258dde2 100644 --- a/chat.c +++ b/chat.c @@ -201,7 +201,9 @@ int main(int argc, char *argv[]) { set(&network.name, host); set(&self.nick, "*"); - commandComplete(); + + editCompleteAdd(); + commandCompleteAdd(); FILE *certFile = NULL; FILE *privFile = NULL; diff --git a/chat.h b/chat.h index 0a84053..545be03 100644 --- a/chat.h +++ b/chat.h @@ -198,7 +198,7 @@ void command(uint id, char *input); const char *commandIsPrivmsg(uint id, const char *input); const char *commandIsNotice(uint id, const char *input); const char *commandIsAction(uint id, const char *input); -void commandComplete(void); +void commandCompleteAdd(void); enum Heat { Cold, Warm, Hot }; extern struct Util uiNotifyUtil; @@ -236,10 +236,12 @@ enum Edit { EditTranspose, EditInsert, EditComplete, + EditExpand, EditEnter, }; void edit(uint id, enum Edit op, wchar_t ch); char *editBuffer(size_t *pos); +void editCompleteAdd(void); const char *complete(uint id, const char *prefix); void completeAccept(void); diff --git a/command.c b/command.c index 914e6cd..8782ee6 100644 --- a/command.c +++ b/command.c @@ -505,7 +505,7 @@ void command(uint id, char *input) { handler->fn(id, input); } -void commandComplete(void) { +void commandCompleteAdd(void) { for (size_t i = 0; i < ARRAY_LEN(Commands); ++i) { completeAdd(None, Commands[i].cmd, Default); } diff --git a/edit.c b/edit.c index 5aa3de4..d9839ea 100644 --- a/edit.c +++ b/edit.c @@ -72,6 +72,42 @@ static void delete(bool copy, size_t index, size_t count) { len -= count; } +static const struct { + const wchar_t *name; + const wchar_t *string; +} Macros[] = { + { L"\\flip", L"(╯°□°)╯︵ ┻━┻" }, + { L"\\gary", L"ᕕ( ᐛ )ᕗ" }, + { L"\\lenny", L"( ͡° ͜ʖ ͡°)" }, + { L"\\look", L"ಠ_ಠ" }, + { L"\\shrug", L"¯\\_(ツ)_/¯" }, +}; + +void editCompleteAdd(void) { + char mbs[256]; + for (size_t i = 0; i < ARRAY_LEN(Macros); ++i) { + size_t n = wcstombs(mbs, Macros[i].name, sizeof(mbs)); + assert(n != (size_t)-1); + completeAdd(None, mbs, Default); + } +} + +static void macroExpand(void) { + size_t macro = pos; + while (macro && !iswspace(buf[macro - 1])) macro--; + if (macro == pos) return; + for (size_t i = 0; i < ARRAY_LEN(Macros); ++i) { + if (wcsncmp(Macros[i].name, &buf[macro], pos - macro)) continue; + delete(false, macro, pos - macro); + pos = macro; + size_t expand = wcslen(Macros[i].string); + if (reserve(macro, expand)) { + wcsncpy(&buf[macro], Macros[i].string, expand); + pos += expand; + } + } +} + static struct { size_t pos; size_t pre; @@ -110,21 +146,24 @@ static void tabComplete(uint id) { } delete(false, tab.pos, tab.len); - if (wcs[0] != L'/' && !tab.pos) { - tab.len = n + 2; + tab.len = n; + if (wcs[0] == L'\\') { + reserve(tab.pos, tab.len); + } else if (wcs[0] != L'/' && !tab.pos) { + tab.len += 2; reserve(tab.pos, tab.len); buf[tab.pos + n + 0] = L':'; buf[tab.pos + n + 1] = L' '; } else if ( tab.pos >= 2 && (buf[tab.pos - 2] == L':' || buf[tab.pos - 2] == L',') ) { - tab.len = n + 2; + tab.len += 2; reserve(tab.pos, tab.len); buf[tab.pos - 2] = L','; buf[tab.pos + n + 0] = L':'; buf[tab.pos + n + 1] = L' '; } else { - tab.len = n + 1; + tab.len++; reserve(tab.pos, tab.len); buf[tab.pos + n] = L' '; } @@ -199,6 +238,11 @@ void edit(uint id, enum Edit op, wchar_t ch) { tabComplete(id); return; } + break; case EditExpand: { + macroExpand(); + tabAccept(); + return; + } break; case EditEnter: { tabAccept(); command(id, editBuffer(NULL)); diff --git a/ui.c b/ui.c index 31fe276..9c1b238 100644 --- a/ui.c +++ b/ui.c @@ -917,6 +917,7 @@ static void keyCtrl(wchar_t ch) { break; case L'U': edit(id, EditDeleteHead, 0); break; case L'V': windowScroll(window, -(PAGE_LINES - 2)); break; case L'W': edit(id, EditDeletePrevWord, 0); + break; case L'X': edit(id, EditExpand, 0); break; case L'Y': edit(id, EditPaste, 0); } } |