lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]



I noticed the fink Lua 5.0.2 doesn't have command line editing (readline-like) enabled. This is possibly due to license restrictions (readline being GPL), but there's a built-in 'editline' library in OS X that can be used instead.

I feel it would be nice even for the off-the-shelf Lua to support this library by default, I'll check if I can get the interfacing code (below) to be under MIT/X11.

-ak

//
// READLINE-DARWIN.C
//
// Readline compatibility, using OS X's built-in editline library.
//
// Adopted from code at:
//  http://www.opensource.apple.com/darwinsource/10.3/libedit-3/libedit/readline.c
//

/*-
 * Copyright (c) 1997 The NetBSD Foundation, Inc.
 * All rights reserved.
 *
 * This code is derived from software contributed to The NetBSD Foundation
 * by Jaromir Dolecek.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. All advertising materials mentioning features or use of this software
 *    must display the following acknowledgement:
 *	This product includes software developed by the NetBSD
 *	Foundation, Inc. and its contributors.
 * 4. Neither the name of The NetBSD Foundation nor the names of its
 *    contributors may be used to endorse or promote products derived
 *    from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */
    
#include <histedit.h>   // see 'man editline'
#include <termios.h>

static EditLine* el= NULL;
static History* h= NULL;
static const char* pr= NULL;    // prompt (allocated)
static int h_len= 0;

const char* f_prompt( EditLine* e ) { return pr; }

static void rl_initialize(void)
{
HistEvent ev;
int editmode = 1;
struct termios t;

    //
    // See if we don't really want to run the editor
    //
    if (tcgetattr(fileno(stdin), &t) != -1 && (t.c_lflag & ECHO) == 0)
            editmode= 0;

    el= el_init( "" /*procname*/, stdin, stdout, stderr );
    if (!editmode) el_set(el, EL_EDITMODE, 0);
    
    h= history_init();  ASSUME( h && el );
    history( h, &ev, H_SETSIZE, INT_MAX );	/* unlimited */
    h_len= 0;
    el_set( el, EL_HIST, history, h );

    // for proper prompt printing in readline()
    pr= strdup("");
    el_set( el, EL_PROMPT, f_prompt );
    el_set( el, EL_SIGNAL, 1 );

    // Set default mode to "emacs"-style and read setting afterwards
    // so this can be overriden
    //
    el_set( el, EL_EDITOR, "emacs" );

    // read settings from configuration file
    el_source( el, NULL );
}

char* readline( const char* prompt )
{
HistEvent ev;
int count;
const char* ret;
char* buf= NULL;

    if (el==NULL || h==NULL) rl_initialize();

    if (!prompt) prompt = "";
    if (strcmp(pr,prompt) != 0)
	   { free( (void*)pr ); pr= strdup(prompt); }

    ret= el_gets(el, &count);
	if (ret && count > 0)
	   {
        int lastidx;
		buf= strdup(ret);
		lastidx= count-1;
		if (buf[lastidx] == '\n')
		  buf[lastidx]= '\0';
       }

    history(h, &ev, H_GETSIZE);
	h_len= ev.num;
	return buf;
}

int add_history( const char* line )
{
HistEvent ev;

    ASSUME( h );
    (void) history( h, &ev, H_ENTER, line );
    if ( history( h, &ev, H_GETSIZE ) == 0 ) 
        h_len= ev.num;
    return !(h_len > 0);	    // 0 if all is okay
}