Previous Thread
Next Thread
Print Thread
Page 13 of 14 1 2 11 12 13 14
#111323 - 11/22/17 03:22 PM Re: 8bit Apples - Apple I, II, /// and the 16 bit GS [Re: crazyc]  
Joined: Feb 2014
Posts: 110
Golden Child Offline
Senior Member
Golden Child  Offline
Senior Member

Joined: Feb 2014
Posts: 110
Originally Posted by crazyc
There shouldn't be any issues enabling that.


Cool. That was one of the things that would crash when I'd experiment.

Now I just have to remember not to try to copy with CTRL+C in the mame console. kaboom! Old habits die hard.


Interestingly, if I type CTRL+V (for paste) I see a ^V in the console, but it takes two deletes to remove it.

If I only delete once after hitting CTRL+V I get this "unexpected symbol" and I could not figure out why my command didn't work.

type print("hello") then CTRL+V and then delete once, the command line looks ok, but there's a bizarro character at the end.

This is with Ubuntu terminal console.

Code
print("hello")
error: 	[string "print("hello")"]:1: unexpected symbol near '<\127>'




I can edit the plugins/console/init.lua and add this line:

Code
local ln = require("linenoise")
ln_global = ln


so I can access the linenoise as the global variable ln_global and then I can save the history as:

Code
ln_global.savehistory("mysavehistoryln.txt")


and loading that into a text editor I can see that there's a strange 007F character at the end.


Is there an easy way of accessing the actual linenoise history entries, like a "history" command in bash, for example?

If I type ln_global. and then hit TAB to complete I get:

Code
ln_global.                                  

addcompletion
clearscreen
sethistorymaxlen
linenoise
lines
historysave
line
preload
loadhistory
savehistory
setcompletion
addhistory
refresh
historyadd
historysetmaxlen
historyload



But none of those seem to give me access to the actual history.


edit:
Hmmm, why not savehistory to /dev/stdout, that seems to work.

Code
ln_global.savehistory("/dev/stdout")


Last edited by Golden Child; 11/22/17 03:55 PM.
#111324 - 11/22/17 03:56 PM Re: 8bit Apples - Apple I, II, /// and the 16 bit GS [Re: rfka01]  
Joined: Jan 2012
Posts: 711
crazyc Offline
Senior Member
crazyc  Offline
Senior Member

Joined: Jan 2012
Posts: 711
The linenoise function char **linenoiseHistory(int *len) provides access to the history but it's not passed to lua in to lua-linenoise. If you can add it that'd be great, it shouldn't be hard to do.

#111325 - 11/22/17 04:12 PM Re: 8bit Apples - Apple I, II, /// and the 16 bit GS [Re: crazyc]  
Joined: Feb 2014
Posts: 110
Golden Child Offline
Senior Member
Golden Child  Offline
Senior Member

Joined: Feb 2014
Posts: 110
Originally Posted by crazyc
The linenoise function char **linenoiseHistory(int *len) provides access to the history but it's not passed to lua in to lua-linenoise. If you can add it that'd be great, it shouldn't be hard to do.


sounds like an interesting idea, I'll give it a shot.

#111329 - 11/22/17 10:41 PM Re: 8bit Apples - Apple I, II, /// and the 16 bit GS [Re: Golden Child]  
Joined: Feb 2014
Posts: 110
Golden Child Offline
Senior Member
Golden Child  Offline
Senior Member

Joined: Feb 2014
Posts: 110

I took a stab at adding it to linenoise.c, this seems to work. Cool!

Code
static int l_gethistorytable(lua_State *L)
{
    int i,j;
    char ** phist;
    int lenhist = linenoiseHistoryGetMaxLen();

    phist = linenoiseHistory(&lenhist); 

    lua_newtable(L);
    i = 1;

    for (j=0; j<lenhist; j++){

        /* create result table */
        lua_pushnumber(L, i++);  /* push key */
        lua_pushstring(L, (char *)*(phist+j));  /* push value */
        lua_settable(L, -3);  /* adds key and value to table on top of stack */
      }
      return 1;  /* table is already on top */
}

luaL_Reg linenoise_funcs[] = {
    { "linenoise", l_linenoise },
    { "historyadd", l_historyadd },
    { "historysetmaxlen", l_historysetmaxlen },
    { "historysave", l_historysave },
    { "historyload", l_historyload },
    { "clearscreen", l_clearscreen },
    { "setcompletion", l_setcompletion},
    { "addcompletion", l_addcompletion },
    { "preload", l_preloadbuffer },
    { "refresh", l_refresh },

    /* Aliases for more consistent function names */
    { "addhistory", l_historyadd },
    { "sethistorymaxlen", l_historysetmaxlen },
    { "savehistory", l_historysave },
    { "loadhistory", l_historyload },

    { "line", l_linenoise },
    { "lines", l_lines },

    { "gethistory", l_gethistorytable},  // added function to gethistory
    { NULL, NULL }
};



I think you don't see the current command in the history list because it gets added after it gets executed.

Code
MAME debugger version 0.191 (mame0191-183-g346a935839-dirty)
Currently targeting a2600 (Atari 2600 (NTSC))
[MAME]> print(#ln_global.gethistory())
0
[MAME]> print(#ln_global.gethistory())
1
[MAME]> function printt(a) local i,j; for i,j in pairs(a) do print(i,j) end end

[MAME]> printt(ln_global.gethistory())
1	print(#ln_global.gethistory())
2	function printt(a) local i,j; for i,j in pairs(a) do print(i,j) end end

[MAME]> printt(ln_global.gethistory())
1	print(#ln_global.gethistory())
2	function printt(a) local i,j; for i,j in pairs(a) do print(i,j) end end
3	printt(ln_global.gethistory())
[MAME]> 

#111330 - 11/23/17 05:23 AM Re: 8bit Apples - Apple I, II, /// and the 16 bit GS [Re: Golden Child]  
Joined: Feb 2004
Posts: 1,874
Vas Crabb Offline
Very Senior Member
Vas Crabb  Offline
Very Senior Member

Joined: Feb 2004
Posts: 1,874
Sydney, Australia
Originally Posted by Golden Child
Interestingly, if I type CTRL+V (for paste) I see a ^V in the console, but it takes two deletes to remove it.

If I only delete once after hitting CTRL+V I get this "unexpected symbol" and I could not figure out why my command didn't work.

type print("hello") then CTRL+V and then delete once, the command line looks ok, but there's a bizarro character at the end.

This is with Ubuntu terminal console.

Code
print("hello")
error: 	[string "print("hello")"]:1: unexpected symbol near '<\127>'



Ctrl-V means "interpret the next character literally", so Ctrl-V Ctrl-C will type a literal ETX character rather than sending SIGINT, Ctrl-V Delete will type a literal DEL rather than deleting the previous character, etc.

#111333 - 11/23/17 08:21 AM Re: 8bit Apples - Apple I, II, /// and the 16 bit GS [Re: Vas Crabb]  
Joined: Feb 2014
Posts: 110
Golden Child Offline
Senior Member
Golden Child  Offline
Senior Member

Joined: Feb 2014
Posts: 110
Originally Posted by Vas Crabb

Ctrl-V means "interpret the next character literally", so Ctrl-V Ctrl-C will type a literal ETX character rather than sending SIGINT, Ctrl-V Delete will type a literal DEL rather than deleting the previous character, etc.


Ohhhh, now that makes perfect sense. That explains why if I'd type Ctrl+v Return that I'd get a ^M or Ctrl+v left arrow I'd get ESC [ D. So that's why I'd get an 007F character from Ctrl+V DEL.

I guess that's a keystroke from VIM.

And sure enough, the code in 3rdparty/linenoise/linenoise.c is pretty straightforward.

Code
    case ctrl('V'):    /* ctrl-v */
            if (has_room(current, 3)) {
                /* Insert the ^V first */
                if (insert_char(current, current->pos, c)) {
                    refreshLine(current->prompt, current);
                    /* Now wait for the next char. Can insert anything except \0 */
                    c = fd_read(current);

                    /* Remove the ^V first */
                    remove_char(current, current->pos - 1);
                    if (c != -1) {
                        /* Insert the actual char */
                        insert_char(current, current->pos, c);
                    }
                    refreshLine(current->prompt, current);
                }
            }

Last edited by Golden Child; 11/23/17 08:33 AM.
#111335 - 11/23/17 09:29 AM Re: 8bit Apples - Apple I, II, /// and the 16 bit GS [Re: Golden Child]  
Joined: Feb 2014
Posts: 110
Golden Child Offline
Senior Member
Golden Child  Offline
Senior Member

Joined: Feb 2014
Posts: 110
So while we're at it, why not do a historygetmaxlen too:

Code
static int l_gethistorytable(lua_State *L)
{
    int i,j;
    char ** phist;
    int lenhist = linenoiseHistoryGetMaxLen();

    phist = linenoiseHistory(&lenhist); 

    lua_newtable(L); /* put a table on the stack */
    i = 1;

    for (j=0; j<lenhist; j++){
        /* create result table */
        lua_pushnumber(L, i++);  /* push key */
        lua_pushstring(L, phist[j]);  /* push value */
        lua_settable(L, -3);  /* adds key and value to table at position 3 from top of stack */
      }
      return 1;  /* table is already on top */
}


static int l_historygetmaxlen(lua_State *L)
{
      lua_pushinteger(L, linenoiseHistoryGetMaxLen());  /* push max len on stack */
      return 1;  /* number of items on stack */
}

luaL_Reg linenoise_funcs[] = {
    { "linenoise", l_linenoise },
    { "historyadd", l_historyadd },
    { "historysetmaxlen", l_historysetmaxlen },
    { "historysave", l_historysave },
    { "historyload", l_historyload },
    { "clearscreen", l_clearscreen },
    { "setcompletion", l_setcompletion},
    { "addcompletion", l_addcompletion },
    { "preload", l_preloadbuffer },
    { "refresh", l_refresh },

    /* Aliases for more consistent function names */
    { "addhistory", l_historyadd },
    { "sethistorymaxlen", l_historysetmaxlen },
    { "savehistory", l_historysave },
    { "loadhistory", l_historyload },

    { "line", l_linenoise },
    { "lines", l_lines },

    { "gethistory", l_gethistorytable},
    { "historygetmaxlen", l_historygetmaxlen},
    { NULL, NULL }
};




Code
MAME debugger version 0.191 (mame0191-183-g346a935839-dirty)
Currently targeting a2600 (Atari 2600 (NTSC))
[MAME]> print(ln_global.historygetmaxlen())
100
[MAME]> print(ln_global.historysetmaxlen(250))
true
[MAME]> print(ln_global.historygetmaxlen())
250
[MAME]> function printt(a) local i,j; for i,j in pairs(a) do print(i,j) end end
[MAME]> printt(ln_global.gethistory())
1	print(ln_global.historygetmaxlen())
2	print(ln_global.historysetmaxlen(250))
3	print(ln_global.historygetmaxlen())
4	function printt(a) local i,j; for i,j in pairs(a) do print(i,j) end end
[MAME]> 

#111361 - 11/24/17 09:29 AM Re: 8bit Apples - Apple I, II, /// and the 16 bit GS [Re: Golden Child]  
Joined: Feb 2014
Posts: 110
Golden Child Offline
Senior Member
Golden Child  Offline
Senior Member

Joined: Feb 2014
Posts: 110
Ok, I thought I should clean the code up a little bit, and maybe add a couple of functions to return the history length ln.historylen() and to print the history ln.print() or ln.history().


3rdparty/lua-linenoise/linenoise.c
Code

static int l_gethistorytable(lua_State *L)
{
    int history_len;
    char ** history = linenoiseHistory(&history_len);

    lua_newtable(L); /* put a table on the stack */

    for (int i=0; i<history_len; i++){
        /* create result table */
        lua_pushnumber(L, i+1);  /* push key */
        lua_pushstring(L, history[i]);  /* push value */
        lua_settable(L, -3);  /* adds key and value to table at position 3 from top of stack */
      }
      return 1;  /* table is on top of stack */
}

static int l_historylen(lua_State *L)
{
     int history_len;
     char ** history = linenoiseHistory(&history_len);
     history = history;  // compiler warning about unused variable
     lua_pushinteger(L, history_len);
     return 1;
}

static int l_historygetmaxlen(lua_State *L)
{
      lua_pushinteger(L, linenoiseHistoryGetMaxLen());
      return 1;
}

static int l_historyprint(lua_State *L)
{
    int history_len;
    char ** history = linenoiseHistory(&history_len);

    printf("print history: %d entries\n",history_len);
    for (int i=0; i<history_len; i++){
       printf("%d %s\n",i+1,history[i]);
      }
    return handle_ln_ok(L);
}


luaL_Reg linenoise_funcs[] = {
    { "linenoise", l_linenoise },
    { "historyadd", l_historyadd },
    { "historysetmaxlen", l_historysetmaxlen },
    { "historysave", l_historysave },
    { "historyload", l_historyload },
    { "clearscreen", l_clearscreen },
    { "setcompletion", l_setcompletion},
    { "addcompletion", l_addcompletion },
    { "preload", l_preloadbuffer },
    { "refresh", l_refresh },

    /* Aliases for more consistent function names */
    { "addhistory", l_historyadd },
    { "sethistorymaxlen", l_historysetmaxlen },
    { "savehistory", l_historysave },
    { "loadhistory", l_historyload },

    { "line", l_linenoise },
    { "lines", l_lines },

    { "gethistorytable", l_gethistorytable},
    { "historygetmaxlen", l_historygetmaxlen},
    { "historylen", l_historylen},
    { "print", l_historyprint},
    { "history", l_historyprint},
    { NULL, NULL }
};


What's kind of interesting is that if you set the history to n, the maximum length is actually n-1.

So for ln.historysetmaxlen(5), the length of the history is actually a maximum of 4 entries.


And if you remove this line from plugins/console/init.lua it will default to a maximum length of 100.

Code
ln.historysetmaxlen(10)

since 3rdparty/linenoise/linenoise.c has this:
Code
#define LINENOISE_DEFAULT_HISTORY_MAX_LEN 100


And if you like to make ln a global variable ln for access you can do this in plugins/console/init.lua

Code
  
local ln = require("linenoise")
_G.ln = ln  -- make a global ln for console access

#111369 - 11/25/17 06:00 PM Re: 8bit Apples - Apple I, II, /// and the 16 bit GS [Re: Golden Child]  
Joined: Feb 2014
Posts: 110
Golden Child Offline
Senior Member
Golden Child  Offline
Senior Member

Joined: Feb 2014
Posts: 110
I was curious how the CTRL+C worked in linenoise and whether it could be "caught".


One interesting side effect of enabling SOL_CHECK_ARGUMENTS in luaengine.h is in whether sol will throw an exception when it executes this in luaengine.cpp:

Code
auto ret = func();

if (ret.valid()) {
	const char *tmp = ret.get<const char *>();
        if (tmp != nullptr)
			ctx.result = tmp;
		else
			exit(0);
	}



So when you type a CTRL+C on the console, it will return a nil from linenoise, tmp will be null so it calls exit(0);

When you've got SOL_CHECK_ARGUMENTS enabled, it will throw a sol::error exception immediately when it executes the following line

Code
const char *tmp = ret.get<const char *>();


It drops out and never sees the following if (tmp != nullptr) statement.

I had to put a bunch of printfs around to figure out exactly where it was blowing up.

And you get this kind of exit.

Code
[MAME]> 
terminate called after throwing an instance of 'sol::error'
  what():  lua: error: stack index 2, expected string, received nil
Aborted (core dumped)


So if we insert a little try catch block, we can catch that sol::error on the get.
Code
if (ret.valid()) {

    printf("calling ret.get const char *\n");

    try{
       const char *tmp = ret.get<const char *>();

	if (tmp != nullptr)
		ctx.result = tmp;
	else
		exit(0);
	
 catch (const std::exception& e) {  
     printf("Caught Exception:\n"); std::cout << e.what() << std::endl;
          }
}
	
		


With the catch it will catch the sol::error and keep you in the console. Of course, it's so convenient to just hit CTRL+C to drop out of mame, but there are other ways, like manager:machine():exit()


Code
[MAME]> 
calling ret.get const char *
Caught exception:
lua: error: stack index 2, expected string, received nil
[MAME]> 

#111370 - 11/25/17 06:54 PM Re: 8bit Apples - Apple I, II, /// and the 16 bit GS [Re: Golden Child]  
Joined: Feb 2014
Posts: 110
Golden Child Offline
Senior Member
Golden Child  Offline
Senior Member

Joined: Feb 2014
Posts: 110
Now that I've thought about for a bit, it's just getting a nil result from linenoise when you hit CTRL+C. The nil will cause the exception so why not look for that in plugins/console/init.lua:

The linenoise reading code:

Code
local scr = [[
local ln = require('linenoise')
ln.setcompletion(function(c, str, pos)
	status = str .. "\x01" .. tostring(pos)
	yield()
	ln.addcompletion(c, status:match("([^\x01]*)\x01(.*)"))
end)
return ln.linenoise('\x1b[1;36m[MAME]\x1b[0m> ')
]]



so instead of just returning the value from ln.linenoise, we'll check it for NIL and if so, convert it to the empty string.

Code
local scr = [[
local ln = require('linenoise')
ln.setcompletion(function(c, str, pos)
	status = str .. "\x01" .. tostring(pos)
	yield()
	ln.addcompletion(c, status:match("([^\x01]*)\x01(.*)"))
end)
local lnresult = ln.linenoise('\x1b[1;36m[MAME]\x1b[0m> ')
if lnresult == nil then print ("NIL result") lnresult = "" end
return lnresult
]]


Page 13 of 14 1 2 11 12 13 14

Who's Online Now
7 registered members (Pernod, box, ted, F1ReB4LL, Cpt. Pugwash, r09, 1 invisible), 19 guests, and 2 spiders.
Key: Admin, Global Mod, Mod
Shout Box
Forum Statistics
Forums9
Topics8,456
Posts109,747
Members4,768
Most Online225
May 26th, 2014
Powered by UBB.threads™ PHP Forum Software 7.6.0
Page Time: 0.040s Queries: 14 (0.009s) Memory: 5.0400 MB (Peak: 5.2862 MB) Zlib enabled. Server Time: 2017-12-15 21:22:53 UTC