about summary refs log tree commit diff
diff options
context:
space:
mode:
authorJune McEnroe <june@causal.agency>2020-03-30 14:56:26 -0400
committerJune McEnroe <june@causal.agency>2020-03-30 14:56:26 -0400
commita0dde10cb61ec2c320103a215172841de636bd03 (patch)
tree182d9675f1ab3a0fff276f0d33c7b4246e463f13
parentTab complete from last iswspace (diff)
downloadcatgirl-a0dde10cb61ec2c320103a215172841de636bd03.tar.gz
catgirl-a0dde10cb61ec2c320103a215172841de636bd03.zip
Add text macros
-rw-r--r--catgirl.17
-rw-r--r--chat.c4
-rw-r--r--chat.h4
-rw-r--r--command.c2
-rw-r--r--edit.c52
-rw-r--r--ui.c1
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);
 	}
 }