diff options
Diffstat (limited to 'Build/source/utils/asymptote/runhistory.in')
-rw-r--r-- | Build/source/utils/asymptote/runhistory.in | 232 |
1 files changed, 232 insertions, 0 deletions
diff --git a/Build/source/utils/asymptote/runhistory.in b/Build/source/utils/asymptote/runhistory.in new file mode 100644 index 00000000000..69bbffcd069 --- /dev/null +++ b/Build/source/utils/asymptote/runhistory.in @@ -0,0 +1,232 @@ +/***** + * runhistory.in + * + * Runtime functions for history operations. + * + *****/ + +pair => primPair() +picture* => primPicture() +stringarray* => stringArray() + + +#include "array.h" +#include "mathop.h" + +using namespace camp; +using namespace settings; +using namespace vm; +using namespace run; + +typedef array stringarray; +using types::stringArray; + +#if defined(HAVE_LIBREADLINE) && defined(HAVE_LIBCURSES) +#include <readline/readline.h> +#include <readline/history.h> + +struct historyState { + bool store; + HISTORY_STATE state; +}; + +typedef mem::map<CONST string, historyState> historyMap_t; +historyMap_t historyMap; +static HISTORY_STATE history_save; + +// Store a deep copy of the current readline history in dest. +void store_history(HISTORY_STATE *dest) +{ + HISTORY_STATE *src=history_get_history_state(); + if(src) { + *dest=*src; + for(Int i=0; i < src->length; ++i) + dest->entries[i]=src->entries[i]; + free(src); + } +} + +stringarray* get_history(Int n) +{ + int N=intcast(n); + if(N <= 0) N=history_length; + else N=Min(N,history_length); + array *a=new array((size_t) N); + int offset=history_length-N+1; + for(int i=0; i < N; ++i) { + HIST_ENTRY *last=history_get(offset+i); + string s=last ? last->line : ""; + (*a)[i]=s; + } + return a; +} + +string historyfilename(const string &name) +{ + return historyname+"_"+name; +} +#endif + +namespace run { + +extern string emptystring; + +#if defined(HAVE_LIBREADLINE) && defined(HAVE_LIBCURSES) +int readline_startup_hook() +{ +#ifdef __CYGWIN__ + rl_set_key("\\M-[3~",rl_delete,rl_get_keymap()); + rl_set_key("\\M-[2~",rl_overwrite_mode,rl_get_keymap()); +#endif + return 0; +} + +void init_readline(bool tabcompletion) +{ + static bool first=true; + if(first) { + first=false; +#ifdef __CYGWIN__ + rl_startup_hook=readline_startup_hook; +#endif + } + rl_bind_key('\t',tabcompletion ? rl_complete : rl_insert); +} +#endif + +void cleanup() +{ +#if defined(HAVE_LIBREADLINE) && defined(HAVE_LIBCURSES) + store_history(&history_save); + int nlines=intcast(getSetting<Int>("historylines")); + for(historyMap_t::iterator h=historyMap.begin(); h != historyMap.end(); + ++h) { + history_set_history_state(&h->second.state); + stifle_history(nlines); + if(h->second.store) write_history(historyfilename(h->first).c_str()); + } + history_set_history_state(&history_save); +#endif +} +} + +// Autogenerated routines: + + +// Return the last n lines of the history named name. +stringarray* history(string name, Int n=1) +{ +#if defined(HAVE_LIBREADLINE) && defined(HAVE_LIBCURSES) + bool newhistory=historyMap.find(name) == historyMap.end(); + + string filename; + + if(newhistory) { + filename=historyfilename(name); + std::ifstream exists(filename.c_str()); + if(!exists) return new array(0); + } + + store_history(&history_save); + HISTORY_STATE& history=historyMap[name].state; + history_set_history_state(&history); + + if(newhistory) + read_history(filename.c_str()); + + array *a=get_history(n); + + store_history(&history); + history_set_history_state(&history_save); + + return a; +#else + unused(&n); + return new array(0); +#endif +} + +// Return the last n lines of the interactive history. +stringarray* history(Int n=0) +{ +#if defined(HAVE_LIBREADLINE) && defined(HAVE_LIBCURSES) + return get_history(n); +#else + unused(&n); + return new array(0); +#endif +} + +// Prompt for a string using prompt, the GNU readline library, and a +// local history named name. +string readline(string prompt=emptystring, string name=emptystring, + bool tabcompletion=false) +{ + if(!(isatty(STDIN_FILENO) || getSetting<bool>("interactive"))) + return emptystring; +#if defined(HAVE_LIBREADLINE) && defined(HAVE_LIBCURSES) + init_readline(tabcompletion); + + store_history(&history_save); + bool newhistory=historyMap.find(name) == historyMap.end(); + historyState& h=historyMap[name]; + HISTORY_STATE& history=h.state; + history_set_history_state(&history); + + if(newhistory) + read_history(historyfilename(name).c_str()); + + static char *line=NULL; + /* Return the memory to the free pool + if the buffer has already been allocated. */ + if(line) { + free(line); + line=NULL; + } + + /* Get a line from the user. */ + line=readline(prompt.c_str()); + + if(!line) cout << endl; + + history_set_history_state(&history_save); + + return line ? string(line) : emptystring; +#else + cout << prompt; + string s; + getline(cin,s); + unused(&tabcompletion); // Avoid unused variable warning message. + return s; +#endif +} + +// Save a string in a local history named name. +// If store=true, store the local history in the file historyfilename(name). +void saveline(string name, string value, bool store=true) +{ +#if defined(HAVE_LIBREADLINE) && defined(HAVE_LIBCURSES) + store_history(&history_save); + bool newhistory=historyMap.find(name) == historyMap.end(); + historyState& h=historyMap[name]; + h.store=store; + HISTORY_STATE& history=h.state; + history_set_history_state(&history); + + if(newhistory) + read_history(historyfilename(name).c_str()); + + if(value != "") { + add_history(value.c_str()); + if(store) { + std::ofstream hout(historyfilename(name).c_str(),std::ios::app); + hout << value << endl; + } + } + + store_history(&history); + history_set_history_state(&history_save); +#else + unused(&store); +#endif +} |