* Make Fn keys execute nth command in the tags buffers
* move by words is inconsistent. Example:
var infoId = 'readerinfo'+reader.id;
+* Add a way to CD using a builtin
+* diagnostic messages should steal focus.
+* Ctrl+Shift+N to set a mark, Ctrl+N to jump to a mark
The Future:
* implement command diffing logic to optimize the undo/redo log
* Status line should omit characters from beginning of path to make file path fit
+* Ctrl+Shift+g to jump to undo a goto line action
+* Shortcut to warp cursor to middle of current screen.
+* Find shortcut should select previous word if current char is newline
+* diagnostic messages can stack up if deselected and not resolved
+* highlight all matches of search term
+
# Auxillary Programs
* Visual diff tool
--- /dev/null
+/* extern the config variables */
+extern char *FontString, *DefaultTags;
+extern unsigned int ColorPalette[16];
+extern char *ShellCmd[], *SedCmd[], *PickFileCmd[], *PickTagCmd[], *OpenCmd[];
+
+/* OS-Specific Config
+ ******************************************************************************/
+#ifdef __MACH__
+#define FONT "Monaco:size=10:antialias=true:autohint=true"
+#define LNSPACE 0
+#else
+#define FONT "Liberation Mono:pixelsize=14:antialias=true:autohint=true"
+#define LNSPACE 2
+#endif
+
+/* General Config
+ ******************************************************************************/
+enum {
+ Width = 640, /* default window width */
+ Height = 480, /* default window height */
+ TabWidth = 4, /* maximum number of spaces used to represent a tab */
+ ScrollLines = 4, /* number of lines to scroll by for mouse wheel scrolling */
+ BufSize = 8192, /* default buffer size */
+ FontCacheSize = 16, /* Maximum number of fonts allowed in the font cache */
+ EventTimeout = 50, /* Maximum blocking wait time for events */
+ TrimOnSave = 1, /* Enable trimming of trailing whitespace on save */
+ DefaultCRLF = 0, /* Default to Unix line endings */
+ DefaultCharset = UTF_8, /* We assume UTF-8 because nothing else matters */
+ LineSpacing = LNSPACE, /* Set the vertical spacing between lines */
+ DblClickTime = 250, /* Millisecond time for detecting double clicks */
+ RulePosition = 80, /* Column in which the vertical ruler appears */
+};
+
+#ifdef INCLUDE_DEFS
+
+/* Default contents of the tags region */
+char* DefaultTags = "Quit Save Undo Redo Cut Copy Paste | Find ";
+
+/* Default font string */
+char* FontString = FONT;
+
+/* 16 color palette used for drawing */
+unsigned int ColorPalette[16] = {
+ 0xff002b36,
+ 0xff073642,
+ 0xff586e75,
+ 0xff657b83,
+ 0xff839496,
+ 0xff93a1a1,
+ 0xffeee8d5,
+ 0xfffdf6e3,
+ 0xffb58900,
+ 0xffcb4b16,
+ 0xffdc322f,
+ 0xffd33682,
+ 0xff6c71c4,
+ 0xff268bd2,
+ 0xff2aa198,
+ 0xff859900
+};
+
+/* The shell: Filled in with $SHELL. Used to execute commands */
+char* ShellCmd[] = { NULL, "-c", NULL, NULL };
+
+/* Sed command used to execute commands marked with ':' sigil */
+char* SedCmd[] = { "sed", "-e", NULL, NULL };
+
+/* Fuzzy Picker for files in the current directory and subdirectories */
+char* PickFileCmd[] = { "xfilepick", ".", NULL };
+
+/* Fuzzy picker for tags in a ctags database. */
+char* PickTagCmd[] = { "xtagpick", NULL, "tags", NULL, NULL };
+
+/* Open a new instance of the editor */
+char* OpenCmd[] = { "xedit", NULL, NULL };
+
+#undef INCLUDE_DEFS
+#endif
# OSX X11 Flags
INCS += -I/usr/X11/include \
- -I/usr/X11/include/freetype2
+ -I/usr/X11/include/freetype2 \
+ -I.
LIBS += -L/usr/X11/lib
# Linux Freetype2 Flags
CLR_GREEN = 15,
CLR_COUNT = 16
};
-
-/* Configuration
- *****************************************************************************/
-enum {
- Width = 640, /* default window width */
- Height = 480, /* default window height */
- TabWidth = 4, /* maximum number of spaces used to represent a tab */
- ScrollLines = 4, /* number of lines to scroll by for mouse wheel scrolling */
- BufSize = 8192, /* default buffer size */
- FontCacheSize = 16, /* Maximum number of fonts allowed in the font cache */
- EventTimeout = 100, /* Maximum blocking wait time for events */
- TrimOnSave = 1, /* Enable trimming of trailing whitespace on save */
-#ifdef __MACH__
- LineSpacing = 0, /* Number of pixels for spacing between lines */
-#else
- LineSpacing = 2, /* Number of pixels for spacing between lines */
-#endif
-};
-
-/* choose the font to use for xft */
-#ifdef __MACH__
-#define FONTNAME "Monaco:size=10:antialias=true:autohint=true"
-#else
-#define FONTNAME "Liberation Mono:pixelsize=14:antialias=true:autohint=true"
-#endif
-#define DEFAULT_COLORSCHEME DARK
-#define DEFAULT_CRLF 0
-#define DEFAULT_CHARSET UTF_8
-#define COLOR_PALETTE \
- { \
- 0xff002b36, \
- 0xff073642, \
- 0xff586e75, \
- 0xff657b83, \
- 0xff839496, \
- 0xff93a1a1, \
- 0xffeee8d5, \
- 0xfffdf6e3, \
- 0xffb58900, \
- 0xffcb4b16, \
- 0xffdc322f, \
- 0xffd33682, \
- 0xff6c71c4, \
- 0xff268bd2, \
- 0xff2aa198, \
- 0xff859900 \
- }
-#define DEFAULT_TAGS "Quit Save Undo Redo Cut Copy Paste | Find "
-
void (*set_focus)(bool focus);
void (*mouse_drag)(int state, int x, int y);
void (*mouse_btn)(int state, bool pressed, int x, int y);
- uint32_t palette[16];
} XConfig;
typedef void* XFont;
#include <edit.h>
#include <ctype.h>
#include <unistd.h>
+#include <config.h>
static void buf_resize(Buf* buf, size_t sz);
buf->modified = false;
buf->expand_tabs = true;
buf->copy_indent = true;
- buf->charset = DEFAULT_CHARSET;
- buf->crlf = DEFAULT_CRLF;
+ buf->charset = DefaultCharset;
+ buf->crlf = DefaultCRLF;
buf->bufsize = BufSize;
buf->bufstart = (Rune*)malloc(buf->bufsize * sizeof(Rune));
buf->bufend = buf->bufstart + buf->bufsize;
#include <stdc.h>
#include <utf.h>
#include <edit.h>
+#include <config.h>
#define __USE_XOPEN
#include <wchar.h>
#include <ctype.h>
#include <utf.h>
#include <edit.h>
#include <ctype.h>
+#include <config.h>
#define ATTR_NORMAL (CLR_BASE03 << 8 | CLR_BASE0)
#define ATTR_SELECTED (CLR_BASE0 << 8 | CLR_BASE03)
#include <x11.h>
#include <win.h>
#include <ctype.h>
+#include <config.h>
static void onredraw(int height, int width);
static void oninput(int mods, Rune key);
.set_focus = onfocus,
.mouse_drag = onmousedrag,
.mouse_btn = onmousebtn,
- .palette = COLOR_PALETTE
};
static WinRegion Focused = EDIT;
static Region Regions[NREGIONS] = {0};
for (int i = 0; i < SCROLL; i++)
view_init(&(Regions[i].view), NULL, errfn);
x11_init(&Config);
- Font = x11_font_load(FONTNAME);
+ Font = x11_font_load(FontString);
}
void win_window(char* name, void (*errfn)(char*)) {
#include <x11.h>
#include <utf.h>
#include <edit.h>
+#include <config.h>
#include <locale.h>
#include <sys/time.h>
#include <sys/types.h>
X.width,
X.height,
0, X.depth,
- Config->palette[0]);
+ ColorPalette[0]);
/* register interest in the delete window message */
Atom wmDeleteMessage = XInternAtom(X.display, "WM_DELETE_WINDOW", False);
void x11_draw_rect(int color, int x, int y, int width, int height) {
XftColor clr;
- xftcolor(&clr, Config->palette[color]);
+ xftcolor(&clr, ColorPalette[color]);
XftDrawRect(X.xft, &clr, x, y, width, height);
XftColorFree(X.display, X.visual, X.colormap, &clr);
}
XftTextExtentsUtf8(X.display, font, (const FcChar8*)"0", 1, &extent);
int w = extent.xOff;
int h = (font->height - font->descent) + LineSpacing;
- xftcolor(&bgc, Config->palette[bg]);
+ xftcolor(&bgc, ColorPalette[bg]);
size_t width = specs[nspecs-1].x - specs[0].x + w;
x11_draw_rect(bg, specs[0].x, specs[0].y - h, width, font->height + LineSpacing);
XftColorFree(X.display, X.visual, X.colormap, &bgc);
}
- xftcolor(&fgc, Config->palette[fg]);
+ xftcolor(&fgc, ColorPalette[fg]);
XftDrawGlyphFontSpec(X.xft, &fgc, (XftGlyphFontSpec*)specs, nspecs);
XftColorFree(X.display, X.visual, X.colormap, &fgc);
}
#include <ctype.h>
#include <win.h>
+#define INCLUDE_DEFS
+#include "config.h"
+
void onmouseleft(WinRegion id, bool pressed, size_t row, size_t col) {
}
CHECK(win_view(EDIT)->selection.beg == 0);
CHECK(win_view(EDIT)->selection.end == 3);
}
-
+
TEST(ctrl+h should nothing for empty buffer) {
setup_view(EDIT, "", CRLF, 0);
send_keys(ModCtrl, XK_h);
CHECK(win_sel(EDIT)->beg == 0);
CHECK(win_sel(EDIT)->end == 0);
}
-
+
TEST(ctrl+h should highlight content in parens from left paren) {
setup_view(EDIT, " (foo bar) ", CRLF, 1);
send_keys(ModCtrl, XK_h);
CHECK(win_sel(EDIT)->beg == 2);
CHECK(win_sel(EDIT)->end == 9);
}
-
+
TEST(ctrl+h should highlight content in parens from right paren) {
setup_view(EDIT, " (foo bar) ", CRLF, 9);
send_keys(ModCtrl, XK_h);
CHECK(win_sel(EDIT)->beg == 9);
CHECK(win_sel(EDIT)->end == 2);
}
-
+
TEST(ctrl+h should highlight content in parens from left bracket) {
setup_view(EDIT, " [foo bar] ", CRLF, 1);
send_keys(ModCtrl, XK_h);
CHECK(win_sel(EDIT)->beg == 2);
CHECK(win_sel(EDIT)->end == 9);
}
-
+
TEST(ctrl+h should highlight content in parens from right bracket) {
setup_view(EDIT, " [foo bar] ", CRLF, 9);
send_keys(ModCtrl, XK_h);
CHECK(win_sel(EDIT)->beg == 9);
CHECK(win_sel(EDIT)->end == 2);
}
-
+
TEST(ctrl+h should highlight content in parens from left brace) {
setup_view(EDIT, " {foo bar} ", CRLF, 1);
send_keys(ModCtrl, XK_h);
CHECK(win_sel(EDIT)->beg == 2);
CHECK(win_sel(EDIT)->end == 9);
}
-
+
TEST(ctrl+h should highlight content in parens from right brace) {
setup_view(EDIT, " {foo bar} ", CRLF, 9);
send_keys(ModCtrl, XK_h);
CHECK(win_sel(EDIT)->beg == 9);
CHECK(win_sel(EDIT)->end == 2);
}
-
+
TEST(ctrl+h should highlight whole line from bol) {
setup_view(EDIT, "foo bar\n", CRLF, 0);
send_keys(ModCtrl, XK_h);
CHECK(win_sel(EDIT)->beg == 0);
CHECK(win_sel(EDIT)->end == 8);
}
-
+
TEST(ctrl+h should highlight whole line from eol) {
setup_view(EDIT, "foo bar\n", CRLF, 7);
send_keys(ModCtrl, XK_h);
CHECK(win_sel(EDIT)->beg == 0);
CHECK(win_sel(EDIT)->end == 8);
}
-
+
TEST(ctrl+h should highlight word under cursor) {
setup_view(EDIT, " foo.bar \n", CRLF, 1);
send_keys(ModCtrl, XK_h);
CHECK(win_sel(EDIT)->beg == 1);
CHECK(win_sel(EDIT)->end == 4);
}
-
+
TEST(ctrl+h should highlight word under cursor) {
setup_view(EDIT, " foo.bar \n", CRLF, 4);
send_keys(ModCtrl, XK_h);
usleep(251 * 1000);
exec("Quit");
CHECK(ExitCode == 42);
- CHECK(verify_text(TAGS, "File is modified. Repeat action twice in < 250ms to quit."));
+ CHECK(verify_text(TAGS, "File is modified. Repeat action twice quickly to quit."));
}
TEST(Quit should discard changes if quit executed twice in less than 250 ms) {
EXPECT_EXIT {
exec("Quit");
CHECK(ExitCode == 42);
- CHECK(verify_text(TAGS, "File is modified. Repeat action twice in < 250ms to quit."));
+ CHECK(verify_text(TAGS, "File is modified. Repeat action twice quickly to quit."));
exec("Quit");
}
ExitExpected = false;
CHECK(ExitCode == 0);
- CHECK(verify_text(TAGS, "File is modified. Repeat action twice in < 250ms to quit."));
+ CHECK(verify_text(TAGS, "File is modified. Repeat action twice quickly to quit."));
}
TEST(Save should save changes to disk with crlf line endings) {
#include <win.h>
#include <shortcuts.h>
+#define INCLUDE_DEFS
+#include "config.h"
+
typedef struct {
char* tag;
union {
} action;
} Tag;
-/* The shell: Filled in with $SHELL. Used to execute commands */
-static char* ShellCmd[] = { NULL, "-c", NULL, NULL };
-static char* SedCmd[] = { "sed", "-e", NULL, NULL };
-static char* PickFileCmd[] = { "xfilepick", ".", NULL };
-static char* PickTagCmd[] = { "xtagpick", NULL, "tags", NULL, NULL };
-static char* OpenCmd[] = { "xedit", NULL, NULL };
static Tag Builtins[];
static int SearchDir = DOWN;
static char* SearchTerm = NULL;
static void quit(void) {
static uint64_t before = 0;
uint64_t now = getmillis();
- if (!win_buf(EDIT)->modified || (now-before) <= 250) {
+ if (!win_buf(EDIT)->modified || (now-before) <= DblClickTime) {
#ifndef TEST
x11_deinit();
#else
#endif
} else {
view_append(win_view(TAGS),
- "File is modified. Repeat action twice in < 250ms to quit.");
+ "File is modified. Repeat action twice quickly to quit.");
}
before = now;
}
static uint64_t before = 0;
if (!pressed) return;
uint64_t now = getmillis();
- count = ((now-before) <= 250 ? count+1 : 1);
+ count = ((now-before) <= DblClickTime ? count+1 : 1);
before = now;
if (count == 1) {
static void search(void) {
char* str;
- SearchDir *= (x11_keymodsset(ModShift) ? -1 : +1);
+ SearchDir *= (x11_keymodsset(ModShift) ? UP : DOWN);
if (x11_keymodsset(ModAlt) && SearchTerm)
str = stringdup(SearchTerm);
else
}
static void find(char* arg) {
- SearchDir *= (x11_keymodsset(ModShift) ? -1 : +1);
+ SearchDir *= (x11_keymodsset(ModShift) ? UP : DOWN);
view_findstr(win_view(EDIT), SearchDir, arg);
}
#ifndef TEST
int main(int argc, char** argv) {
/* setup the shell */
- ShellCmd[0] = getenv("SHELL");
+ if (!ShellCmd[0]) ShellCmd[0] = getenv("SHELL");
if (!ShellCmd[0]) ShellCmd[0] = "/bin/sh";
/* Create the window and enter the event loop */
win_window("edit", onerror);
char* tags = getenv("EDITTAGS");
- win_settext(TAGS, (tags ? tags : DEFAULT_TAGS));
- win_setruler(80);
+ win_settext(TAGS, (tags ? tags : DefaultTags));
+ win_setruler(RulePosition);
view_init(win_view(EDIT), (argc > 1 ? argv[1] : NULL), onerror);
win_setkeys(Bindings);
win_loop();
#include <ctype.h>
#include <shortcuts.h>
+#define INCLUDE_DEFS
+#include "config.h"
+
typedef struct {
float score;
char* string;