diff options
author | Karl Berry <karl@freefriends.org> | 2021-02-25 19:22:25 +0000 |
---|---|---|
committer | Karl Berry <karl@freefriends.org> | 2021-02-25 19:22:25 +0000 |
commit | ad547a6b5986815fda458221149728d9d9ab1d87 (patch) | |
tree | 16296910eb3eca724371474ea9aea3994dc69614 /Build/source/utils/asymptote/interact.cc | |
parent | 947b43de3dd21d58ccc2ffadefc4441ea1c2a813 (diff) |
restore Build,TODO from r57911
git-svn-id: svn://tug.org/texlive/trunk@57915 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Build/source/utils/asymptote/interact.cc')
-rw-r--r-- | Build/source/utils/asymptote/interact.cc | 252 |
1 files changed, 252 insertions, 0 deletions
diff --git a/Build/source/utils/asymptote/interact.cc b/Build/source/utils/asymptote/interact.cc new file mode 100644 index 00000000000..ad472942d5a --- /dev/null +++ b/Build/source/utils/asymptote/interact.cc @@ -0,0 +1,252 @@ +/***** + * interact.cc + * + * The glue between the lexical analyzer and the readline library. + *****/ + +#include <cstdlib> +#include <cassert> +#include <iostream> +#include <sstream> +#include <sys/wait.h> +#include <sys/types.h> +#include <unistd.h> +#include <csignal> +#include <cstdio> +#include <cstring> + +#include "interact.h" +#include "runhistory.h" + +#ifdef HAVE_LIBCURSES +#ifdef HAVE_LIBREADLINE +#include <readline/readline.h> +#include <readline/history.h> +#else +#ifdef HAVE_LIBEDIT +// Work around incorrect declaration in NetBSD readline.h v1.33 +#define rl_completion_entry_function rl_completion_entry_function_declaration +#ifdef HAVE_EDITLINE_READLINE_H +#include <editline/readline.h> +#else +#include <readline/readline.h> +#endif +#undef rl_completion_entry_function +extern "C" rl_compentry_func_t *rl_completion_entry_function; +#endif +#endif +#endif + +#include "util.h" +#include "errormsg.h" + +using namespace settings; + +namespace run { +void init_readline(bool); +} + +namespace interact { + +bool interactive=false; +bool uptodate=true; +int lines=0; +bool query=false; + +bool tty=isatty(STDIN_FILENO); +completer *currentCompleter=0; + +void setCompleter(completer *c) { + currentCompleter=c; +} + +char *call_completer(const char *text, int state) { + return currentCompleter ? (*currentCompleter)(text, state) : 0; +} + +#if defined(HAVE_READLINE) && defined(HAVE_LIBCURSES) +void init_completion() { + rl_completion_entry_function=call_completer; + + rl_completion_append_character='\0'; // Don't add a space after a match. + + /* + // Build a string containing all characters that separate words to be + // completed. All characters that can't form part of an identifier are + // treated as break characters. + static char break_characters[128]; + Int j=0; + for (unsigned char c=9; c < 128; ++c) + if (!isalnum(c) && c != '_') { + break_characters[j]=c; + ++j; + } + break_characters[j]='\0'; + rl_completer_word_break_characters=break_characters; + */ +} +#endif + +char *(*Readline)(const char *prompt); + +char *readverbatimline(const char *prompt) +{ + if(!cin.good()) {cin.clear(); return NULL;} + cout << prompt; + string s; + getline(cin,s); + return StrdupMalloc(s); +} + +FILE *fin=NULL; + +char *readpipeline(const char *prompt) +{ +#if _POSIX_VERSION >= 200809L + char *line=NULL; + size_t n=0; + return getline(&line,&n,fin) >= 0 ? line : NULL; +#else + const int max_size=256; + static char buf[max_size]; + ostringstream s; + do { + if(fgets(buf,max_size-1,fin) == NULL) break; + s << buf; + } while(buf[std::strlen(buf)-1] != '\n'); + return StrdupMalloc(s.str()); +#endif +} + +void pre_readline() +{ + int fd=intcast(settings::getSetting<Int>("inpipe")); + if(fd >= 0) { + if(!fin) fin=fdopen(fd,"r"); + Readline=readpipeline; + } else { +#if defined(HAVE_READLINE) && defined(HAVE_LIBCURSES) + if(tty) { + Readline=readline; + } else +#endif + Readline=readverbatimline; + } +} + +void init_readline(bool tabcompletion) +{ +#if defined(HAVE_READLINE) && defined(HAVE_LIBCURSES) + rl_bind_key('\t',tabcompletion ? rl_complete : rl_insert); +#endif +} + +void init_interactive() +{ + if(getSetting<bool>("xasy")) tty=false; +#if defined(HAVE_READLINE) && defined(HAVE_LIBCURSES) + if(tty) { + init_completion(); + interact::init_readline(getSetting<bool>("tabcompletion")); + read_history(historyname.c_str()); + } +#endif +} + +string simpleline(string prompt) { + // Rebind tab key, as the setting tabcompletion may be changed at runtime. + pre_readline(); + + Signal(SIGINT,SIG_IGN); + // Get a line from the user. + char *line=Readline(prompt.c_str()); + Signal(SIGINT,interruptHandler); + + // Reset scroll count. + interact::lines=0; + interact::query=tty; + + // Ignore keyboard interrupts while taking input. + errorstream::interrupt=false; + + if(line) { + string s=line; + free(line); + return s; + } else { + cout << endl; + if(!tty || getSetting<bool>("exitonEOF")) + throw eof(); + return "\n"; + } +} + +void addToHistory(string line) { +#if defined(HAVE_READLINE) && defined(HAVE_LIBCURSES) + // Only add it if it has something other than newlines. + if(tty && line.find_first_not_of('\n') != string::npos) { + add_history(line.c_str()); + } +#endif +} + +string getLastHistoryLine() { +#if defined(HAVE_LIBREADLINE) && defined(HAVE_LIBCURSES) + if(tty && history_length > 0) { + HIST_ENTRY *entry=history_list()[history_length-1]; + if(!entry) { + em.compiler(); + em << "cannot access last history line"; + return ""; + } else + return entry->line; + } else +#endif + return ""; +} + +void setLastHistoryLine(string line) { +#if defined(HAVE_READLINE) && defined(HAVE_LIBCURSES) + if(tty) { + if (history_length > 0) { + HIST_ENTRY *entry=remove_history(history_length-1); + + if(!entry) { + em.compiler(); + em << "cannot modify last history line"; + } else { + free((char *) entry->line); + free(entry); + } + } + addToHistory(line); + } +#endif +} + +void deleteLastLine() { +#if defined(HAVE_READLINE) && defined(HAVE_LIBCURSES) + if(tty) { + HIST_ENTRY *entry=remove_history(history_length-1); + if(!entry) { + em.compiler(); + em << "cannot delete last history line"; + } else { + free((char *) entry->line); + free(entry); + } + } +#endif +} + +void cleanup_interactive() { +#if defined(HAVE_READLINE) && defined(HAVE_LIBCURSES) + // Write the history file. + if(tty) { + stifle_history(intcast(getSetting<Int>("historylines"))); + write_history(historyname.c_str()); + } +#endif +} + +} // namespace interact |