]> git.lizzy.rs Git - metalua.git/blob - src/binlibs/editline.c
CRLF fsckup
[metalua.git] / src / binlibs / editline.c
1 #include <stdlib.h>
2 #include <stdio.h>
3 #include <histedit.h>
4 #include <lua.h>
5 #include <lauxlib.h>
6 #include <string.h>
7
8 #define MOD_NAME "editline"
9 #define DEFAULT_PROMPT "> "
10 #define DEFAULT_HIST_NAME "metalua"
11
12 struct el_userdata {
13   EditLine   *el;
14   History    *hist;
15   lua_State  *L;
16   char       *prompt;
17   HistEvent   hev;
18 };
19
20 /* static const lua_CFunction init, read, close, set; */
21 static int init( lua_State *L);
22 static int read( lua_State *L);
23 static int close( lua_State *L);
24 static int setf( lua_State *L);
25
26 static const struct luaL_Reg REG_TABLE[] = {
27   { "init",  init  },
28   { "read",  read  },
29   { "close", close },
30   { "__gc",  close },
31   { "__newindex", setf }, 
32   { NULL,    NULL  } };
33
34 int luaopen_editline( lua_State *L) {
35   /* Create the module. */
36   luaL_register( L, MOD_NAME, REG_TABLE);  
37
38   /* Set the module as editline's metatable */  
39   lua_pushvalue( L, -1);
40   lua_setfield( L, LUA_REGISTRYINDEX, MOD_NAME);
41
42   /* Set the table as its own __index metamethod */
43   lua_pushvalue( L, -1);
44   lua_setfield( L, -2, "__index");
45
46   /* printf( "Editline binary registered\n"); */
47
48   return 1;
49 }
50
51 static int setf( lua_State *L) {
52   struct el_userdata *u = luaL_checkudata( L, 1, MOD_NAME);
53   const  char *key     = luaL_checkstring( L, 2);
54   if( ! strcmp( key, "prompt")) {
55     const char *prompt = luaL_checkstring( L, 3);
56     realloc( u->prompt, strlen( prompt));
57     strcpy( u->prompt, prompt);
58   } else {   
59     luaL_error( L, "invalid field in editline");
60   }
61   return 0;
62 }  
63
64 static char *prompt( EditLine *el) {
65   /* Hack Hack Hack: the address of el_userdata is the same as
66    * its el field's. */
67   struct el_userdata *u;
68   el_get( el, EL_CLIENTDATA, &u);
69   return u->prompt;
70 }
71
72 #include <dlfcn.h>
73
74 static int init( lua_State *L) {
75   /* Allocate the structure and initialize its fields */
76   const char *name      = luaL_optstring( L, 1, DEFAULT_HIST_NAME);
77   struct el_userdata *u = lua_newuserdata( L, sizeof( *u));
78
79   u->el = el_init( name, stdin, stdout, stderr);
80   if( ! u->el) luaL_error( L, "can't create editline object");
81   u->hist = history_init();
82   if( ! u->hist) luaL_error( L, "can't create editline history");
83   u->L = L;
84   u->prompt = (char *) malloc( sizeof( DEFAULT_PROMPT));
85   strcpy( u->prompt, DEFAULT_PROMPT);
86
87   /* Set its metatable; if necessary, create the metatable. */
88   luaL_newmetatable( L, MOD_NAME);
89   lua_setmetatable( L, -2);
90
91   /* Some basic settings */
92   history( u->hist, & u->hev, H_SETSIZE, 800);
93   el_set( u->el, EL_PROMPT, & prompt);
94   el_set( u->el, EL_EDITOR, "emacs");
95   el_set( u->el, EL_HIST,   history, u->hist);
96   el_set( u->el, EL_CLIENTDATA, u);
97   return 1;
98 }
99
100 static int close( lua_State *L) {
101   struct el_userdata *u = luaL_checkudata( L, 1, MOD_NAME);
102   free( u->prompt);
103   history_end( u->hist);
104   el_end( u->el);
105   return 0;
106 }
107
108 static int read( lua_State *L) {
109   struct el_userdata *u = luaL_checkudata( L, 1, MOD_NAME);
110   const char *p = luaL_optstring( L, 2, NULL);
111   char *old_p = NULL;
112   int count;
113   const char *line;
114   if( p) { old_p = u->prompt; u->prompt = (char*) p; }
115   line = el_gets( u->el, & count);
116   if( p) { u->prompt = old_p; }
117   if( line) {
118     if (count > 0) history(u->hist, & u->hev, H_ENTER, line);
119     lua_pushlstring( L, line, count);
120   } else {
121     lua_pushnil( L);
122   }
123   return 1;
124 }
125