Commit Diff


commit - beada781bf1465d95197dafcbb55f57c575ab1a8
commit + ba49fdf91d954e8173e65ade03d58ea09accd8ce
blob - eadce1c536e0178454f2f2be0e5487d97b32b0de
blob + f9700485e6e51e0685df1b85448c1dacebc0f557
--- Makefile.am
+++ Makefile.am
@@ -28,6 +28,7 @@ telescope_SOURCES =	cmd.c			\
 			parser.h		\
 			parser_gemtext.c	\
 			parser_gophermap.c	\
+			parser_textpatch.c	\
 			parser_textplain.c	\
 			sandbox.c		\
 			telescope.c		\
blob - ceb09e2d60e4c7ae711c1e9e31f46408a5b5b8ea
blob + facabdcd2d6b9773064bb8a33592917c2687471b
--- defaults.c
+++ defaults.c
@@ -49,6 +49,12 @@ struct lineprefix line_prefixes[] = {
 	[LINE_PRE_CONTENT] =	{ "",		"" },
 	[LINE_PRE_END] =	{ "─── ",	"" },
 
+	[LINE_PATCH] =		{"", ""},
+	[LINE_PATCH_HDR] =	{"", ""},
+	[LINE_PATCH_HUNK_HDR] =	{"", ""},
+	[LINE_PATCH_ADD] =	{"", ""},
+	[LINE_PATCH_DEL] =	{"", ""},
+
 	[LINE_COMPL] =		{"", ""},
 	[LINE_COMPL_CURRENT] =	{"", ""},
 
@@ -110,6 +116,33 @@ struct line_face line_faces[] = {
 		.prfx_pair = PPEND_PRFX,
 		.pair = PPEND,
 		.trail_pair = PPEND_TRAIL,
+	},
+
+	/* text/x-patch */
+	[LINE_PATCH] = {
+		.prfx_pair = PPATCH_PRFX,
+		.pair = PPATCH,
+		.trail_pair = PPATCH_TRAIL,
+	},
+	[LINE_PATCH_HDR] = {
+		.prfx_pair = PPATCH_HDR_PRFX,
+		.pair = PPATCH_HDR,
+		.trail_pair = PPATCH_HDR_TRAIL,
+	},
+	[LINE_PATCH_HUNK_HDR] = {
+		.prfx_pair = PPATCH_HUNK_HDR_PRFX,
+		.pair = PPATCH_HUNK_HDR,
+		.trail_pair = PPATCH_HUNK_HDR_TRAIL,
+	},
+	[LINE_PATCH_ADD] = {
+		.prfx_pair = PPATCH_ADD_PRFX,
+		.pair = PPATCH_ADD,
+		.trail_pair = PPATCH_ADD_TRAIL,
+	},
+	[LINE_PATCH_DEL] = {
+		.prfx_pair = PPATCH_DEL_PRFX,
+		.pair = PPATCH_DEL,
+		.trail_pair = PPATCH_DEL_TRAIL,
 	},
 
 	/* minibuffer */
@@ -181,6 +214,13 @@ struct mapping {
 	{"pre",		LINE_PRE_CONTENT},
 	{"pre.end",	LINE_PRE_END},
 
+	/* text/x-patch */
+	{"patch",	LINE_PATCH},
+	{"patch.hdr",	LINE_PATCH_HDR},
+	{"patch.hunk",	LINE_PATCH_HUNK_HDR},
+	{"patch.add",	LINE_PATCH_ADD},
+	{"patch.del",	LINE_PATCH_DEL},
+
 	/* minibuffer */
 	{"compl",	LINE_COMPL},
 	{"compl.current", LINE_COMPL_CURRENT},
@@ -401,6 +441,8 @@ config_init(void)
 	}
 
 	line_faces[LINE_LINK].fg = COLOR_BLUE;
+	line_faces[LINE_PATCH_ADD].fg = COLOR_GREEN;
+	line_faces[LINE_PATCH_DEL].fg = COLOR_RED;
 
 	load_default_keys();
 }
blob - cfccf093c420f93266dc00b5c0f63351515717d4
blob + 1b03366158021c761e241fa787e615c79353aecc
--- mime.c
+++ mime.c
@@ -30,6 +30,7 @@ static struct parser_table {
 	void		(*parserinit)(struct parser*);
 } ptable[] = {
 	{ "text/gemini",	gemtext_initparser },
+	{ "text/x-patch",	textpatch_initparser },
 	{ "text/*",		textplain_initparser },
 	{ NULL, NULL}
 };
blob - 3aae3f3c34946246c5fe41a78a95593868ae45c3
blob + d1ef5e24490de37385e3d9fdc808aa2a598d8925
--- parser.h
+++ parser.h
@@ -36,6 +36,9 @@ void	 gemtext_initparser(struct parser*);
 /* parser_gophermap.c */
 void	 gophermap_initparser(struct parser *);
 
+/* parser_textpatch.c */
+void	 textpatch_initparser(struct parser *);
+
 /* parser_textplain.c */
 void	 textplain_initparser(struct parser*);
 
blob - /dev/null
blob + c7f6f958e1e85fac47c776f16397c03e63a22d34 (mode 644)
--- /dev/null
+++ parser_textpatch.c
@@ -0,0 +1,108 @@
+/*
+ * Copyright (c) 2021 Omar Polo <op@omarpolo.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * A streaming text/x-patch parser
+ */
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "telescope.h"
+#include "parser.h"
+
+static int	tpatch_parse(struct parser *, const char *, size_t);
+static int	tpatch_emit_line(struct parser *, const char *, size_t);
+static int	tpatch_foreach_line(struct parser *, const char *, size_t);
+static int	tpatch_free(struct parser *);
+
+void
+textpatch_initparser(struct parser *p)
+{
+	memset(p, 0, sizeof(*p));
+
+	p->name = "text/x-patch";
+	p->parse = &tpatch_parse;
+	p->free = &tpatch_free;
+
+	p->flags = PARSER_IN_PATCH_HDR;
+}
+
+static int
+tpatch_parse(struct parser *p, const char *buf, size_t size)
+{
+	return parser_foreach_line(p, buf, size, tpatch_foreach_line);
+}
+
+static int
+tpatch_emit_line(struct parser *p, const char *line, size_t linelen)
+{
+	struct line *l;
+
+	if ((l = calloc(1, sizeof(*l))) == NULL)
+		return 0;
+
+	if (p->flags & PARSER_IN_PATCH_HDR)
+		l->type = LINE_PATCH_HDR;
+	else
+		l->type = LINE_PATCH;
+
+	if (linelen != 0) {
+		if ((l->line = calloc(1, linelen+1)) == NULL) {
+			free(l);
+			return 0;
+		}
+
+		memcpy(l->line, line, linelen);
+
+		if (!(p->flags & PARSER_IN_PATCH_HDR))
+			switch (*l->line) {
+			case '+':
+				l->type = LINE_PATCH_ADD;
+				break;
+			case '-':
+				l->type = LINE_PATCH_DEL;
+				break;
+			case '@':
+				l->type = LINE_PATCH_HUNK_HDR;
+				break;
+			}
+
+		if (has_prefix(l->line, "+++"))
+			p->flags &= ~PARSER_IN_PATCH_HDR;
+	}
+
+	if (TAILQ_EMPTY(&p->head))
+		TAILQ_INSERT_HEAD(&p->head, l, lines);
+	else
+		TAILQ_INSERT_TAIL(&p->head, l, lines);
+
+	return 1;
+}
+
+static int
+tpatch_foreach_line(struct parser *p, const char *line, size_t linelen)
+{
+	return tpatch_emit_line(p, line, linelen);
+}
+
+static int
+tpatch_free(struct parser *p)
+{
+	if (p->len != 0)
+		return tpatch_emit_line(p, p->buf, p->len);
+	return 1;
+}
blob - 7c4ee68d7d4edd32bfa32690932f387072b825f8
blob + 07270a94d9d7afeab8970f624bc10963e85c41d3
--- telescope.h
+++ telescope.h
@@ -79,6 +79,13 @@ enum line_type {
 	LINE_PRE_START,
 	LINE_PRE_CONTENT,
 	LINE_PRE_END,
+
+	/* text/x-patch */
+	LINE_PATCH,
+	LINE_PATCH_HDR,
+	LINE_PATCH_HUNK_HDR,
+	LINE_PATCH_ADD,
+	LINE_PATCH_DEL,
 
 	/* minibuffer */
 	LINE_COMPL,
@@ -127,6 +134,7 @@ struct parser {
 
 #define PARSER_IN_BODY	1
 #define PARSER_IN_PRE	2
+#define PARSER_IN_PATCH_HDR 4
 	int		 flags;
 	parsechunkfn	 parse;
 	parserfreefn	 free;
blob - 9e4beea54dee556d8373c629423cee16e377e2ea
blob + 7cd34f73c633cd97bf099d9d7e098a0aba749a82
--- ui.h
+++ ui.h
@@ -72,6 +72,22 @@ enum pairs {
 	PPEND_PRFX,
 	PPEND_TRAIL,
 
+	PPATCH,
+	PPATCH_PRFX,
+	PPATCH_TRAIL,
+	PPATCH_HDR,
+	PPATCH_HDR_PRFX,
+	PPATCH_HDR_TRAIL,
+	PPATCH_HUNK_HDR,
+	PPATCH_HUNK_HDR_PRFX,
+	PPATCH_HUNK_HDR_TRAIL,
+	PPATCH_ADD,
+	PPATCH_ADD_PRFX,
+	PPATCH_ADD_TRAIL,
+	PPATCH_DEL,
+	PPATCH_DEL_PRFX,
+	PPATCH_DEL_TRAIL,
+
 	PCOMPL_PRFX,
 	PCOMPL,
 	PCOMPL_TRAIL,
blob - 87393e3d4ab3e7bfe8fc9c291eea287064fbb55e
blob + 53ac51e380d2dd0753035cb4e7c0b2970f4cbf97
--- wrap.c
+++ wrap.c
@@ -272,6 +272,11 @@ wrap_page(struct buffer *buffer, int width)
 			wrap_text(buffer, prfx, l, MIN(fill_column, width));
 			break;
 		case LINE_PRE_CONTENT:
+		case LINE_PATCH:
+		case LINE_PATCH_HDR:
+		case LINE_PATCH_HUNK_HDR:
+		case LINE_PATCH_ADD:
+		case LINE_PATCH_DEL:
 			if (olivetti_mode)
 				pre_width = MIN(fill_column, width);
 			else