Add text macros

master
C. McEnroe 2020-03-30 14:56:26 -04:00
parent 407eaf9dbf
commit a0dde10cb6
6 changed files with 61 additions and 9 deletions

View File

@ -1,4 +1,4 @@
.Dd March 29, 2020 .Dd March 30, 2020
.Dt CATGIRL 1 .Dt CATGIRL 1
.Os .Os
. .
@ -392,6 +392,9 @@ Transpose characters.
Delete to beginning of line. Delete to beginning of line.
.It Ic C-w .It Ic C-w
Delete previous word. Delete previous word.
.It Ic C-x
Expand a text macro beginning with
.Ql \e .
.It Ic C-y .It Ic C-y
Paste previously deleted text. Paste previously deleted text.
.It Ic M-Enter .It Ic M-Enter
@ -403,7 +406,7 @@ Delete next word.
.It Ic M-f .It Ic M-f
Move to next word. Move to next word.
.It Ic Tab .It Ic Tab
Complete nick, channel or command. Complete nick, channel, command or macro.
.El .El
. .
.Ss Window Keys .Ss Window Keys

4
chat.c
View File

@ -201,7 +201,9 @@ int main(int argc, char *argv[]) {
set(&network.name, host); set(&network.name, host);
set(&self.nick, "*"); set(&self.nick, "*");
commandComplete();
editCompleteAdd();
commandCompleteAdd();
FILE *certFile = NULL; FILE *certFile = NULL;
FILE *privFile = NULL; FILE *privFile = NULL;

4
chat.h
View File

@ -198,7 +198,7 @@ void command(uint id, char *input);
const char *commandIsPrivmsg(uint id, const char *input); const char *commandIsPrivmsg(uint id, const char *input);
const char *commandIsNotice(uint id, const char *input); const char *commandIsNotice(uint id, const char *input);
const char *commandIsAction(uint id, const char *input); const char *commandIsAction(uint id, const char *input);
void commandComplete(void); void commandCompleteAdd(void);
enum Heat { Cold, Warm, Hot }; enum Heat { Cold, Warm, Hot };
extern struct Util uiNotifyUtil; extern struct Util uiNotifyUtil;
@ -236,10 +236,12 @@ enum Edit {
EditTranspose, EditTranspose,
EditInsert, EditInsert,
EditComplete, EditComplete,
EditExpand,
EditEnter, EditEnter,
}; };
void edit(uint id, enum Edit op, wchar_t ch); void edit(uint id, enum Edit op, wchar_t ch);
char *editBuffer(size_t *pos); char *editBuffer(size_t *pos);
void editCompleteAdd(void);
const char *complete(uint id, const char *prefix); const char *complete(uint id, const char *prefix);
void completeAccept(void); void completeAccept(void);

View File

@ -505,7 +505,7 @@ void command(uint id, char *input) {
handler->fn(id, input); handler->fn(id, input);
} }
void commandComplete(void) { void commandCompleteAdd(void) {
for (size_t i = 0; i < ARRAY_LEN(Commands); ++i) { for (size_t i = 0; i < ARRAY_LEN(Commands); ++i) {
completeAdd(None, Commands[i].cmd, Default); completeAdd(None, Commands[i].cmd, Default);
} }

52
edit.c
View File

@ -72,6 +72,42 @@ static void delete(bool copy, size_t index, size_t count) {
len -= 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 { static struct {
size_t pos; size_t pos;
size_t pre; size_t pre;
@ -110,21 +146,24 @@ static void tabComplete(uint id) {
} }
delete(false, tab.pos, tab.len); delete(false, tab.pos, tab.len);
if (wcs[0] != L'/' && !tab.pos) { tab.len = n;
tab.len = n + 2; if (wcs[0] == L'\\') {
reserve(tab.pos, tab.len);
} else if (wcs[0] != L'/' && !tab.pos) {
tab.len += 2;
reserve(tab.pos, tab.len); reserve(tab.pos, tab.len);
buf[tab.pos + n + 0] = L':'; buf[tab.pos + n + 0] = L':';
buf[tab.pos + n + 1] = L' '; buf[tab.pos + n + 1] = L' ';
} else if ( } else if (
tab.pos >= 2 && (buf[tab.pos - 2] == L':' || buf[tab.pos - 2] == L',') 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); reserve(tab.pos, tab.len);
buf[tab.pos - 2] = L','; buf[tab.pos - 2] = L',';
buf[tab.pos + n + 0] = L':'; buf[tab.pos + n + 0] = L':';
buf[tab.pos + n + 1] = L' '; buf[tab.pos + n + 1] = L' ';
} else { } else {
tab.len = n + 1; tab.len++;
reserve(tab.pos, tab.len); reserve(tab.pos, tab.len);
buf[tab.pos + n] = L' '; buf[tab.pos + n] = L' ';
} }
@ -199,6 +238,11 @@ void edit(uint id, enum Edit op, wchar_t ch) {
tabComplete(id); tabComplete(id);
return; return;
} }
break; case EditExpand: {
macroExpand();
tabAccept();
return;
}
break; case EditEnter: { break; case EditEnter: {
tabAccept(); tabAccept();
command(id, editBuffer(NULL)); command(id, editBuffer(NULL));

1
ui.c
View File

@ -917,6 +917,7 @@ static void keyCtrl(wchar_t ch) {
break; case L'U': edit(id, EditDeleteHead, 0); break; case L'U': edit(id, EditDeleteHead, 0);
break; case L'V': windowScroll(window, -(PAGE_LINES - 2)); break; case L'V': windowScroll(window, -(PAGE_LINES - 2));
break; case L'W': edit(id, EditDeletePrevWord, 0); break; case L'W': edit(id, EditDeletePrevWord, 0);
break; case L'X': edit(id, EditExpand, 0);
break; case L'Y': edit(id, EditPaste, 0); break; case L'Y': edit(id, EditPaste, 0);
} }
} }