<commit_before>/* See LICENSE file for copyright and license details. */
#include <errno.h>
#include <fcntl.h>
#include <locale.h>
#include <ncurses.h>
#include <regex.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <sys/select.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/wait.h>

/* Defines */
#ifndef PIPESIZ /* This is POSIX magic */
#define PIPESIZ 4096
#endif /*PIPESIZ*/

#ifndef PATHSIZ /* Max path length */
#define PATHSIZ 1024
#endif /*PATHSIZ*/

#define LENGTH(x)     ((int)(sizeof (x) / sizeof *(x)))
#define LINSIZ        128
#define UTF8LEN(ch)     ((unsigned char)ch>=0xFC ? 6 : \
			((unsigned char)ch>=0xF8 ? 5 : \
			((unsigned char)ch>=0xF0 ? 4 : \
			((unsigned char)ch>=0xE0 ? 3 : \
			((unsigned char)ch>=0xC0 ? 2 : 1)))))
#define ISASCII(ch)   ((unsigned char)ch < 0x80)
#define ISCTRL(ch)    (((unsigned char)ch < 0x20) || (ch == 0x7F))
#define ISFILL(ch)    (isutf8 && !ISASCII(ch) && (unsigned char)ch<=0xBF)
#define ISBLANK(ch)   (ch == ' ' || ch == '\t' || ch == '\0')
#define ISWORDBRK(ch) (ISASCII(ch) && (ch < 0x30 || \
				      (ch > 0x39 && ch < 0x41) || \
				      (ch > 0x5A && ch < 0x5F) || \
				      ch == 0x60 || \
				      ch > 0x7A)) /* A bit flawed because we assume multibyte UTF8 chars are alnum */
#define VLEN(ch,col)  (ch==0x09 ? tabstop-(col%tabstop) : (ISCTRL(ch) ? 2: (ISFILL(ch) ? 0: 1)))
#define VLINES(l)     (1+(l?l->vlen/cols:0))
#define FIXNEXT(pos)  while(isutf8 && ISFILL(pos.l->c[pos.o]) && ++pos.o < pos.l->len)
#define FIXPREV(pos)  while(isutf8 && ISFILL(pos.l->c[pos.o]) && --pos.o > 0)
#define LINES2        (lines - (titlewin==NULL?0:1))

/* Typedefs */
typedef struct Line Line;
struct Line {        /** The internal representation of a line of text */
	char *c;     /* Line content */
	size_t len;  /* Line byte length */
	size_t vlen; /* On-screen line-length */
	size_t mul;  /* How many times LINSIZ is c malloc'd to */
	bool dirty;  /* Should I repaint on screen? */
	Line *next;  /* Next line, NULL if I'm last */
	Line *prev;  /* Previous line, NULL if I'm first */
};

typedef struct {  /** A position in the file */
	Line *l;  /* Line */
	size_t o; /* Offset inside the line */
} Filepos;

typedef union { /** An argument to a f_* function, generic */
	long i;
	const void *v;
	Filepos (*m)(Filepos);
} Arg;

typedef struct {                      /** A keybinding */
	union {
		char c[6];            /* Standard chars */
		int  i;               /* NCurses code */
	} keyv;
	bool (*test[4])(void);        /* Conditions to match, make sure the last one is 0x00 */
	void (*func)(const Arg *arg); /* Function to perform */
	const Arg arg;                /* Argument to func() */
} Key;

typedef struct {                      /** A mouse click */
	mmask_t mask;                 /* Mouse mask */
	bool place[2];                /* Place fcur / fsel at click place before testing */
	bool (*test[3])(void);        /* Conditions to match, make sure the last one is 0x00 */
	void (*func)(const Arg *arg); /* Function to perform */
	const Arg arg;                /* Argument to func() */
} Click;

typedef struct {                      /** A command read at the fifo */
	const char *re_text;          /* A regex to match the command, must have a parentheses group for argument */
	bool (*test[3])(void);        /* Conditions to match, make sure the last one is 0x00 */
	void (*func)(const Arg *arg); /* Function to perform, argument is determined as arg->v from regex above */
	const Arg arg;                /* Argument to func(), if empty will fill .v = re_match */
} Command;

#define SYN_COLORS 8
typedef struct {                      /** A syntax definition */
	char *name;                   /* Syntax name */
	char *file_re_text;           /* Apply to files matching this regex */
	char *re_text[SYN_COLORS];    /* Apply colors (in order) matching these regexes */
} Syntax;

typedef struct Undo Undo;
struct Undo {                       /** Undo information */
	char flags;                 /* Flags: is insert/delete?, should concatenate with next undo/redo? */
	unsigned long startl, endl; /* Line number for undo/redo start and end */
	size_t starto, endo;        /* Character offset for undo/redo start and end */
	char *str;                  /* Content (added or deleted text) */
	Undo *prev;                 /* Previous undo/redo in the ring */
};

/* ENUMS */
/* Colors */
enum { DefFG, CurFG, SelFG, SpcFG, CtrlFG, Syn0FG, Syn1FG, Syn2FG, Syn3FG, Syn4FG, Syn5FG, Syn6FG, Syn7FG, LastFG, };
enum { DefBG, CurBG, SelBG, /* WARNING: BGs MUST have a matching FG */     LastBG, };

/* arg->i to use in f_extsel() */
enum { ExtDefault, ExtWord, ExtLines, ExtAll, };

/* To use in lastaction */
enum { LastNone, LastDelete, LastInsert, LastPipe, LastPipeRO, };

/* Environment variables index */
enum { EnvFind, EnvPipe, EnvLine, EnvOffset, EnvFile, EnvSyntax, EnvFifo, EnvLast, };

enum { /* To use in statusflags */
	S_Running    = 1,
	S_Readonly   = 1<<1,
	S_InsEsc     = 1<<2,
	S_CaseIns    = 1<<3,
	S_Modified   = 1<<4,
	S_DirtyScr   = 1<<5,
	S_DirtyDown  = 1<<6,
	S_NeedResize = 1<<7,
	S_Warned     = 1<<8,
	S_GroupUndo  = 1<<9,
	S_AutoIndent = 1<<10,
};

enum { /* To use in Undo.flags */
	UndoIns  = 1,
	UndoMore = 1<<1,
	RedoMore = 1<<2,
};

/* Constants */
static const char *envs[EnvLast] = {
	[EnvFind]   = "SANDY_FIND",
	[EnvPipe]   = "SANDY_PIPE",
	[EnvLine]   = "SANDY_LINE",
	[EnvOffset] = "SANDY_OFFSET",
	[EnvFile]   = "SANDY_FILE",
	[EnvSyntax] = "SANDY_SYNTAX",
	[EnvFifo]   = "SANDY_FIFO",
};
<commit_msg>Some dull commenting<commit_after>/* See LICENSE file for copyright and license details. */
#include <errno.h>
#include <fcntl.h>
#include <locale.h>
#include <ncurses.h>
#include <regex.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <sys/select.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/wait.h>

/* Defines */
#ifndef PIPESIZ /* This is POSIX magic */
#define PIPESIZ 4096
#endif /*PIPESIZ*/

#ifndef PATHSIZ /* Max path length */
#define PATHSIZ 1024
#endif /*PATHSIZ*/

#define LENGTH(x)     ((int)(sizeof (x) / sizeof *(x)))
#define LINSIZ        128
#define UTF8LEN(ch)     ((unsigned char)ch>=0xFC ? 6 : \
			((unsigned char)ch>=0xF8 ? 5 : \
			((unsigned char)ch>=0xF0 ? 4 : \
			((unsigned char)ch>=0xE0 ? 3 : \
			((unsigned char)ch>=0xC0 ? 2 : 1)))))
#define ISASCII(ch)   ((unsigned char)ch < 0x80)
#define ISCTRL(ch)    (((unsigned char)ch < 0x20) || (ch == 0x7F))
#define ISFILL(ch)    (isutf8 && !ISASCII(ch) && (unsigned char)ch<=0xBF)
#define ISBLANK(ch)   (ch == ' ' || ch == '\t' || ch == '\0')
#define ISWORDBRK(ch) (ISASCII(ch) && (ch < 0x30 || \
				      (ch > 0x39 && ch < 0x41) || \
				      (ch > 0x5A && ch < 0x5F) || \
				      ch == 0x60 || \
				      ch > 0x7A)) /* A bit flawed because we assume multibyte UTF8 chars are alnum */
#define VLEN(ch,col)  (ch==0x09 ? tabstop-(col%tabstop) : (ISCTRL(ch) ? 2: (ISFILL(ch) ? 0: 1)))
#define VLINES(l)     (1+(l?l->vlen/cols:0))
#define FIXNEXT(pos)  while(isutf8 && ISFILL(pos.l->c[pos.o]) && ++pos.o < pos.l->len)
#define FIXPREV(pos)  while(isutf8 && ISFILL(pos.l->c[pos.o]) && --pos.o > 0)
#define LINES2        (lines - (titlewin==NULL?0:1))

/* Typedefs */
typedef struct Line Line;
struct Line {        /** The internal representation of a line of text */
	char *c;     /* Line content */
	size_t len;  /* Line byte length */
	size_t vlen; /* On-screen line-length */
	size_t mul;  /* How many times LINSIZ is c malloc'd to */
	bool dirty;  /* Should I repaint on screen? */
	Line *next;  /* Next line, NULL if I'm last */
	Line *prev;  /* Previous line, NULL if I'm first */
};

typedef struct {  /** A position in the file */
	Line *l;  /* Line */
	size_t o; /* Offset inside the line */
} Filepos;

typedef union { /** An argument to a f_* function, generic */
	long i;
	const void *v;
	Filepos (*m)(Filepos);
} Arg;

typedef struct {                      /** A keybinding */
	union {
		char c[6];            /* Standard chars */
		int  i;               /* NCurses code */
	} keyv;
	bool (*test[4])(void);        /* Conditions to match, make sure the last one is 0x00 */
	void (*func)(const Arg *arg); /* Function to perform */
	const Arg arg;                /* Argument to func() */
} Key;

typedef struct {                      /** A mouse click */
	mmask_t mask;                 /* Mouse mask */
	bool place[2];                /* Place fcur / fsel at click place before testing */
	bool (*test[3])(void);        /* Conditions to match, make sure the last one is 0x00 */
	void (*func)(const Arg *arg); /* Function to perform */
	const Arg arg;                /* Argument to func() */
} Click;

typedef struct {                      /** A command read at the fifo */
	const char *re_text;          /* A regex to match the command, must have a parentheses group for argument */
	bool (*test[3])(void);        /* Conditions to match, make sure the last one is 0x00 */
	void (*func)(const Arg *arg); /* Function to perform, argument is determined as arg->v from regex above */
	const Arg arg;                /* Argument to func(), if empty will fill .v = re_match */
} Command;

#define SYN_COLORS 8
typedef struct {                      /** A syntax definition */
	char *name;                   /* Syntax name */
	char *file_re_text;           /* Apply to files matching this regex */
	char *re_text[SYN_COLORS];    /* Apply colors (in order) matching these regexes */
} Syntax;

typedef struct Undo Undo;
struct Undo {                       /** Undo information */
	char flags;                 /* Flags: is insert/delete?, should concatenate with next undo/redo? */
	unsigned long startl, endl; /* Line number for undo/redo start and end */
	size_t starto, endo;        /* Character offset for undo/redo start and end */
	char *str;                  /* Content (added or deleted text) */
	Undo *prev;                 /* Previous undo/redo in the ring */
};

/* ENUMS */
/* Colors */
enum { DefFG, CurFG, SelFG, SpcFG, CtrlFG, Syn0FG, Syn1FG, Syn2FG, Syn3FG, Syn4FG, Syn5FG, Syn6FG, Syn7FG, LastFG, };
enum { DefBG, CurBG, SelBG, /* WARNING: BGs MUST have a matching FG */     LastBG, };

/* arg->i to use in f_extsel() */
enum { ExtDefault, ExtWord, ExtLines, ExtAll, };

/* To use in lastaction */
enum { LastNone, LastDelete, LastInsert, LastPipe, LastPipeRO, };

/* Environment variables index */
enum { EnvFind, EnvPipe, EnvLine, EnvOffset, EnvFile, EnvSyntax, EnvFifo, EnvLast, };

enum { /* To use in statusflags */
	S_Running    = 1,     /* Keep the editor running, flip to stop */
	S_Readonly   = 1<<1,  /* File is readonly, this should be enforced so that file is not modified */
	S_InsEsc     = 1<<2,  /* Insert next character as-is, even if it's a control sequence */
	S_CaseIns    = 1<<3,  /* Search is casi insensitive */
	S_Modified   = 1<<4,  /* File has been modified, set automatically */
	S_DirtyScr   = 1<<5,  /* Screen is dirty and should be repainted, set automatically */
	S_DirtyDown  = 1<<6,  /* Line has changed so that we must repaint from here down, set automatically */
	S_NeedResize = 1<<7,  /* Need to resize screen in next update, set automatically */
	S_Warned     = 1<<8,  /* Set to warn about file not being saved */
	S_GroupUndo  = 1<<9,  /* Last action was an insert, so another insert should group with it, set automatically */
	S_AutoIndent = 1<<10, /* Perform autoindenting on RET */
};

enum { /* To use in Undo.flags */
	UndoIns  = 1,    /* This undo is an insert (otherwise a delete) */
	UndoMore = 1<<1, /* This undo must be chained with the next one when redoing */
	RedoMore = 1<<2, /* This undo must be chained with the next one when undoing */
};

/* Constants */
static const char *envs[EnvLast] = {
	[EnvFind]   = "SANDY_FIND",
	[EnvPipe]   = "SANDY_PIPE",
	[EnvLine]   = "SANDY_LINE",
	[EnvOffset] = "SANDY_OFFSET",
	[EnvFile]   = "SANDY_FILE",
	[EnvSyntax] = "SANDY_SYNTAX",
	[EnvFifo]   = "SANDY_FIFO",
};

{'fraction_non_alphanumeric': 0.15437577768560762, 'fraction_numerical': 0.02007465781833264, 'mean_word_length': 2.6368024132730015, 'pattern_counts': {'":': 0, '<': 95, '<?xml version=': 0, '>': 63, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6084246', 'n_tokens_mistral': 4522, 'n_tokens_neox': 4185, 'n_words': 1357}