about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorKartik K. Agaram <vc@akkartik.com>2021-12-06 16:53:11 -0800
committerKartik K. Agaram <vc@akkartik.com>2021-12-06 16:53:11 -0800
commita0c66dbe3112fbd9ff4716fc6c93b82a59c8e7f0 (patch)
tree9fe16e4f1e6200096b3729ba1a113c43aae66451
parent88071687292d9ad3766f3fa05f48777d97725b0c (diff)
downloadteliva-a0c66dbe3112fbd9ff4716fc6c93b82a59c8e7f0.tar.gz
more configurable colors
Also start using 256 colors, under the assumption most people will have
them.
-rw-r--r--hanoi.tlv3
-rw-r--r--life.tlv6
-rw-r--r--src/Makefile3
-rw-r--r--src/kilo.c20
-rw-r--r--src/lcurses/curses.c17
-rw-r--r--src/lua.c38
-rw-r--r--src/teliva.h86
7 files changed, 140 insertions, 33 deletions
diff --git a/hanoi.tlv b/hanoi.tlv
index 49ca232..a7a1e68 100644
--- a/hanoi.tlv
+++ b/hanoi.tlv
@@ -85,10 +85,11 @@ end]==],
 original]==],
     main = [==[
 function main()
+  curses.assume_default_colors(250, 30)
   for i=1,7 do
     curses.init_pair(i, 0, i)
   end
-  curses.init_pair(15, 0, 15)
+  curses.init_pair(15, 0, 250)  -- tower frames
   curses.init_pair(255, 15, 1)  -- reserved for Teliva error messages
 
   while true do
diff --git a/life.tlv b/life.tlv
index 4c948c7..ba4f1e7 100644
--- a/life.tlv
+++ b/life.tlv
@@ -116,11 +116,13 @@ original]==],
     render = [==[
 function render(window)
   window:clear()
+  curses.attron(curses.color_pair(1))
   for line=1,lines do
     for col=1,cols do
       window:addstr(utf8(glyph[grid_char_to_glyph_index(grid_char(line, col))]))
     end
   end
+  curses.attroff(curses.color_pair(1))
   curses.refresh()
 end
 ]==],
@@ -263,10 +265,8 @@ end]==],
 original]==],
     main = [==[
 function main()
-  for i=1,7 do
-    curses.init_pair(i, i, -1)
-  end
   curses.init_pair(255, 15, 1)  -- reserved for Teliva error messages
+  curses.init_pair(1, 22, 189)
 
   -- initialize grid based on commandline args
   if (#arg == 0) then
diff --git a/src/Makefile b/src/Makefile
index 720a35e..65580bb 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -172,7 +172,7 @@ ltable.o: ltable.c lua.h luaconf.h ldebug.h lstate.h lobject.h llimits.h \
 ltablib.o: ltablib.c lua.h luaconf.h lauxlib.h lualib.h
 ltm.o: ltm.c lua.h luaconf.h lobject.h llimits.h lstate.h ltm.h lzio.h \
   lmem.h lstring.h lgc.h ltable.h
-lua.o: lua.c lua.h luaconf.h lauxlib.h lualib.h
+lua.o: lua.c lua.h luaconf.h lauxlib.h lualib.h teliva.h
 lundump.o: lundump.c lua.h luaconf.h ldebug.h lstate.h lobject.h \
   llimits.h ltm.h lzio.h lmem.h ldo.h lfunc.h lstring.h lgc.h lundump.h
 lvm.o: lvm.c lua.h luaconf.h ldebug.h lstate.h lobject.h llimits.h ltm.h \
@@ -181,5 +181,6 @@ lzio.o: lzio.c lua.h luaconf.h llimits.h lmem.h lstate.h lobject.h ltm.h \
   lzio.h
 print.o: print.c ldebug.h lstate.h lua.h luaconf.h lobject.h llimits.h \
   ltm.h lzio.h lmem.h lopcodes.h lundump.h
+kilo.o: kilo.c teliva.h
 
 # (end of Makefile)
diff --git a/src/kilo.c b/src/kilo.c
index df7359a..a1a36e8 100644
--- a/src/kilo.c
+++ b/src/kilo.c
@@ -129,7 +129,7 @@ char *Lua_HL_keywords[] = {
     "and", "or", "not", "in",
 
     /* types */
-    "nil", "false", "true",
+    "nil|", "false|", "true|",
 
     NULL
 };
@@ -306,16 +306,16 @@ static void editorUpdateSyntax(erow *row) {
 }
 
 /* Maps syntax highlight token types to terminal colors. */
-static int editorSyntaxToColor(int hl) {
+static int editorSyntaxToColorPair(int hl) {
     switch(hl) {
     case HL_COMMENT:
-    case HL_MLCOMMENT: return 6;  /* cyan */
-    case HL_KEYWORD1: return 3;   /* yellow */
-    case HL_KEYWORD2: return 2;   /* green */
-    case HL_STRING: return 5;     /* magenta */
-    case HL_NUMBER: return 1;     /* red */
-    case HL_MATCH: return 4;      /* blue */
-    default: return 7;            /* white */
+    case HL_MLCOMMENT: return COLOR_PAIR_LUA_COMMENT;
+    case HL_KEYWORD1: return COLOR_PAIR_LUA_KEYWORD;
+    case HL_KEYWORD2: return COLOR_PAIR_LUA_CONSTANT;
+    case HL_STRING: return COLOR_PAIR_LUA_CONSTANT;
+    case HL_NUMBER: return COLOR_PAIR_LUA_CONSTANT;
+    case HL_MATCH: return COLOR_PAIR_MATCH;
+    default: return COLOR_PAIR_NORMAL;
     }
 }
 
@@ -760,7 +760,7 @@ static void editorRefreshScreen(void (*menu_func)(void)) {
                     }
                     addch(c[j]);
                 } else {
-                    int color = editorSyntaxToColor(hl[j]);
+                    int color = editorSyntaxToColorPair(hl[j]);
                     if (color != current_color) {
                         attrset(COLOR_PAIR(color));
                         current_color = color;
diff --git a/src/lcurses/curses.c b/src/lcurses/curses.c
index f6b425d..2c53022 100644
--- a/src/lcurses/curses.c
+++ b/src/lcurses/curses.c
@@ -367,6 +367,22 @@ Puse_default_colors(lua_State *L)
 
 
 /***
+Set -1 foreground and background colors.
+@function use_default_colors
+@treturn bool `true`, if successful
+@see use_default_colors(3x)
+@fixme ncurses only?
+*/
+static int
+Passume_default_colors(lua_State *L)
+{
+	int fg = checkint(L, 1);
+	int bg = checkint(L, 2);
+	return pushokresult(assume_default_colors(fg, bg));
+}
+
+
+/***
 Associate a color pair id with a specific foreground and background color.
 @function init_pair
 @int pair color pair id to act on
@@ -1289,6 +1305,7 @@ static const luaL_Reg curseslib[] =
 	LCURSES_FUNC( Punctrl		),
 	LCURSES_FUNC( Pungetch		),
 	LCURSES_FUNC( Puse_default_colors),
+	LCURSES_FUNC( Passume_default_colors),
 	{NULL, NULL}
 };
 
diff --git a/src/lua.c b/src/lua.c
index afceafd..9707712 100644
--- a/src/lua.c
+++ b/src/lua.c
@@ -27,10 +27,6 @@
 #include "lualib.h"
 
 
-#define BG(i) (COLOR_PAIR((i)+8))
-#define FG(i) (COLOR_PAIR(i))
-
-
 static lua_State *globalL = NULL;
 
 static const char *progname = LUA_PROGNAME;
@@ -503,7 +499,7 @@ static int render_wrapped_lua_text (int y, int xmin, int xmax, const char *text)
   for (int j = 0; j < strlen(text); ++j) {
     char c = text[j];
     if (c == '-' && j+1 < strlen(text) && text[j+1] == '-')
-      attron(FG(6));
+      attron(COLOR_PAIR(COLOR_PAIR_LUA_COMMENT));
     if (c != '\n') {
       addch(text[j]);
       ++x;
@@ -518,7 +514,7 @@ static int render_wrapped_lua_text (int y, int xmin, int xmax, const char *text)
       ++y;
       x = xmin;
       move(y, x);
-      attroff(FG(6));
+      attroff(COLOR_PAIR(COLOR_PAIR_LUA_COMMENT));
     }
   }
   return y;
@@ -553,16 +549,16 @@ void render_recent_changes (lua_State *L, int history_array, int start_index, in
       /* save timestamp of binding if available */
       lua_getfield(L, t, "__teliva_timestamp");
       if (!lua_isnil(L, -1)) {
-        attron(FG(7));
+        attron(COLOR_PAIR(COLOR_PAIR_FADE));
         printw("  %s", lua_tostring(L, -1));
-        attroff(FG(7));
+        attroff(COLOR_PAIR(COLOR_PAIR_FADE));
       }
       lua_pop(L, 1);
       lua_getfield(L, t, "__teliva_note");
       if (!lua_isnil(L, -1)) {
-        attron(FG(6));
+        attron(COLOR_PAIR(COLOR_PAIR_FADE));
         printw("  -- %s", lua_tostring(L, -1));
-        attroff(FG(6));
+        attroff(COLOR_PAIR(COLOR_PAIR_FADE));
       }
       lua_pop(L, 1);
       y++;
@@ -724,9 +720,11 @@ static int is_current_definition(lua_State *L, const char *definition_name, int
 
 
 void draw_definition_name (const char *definition_name) {
-  attron(BG(7));
+  attron(COLOR_PAIR(COLOR_PAIR_HIGHLIGHT));
+  addstr(" ");
   addstr(definition_name);
-  attroff(BG(7));
+  addstr(" ");
+  attroff(COLOR_PAIR(COLOR_PAIR_HIGHLIGHT));
   addstr("  ");
 }
 
@@ -928,11 +926,15 @@ char **Argv = NULL;
 extern void cleanup_curses (void);
 void developer_mode (lua_State *L) {
   /* clobber the app's ncurses colors; we'll restart the app when we rerun it. */
-  for (int i = 0; i < 8; ++i)
-    init_pair(i, i, 7);
-  for (int i = 0; i < 8; ++i)
-    init_pair(i+8, 0, i);
-  init_pair(255, /*white fg*/ 15, /*red bg*/ 1);  /* for teliva error messages */
+  assume_default_colors(COLOR_FOREGROUND, COLOR_BACKGROUND);
+  init_pair(COLOR_PAIR_NORMAL, COLOR_FOREGROUND, COLOR_BACKGROUND);
+  init_pair(COLOR_PAIR_HIGHLIGHT, COLOR_HIGHLIGHT_FOREGROUND, COLOR_HIGHLIGHT_BACKGROUND);
+  init_pair(COLOR_PAIR_FADE, COLOR_FADE, COLOR_BACKGROUND);
+  init_pair(COLOR_PAIR_LUA_COMMENT, COLOR_LUA_COMMENT, COLOR_BACKGROUND);
+  init_pair(COLOR_PAIR_LUA_KEYWORD, COLOR_LUA_KEYWORD, COLOR_BACKGROUND);
+  init_pair(COLOR_PAIR_LUA_CONSTANT, COLOR_LUA_CONSTANT, COLOR_BACKGROUND);
+  init_pair(COLOR_PAIR_MATCH, COLOR_MATCH_FOREGROUND, COLOR_MATCH_BACKGROUND);
+  init_pair(COLOR_PAIR_ERROR, COLOR_ERROR_FOREGROUND, COLOR_ERROR_BACKGROUND);
   nodelay(stdscr, 0);  /* make getch() block */
   int switch_to_big_picture_view = 1;
   if (editor_view_in_progress(L))
@@ -1034,7 +1036,7 @@ int main (int argc, char **argv) {
   initscr();
   keypad(stdscr, 1);
   start_color();
-  assume_default_colors(0, 7);
+  assume_default_colors(COLOR_FOREGROUND, COLOR_BACKGROUND);
   draw_menu(L);
   echo();
   s.argc = argc;
diff --git a/src/teliva.h b/src/teliva.h
index 772f17a..764a0b1 100644
--- a/src/teliva.h
+++ b/src/teliva.h
@@ -1,6 +1,8 @@
 #ifndef __TELIVA_H__
 #define __TELIVA_H__
 
+// Some names for hotkeys beyond those provided by ncurses.
+
 enum KEY_ACTION {
   KEY_NULL = 0,
   CTRL_A = 1,
@@ -25,4 +27,88 @@ enum KEY_ACTION {
   DELETE = 127,
 };
 
+
+// Colors (experimental)
+// Primary goal here: Keep text readable regardless of OS, terminal emulator
+// and color scheme. Unfortunately I don't yet have a good answer, so this
+// approach may yet change. Current approach:
+//  - Hardcode colors so that we can be sure we use legible combinations of
+//    foreground and background.
+//  - Use only the terminal palette in the range 16-255.
+//    - Not all terminals may support more than 256 colors. (I'm not yet sure
+//      everyone has even 256 colors. If you don't, please let me know:
+//      http://akkartik.name/contact)
+//    - Many terminals provide color schemes which give the ability to tweak
+//      colors 0-15. This makes it hard to assume specific combinations are
+//      legible. I'm hoping most terminal emulators don't tend to encourage
+//      messing with colors 16-255. (Please let me know if you know of
+//      counter-examples.)
+//
+// For now, you have to edit these values if you want to adjust colors in the
+// editing environment. Check out https://www.robmeerman.co.uk/unix/256colours
+// for a map of available colors.
+
+// Toggle between a few color schemes
+#define COLOR_SCHEME 0
+#if COLOR_SCHEME == 0
+// Light color scheme.
+enum color {
+  COLOR_FOREGROUND = 238,                     // almost black
+  COLOR_BACKGROUND = 253,                     // almost white
+  COLOR_FADE = 244,                           // closer to background
+  COLOR_HIGHLIGHT_FOREGROUND = 238,
+  COLOR_HIGHLIGHT_BACKGROUND = 250,
+  COLOR_ERROR_FOREGROUND = COLOR_BACKGROUND,
+  COLOR_ERROR_BACKGROUND = 124,               // deep red
+  COLOR_LUA_COMMENT = 27,                     // blue
+  COLOR_LUA_KEYWORD = 172,                    // orange
+  COLOR_LUA_CONSTANT = 31,                    // cyan
+  COLOR_MATCH_FOREGROUND = COLOR_BACKGROUND,
+  COLOR_MATCH_BACKGROUND = 28,                // green
+};
+#elif COLOR_SCHEME == 1
+// Dark color scheme.
+enum color {
+  COLOR_FOREGROUND = 253,                     // almost white
+  COLOR_BACKGROUND = 238,                     // almost black
+  COLOR_FADE = 244,                           // closer to background
+  COLOR_HIGHLIGHT_FOREGROUND = 238,
+  COLOR_HIGHLIGHT_BACKGROUND = 250,
+  COLOR_ERROR_FOREGROUND = COLOR_BACKGROUND,
+  COLOR_ERROR_BACKGROUND = 124,               // deep red
+  COLOR_LUA_COMMENT = 39,                     // blue
+  COLOR_LUA_KEYWORD = 172,                    // orange
+  COLOR_LUA_CONSTANT = 37,                    // cyan
+  COLOR_MATCH_FOREGROUND = COLOR_BACKGROUND,
+  COLOR_MATCH_BACKGROUND = 28,                // green
+};
+#elif COLOR_SCHEME == 2
+// Solarized dark.
+enum color {
+  COLOR_FOREGROUND = 250,                     // almost white
+  COLOR_BACKGROUND = 24,                      // dark blue-green
+  COLOR_FADE = 246,                           // closer to background
+  COLOR_HIGHLIGHT_FOREGROUND = 238,
+  COLOR_HIGHLIGHT_BACKGROUND = 31,
+  COLOR_ERROR_FOREGROUND = 250,
+  COLOR_ERROR_BACKGROUND = 124,               // deep red
+  COLOR_LUA_COMMENT = 45,                     // light blue
+  COLOR_LUA_KEYWORD = 172,                    // orange
+  COLOR_LUA_CONSTANT = 37,                    // cyan
+  COLOR_MATCH_FOREGROUND = COLOR_FOREGROUND,
+  COLOR_MATCH_BACKGROUND = 125,               // magenta
+};
+#endif
+
+enum color_pair {
+  COLOR_PAIR_NORMAL = 0,
+  COLOR_PAIR_HIGHLIGHT = 1,
+  COLOR_PAIR_FADE = 2,
+  COLOR_PAIR_LUA_COMMENT = 3,
+  COLOR_PAIR_LUA_KEYWORD = 4,
+  COLOR_PAIR_LUA_CONSTANT = 5,
+  COLOR_PAIR_MATCH = 6,
+  COLOR_PAIR_ERROR = 255,
+};
+
 #endif