summary refs log tree commit diff
diff options
context:
space:
mode:
authorJune McEnroe <june@causal.agency>2018-08-13 13:49:03 -0400
committerJune McEnroe <june@causal.agency>2018-08-13 13:49:03 -0400
commit2ae5b6b9ab2a528425c1c5265b04bb01a5246e29 (patch)
tree499faf3fd2401818005aed8c3af56206b224830b
parentFactor out input param and add tagFind (diff)
downloadcatgirl-2ae5b6b9ab2a528425c1c5265b04bb01a5246e29.tar.gz
catgirl-2ae5b6b9ab2a528425c1c5265b04bb01a5246e29.zip
Add /query, /part and /close
Closing a channel before parting it is a bit weird, but if I send a PART
on /close, it would get reopened again to show the part message.
-rw-r--r--chat.h1
-rw-r--r--handle.c5
-rw-r--r--input.c24
-rw-r--r--ui.c81
4 files changed, 88 insertions, 23 deletions
diff --git a/chat.h b/chat.h
index a4ab195..7e9f220 100644
--- a/chat.h
+++ b/chat.h
@@ -93,6 +93,7 @@ void uiDraw(void);
 void uiRead(void);
 void uiViewTag(struct Tag tag);
 void uiViewNum(int num);
+void uiCloseTag(struct Tag tag);
 void uiTopic(struct Tag tag, const char *topic);
 void uiLog(struct Tag tag, const wchar_t *line);
 void uiFmt(struct Tag tag, const wchar_t *format, ...);
diff --git a/handle.c b/handle.c
index 4d2d4b1..80ed1b4 100644
--- a/handle.c
+++ b/handle.c
@@ -122,12 +122,15 @@ static void handleJoin(char *prefix, char *params) {
 	char *nick, *user, *chan;
 	shift(prefix, &nick, &user, NULL, params, 1, 0, &chan);
 	struct Tag tag = tagFor(chan);
+	if (isSelf(nick, user)) {
+		tabTouch(TAG_NONE, chan);
+		uiViewTag(tag);
+	}
 	tabTouch(tag, nick);
 	uiFmt(
 		tag, "\3%d%s\3 arrives in \3%d%s\3",
 		color(user), nick, color(chan), chan
 	);
-	if (isSelf(nick, user)) uiViewTag(tag);
 }
 
 static void handlePart(char *prefix, char *params) {
diff --git a/input.c b/input.c
index 9f7eddf..2d9bc46 100644
--- a/input.c
+++ b/input.c
@@ -64,6 +64,21 @@ static void inputJoin(struct Tag tag, char *params) {
 	ircFmt("JOIN %s\r\n", chan);
 }
 
+static void inputPart(struct Tag tag, char *params) {
+	if (params) {
+		ircFmt("PART %s :%s\r\n", tag.name, params);
+	} else {
+		ircFmt("PART %s :Goodbye\r\n", tag.name);
+	}
+}
+
+static void inputQuery(struct Tag tag, char *params) {
+	(void)tag;
+	char *nick = param("/query", &params, "name");
+	tabTouch(TAG_NONE, nick);
+	uiViewTag(tagFor(nick));
+}
+
 static void inputWho(struct Tag tag, char *params) {
 	(void)params;
 	ircFmt("WHO %s\r\n", tag.name);
@@ -113,15 +128,24 @@ static void inputView(struct Tag tag, char *params) {
 	}
 }
 
+static void inputClose(struct Tag tag, char *params) {
+	(void)params;
+	uiCloseTag(tag);
+	tabRemove(TAG_NONE, tag.name);
+}
+
 static const struct {
 	const char *command;
 	Handler handler;
 } COMMANDS[] = {
+	{ "/close", inputClose },
 	{ "/join", inputJoin },
 	{ "/me", inputMe },
 	{ "/names", inputWho },
 	{ "/nick", inputNick },
 	{ "/open", inputOpen },
+	{ "/part", inputPart },
+	{ "/query", inputQuery },
 	{ "/quit", inputQuit },
 	{ "/topic", inputTopic },
 	{ "/url", inputUrl },
diff --git a/ui.c b/ui.c
index 559f7b7..6fcb75e 100644
--- a/ui.c
+++ b/ui.c
@@ -70,11 +70,7 @@ static short pair8(short pair) {
 	return (pair & 0x70) >> 1 | (pair & 0x07);
 }
 
-static const int LOG_LINES   = 256;
-static const int TOPIC_COLS  = 512;
-static const int INPUT_COLS  = 512;
-
-static struct View {
+struct View {
 	struct Tag tag;
 	WINDOW *topic;
 	WINDOW *log;
@@ -82,16 +78,35 @@ static struct View {
 	bool mark;
 	struct View *prev;
 	struct View *next;
-} *viewHead, *viewTail;
+};
+
+static struct {
+	struct View *head;
+	struct View *tail;
+	struct View *tags[TAGS_LEN];
+} views;
 
 static void viewAppend(struct View *view) {
-	if (viewTail) viewTail->next = view;
-	view->prev = viewTail;
+	if (views.tail) views.tail->next = view;
+	view->prev = views.tail;
 	view->next = NULL;
-	viewTail = view;
-	if (!viewHead) viewHead = view;
+	if (!views.head) views.head = view;
+	views.tail = view;
+	views.tags[view->tag.id] = view;
+}
+
+static void viewRemove(struct View *view) {
+	if (view->prev) view->prev->next = view->next;
+	if (view->next) view->next->prev = view->prev;
+	if (views.head == view) views.head = view->next;
+	if (views.tail == view) views.tail = view->prev;
+	views.tags[view->tag.id] = NULL;
 }
 
+static const int LOG_LINES   = 256;
+static const int TOPIC_COLS  = 512;
+static const int INPUT_COLS  = 512;
+
 static int logHeight(const struct View *view) {
 	return LINES - (view->topic ? 2 : 0) - 2;
 }
@@ -105,15 +120,8 @@ static int lastCol(void) {
 	return COLS - 1;
 }
 
-static struct {
-	bool hide;
-	WINDOW *input;
-	struct View *view;
-	struct View *tags[TAGS_LEN];
-} ui;
-
 static struct View *viewTag(struct Tag tag) {
-	struct View *view = ui.tags[tag.id];
+	struct View *view = views.tags[tag.id];
 	if (view) return view;
 
 	view = calloc(1, sizeof(*view));
@@ -127,10 +135,22 @@ static struct View *viewTag(struct Tag tag) {
 	view->scroll = LOG_LINES;
 
 	viewAppend(view);
-	ui.tags[tag.id] = view;
 	return view;
 }
 
+static void viewClose(struct View *view) {
+	viewRemove(view);
+	if (view->topic) delwin(view->topic);
+	delwin(view->log);
+	free(view);
+}
+
+static struct {
+	bool hide;
+	struct View *view;
+	WINDOW *input;
+} ui;
+
 void uiHide(void) {
 	ui.hide = true;
 	termMode(TERM_FOCUS, false);
@@ -170,7 +190,7 @@ void uiExit(void) {
 }
 
 static void uiResize(void) {
-	for (struct View *view = viewHead; view; view = view->next) {
+	for (struct View *view = views.head; view; view = view->next) {
 		wresize(view->log, LOG_LINES, COLS);
 		wmove(view->log, lastLogLine(), lastCol());
 	}
@@ -215,19 +235,36 @@ static void uiView(struct View *view) {
 	ui.view = view;
 }
 
+static void uiClose(struct View *view) {
+	if (ui.view == view) {
+		if (view->next) {
+			uiView(view->next);
+		} else if (view->prev) {
+			uiView(view->prev);
+		} else {
+			return;
+		}
+	}
+	viewClose(view);
+}
+
 void uiViewTag(struct Tag tag) {
 	uiView(viewTag(tag));
 }
 
+void uiCloseTag(struct Tag tag) {
+	uiClose(viewTag(tag));
+}
+
 void uiViewNum(int num) {
 	if (num < 0) {
-		for (struct View *view = viewTail; view; view = view->prev) {
+		for (struct View *view = views.tail; view; view = view->prev) {
 			if (++num) continue;
 			uiView(view);
 			break;
 		}
 	} else {
-		for (struct View *view = viewHead; view; view = view->next) {
+		for (struct View *view = views.head; view; view = view->next) {
 			if (num--) continue;
 			uiView(view);
 			break;
tests/t0001-validate-git-versions.sh?h=1.3.0&id=d483e8f5692117d6f3ea0801c0ca2ec7aa8f6f3b&follow=1'>t0001: ignore ".dirty" suffix on Git versionJohn Keeping When testing modifications in Git that affect CGit, it is annoying to have t0001 failing simply because the Git version has a ".dirty" suffix when the version of Git there does indeed match that specified in the CGit makefile. Stop this by stripping the ".dirty" suffix from the GIT_VERSION variable. Note that this brings the "Git version" behaviour in line with the "submodule version" case which does not check if the working tree in git/ is modified. Signed-off-by: John Keeping <john@keeping.me.uk> 2013-04-15tests: set TEST_OUTPUT_DIRECTORY to the CGit test directoryJohn Keeping By default, Git's test suite puts the trash directories and test-results directory into its own directory, not that containing the tests being run. This is less convenient for inspecting test failures, so set the output directory to CGit's tests/ directory instead. Note that there is currently a bug in Git whereby it will create the trash directories in our tests/ directory regardless of the value of TEST_OUTPUT_DIRECTORY, and then fail to remove them once the tests are done. This change does currently affect the location of the test-results/ directory though. Signed-off-by: John Keeping <john@keeping.me.uk> 2013-04-15t0109: test more URLsJohn Keeping In order to ensure that we don't access $HOME at some point after initial startup when rendering a specific view, run the strace test on a range of different pages. This ensures that we don't end up reading a configuration later for some specific view. Signed-off-by: John Keeping <john@keeping.me.uk> 2013-04-10cgitrc.5.txt: Specify when scan-path must be defined before.Jason A. Donenfeld Several options must be specified prior to scan-path. This is consistant source of user confusion. Document these facts. Suggested-by: Lukas Fleischer <cgit@cryptocrack.de> Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com> 2013-04-10ui-snapshot.c: Prepend "V" when guessing ref namesLukas Fleischer In cgit_print_snapshot_links() we strip leading "v" and "V", while we currently only prepend a lower case "v" when parsing a snapshot file name. This results in broken snapshot links for tags that start with an upper case "V". Avoid this by prepending a "V" as a fallback. Signed-off-by: Lukas Fleischer <cgit@cryptocrack.de> 2013-04-10t0107: Skip ZIP tests if unzip(1) isn't availableLukas Fleischer Note that we cannot use skip_all here since some tests have already been executed when ZIP tests are reached. Use test prerequisites to skip everything using unzip(1) if the binary is not available instead. Signed-off-by: Lukas Fleischer <cgit@cryptocrack.de> 2013-04-10tests/: Do not use `sed -i`Lukas Fleischer "-i" isn't part of the POSIX standard and doesn't work on several platforms such as OpenBSD. Use a temporary file instead. Signed-off-by: Lukas Fleischer <cgit@cryptocrack.de> 2013-04-10Add branch-sort and repo.branch-sort options.Jason A. Donenfeld When set to "name", branches are sorted by name, which is the current default. When set to "age", branches are sorted by the age of the repository. This feature was requested by Konstantin Ryabitsev for use on kernel.org. Proposed-by: Konstantin Ryabitsev <mricon@kernel.org> 2013-04-10t0109: chain operations with &&John Keeping Without '&&' between operations, we will not detect if strace or cgit exit with an error status, which would cause a false positive test status in this case. Signed-off-by: John Keeping <john@keeping.me.uk> 2013-04-10cgit.c: Do not restore unset environment variablesLukas Fleischer getenv() returns a NULL pointer if the specified variable name cannot be found in the environment. However, some setenv() implementations crash if a NULL pointer is passed as second argument. Only restore variables that are not NULL. See commit d96d2c98ebc4c2d3765f5b35c4142e0e828a421b for a related patch. Signed-off-by: Lukas Fleischer <cgit@cryptocrack.de> 2013-04-09t0107: Use `tar -z` for gzip'ed archivesLukas Fleischer