summaryrefslogtreecommitdiff
path: root/Build/source/utils/asymptote/runhistory.in
diff options
context:
space:
mode:
Diffstat (limited to 'Build/source/utils/asymptote/runhistory.in')
-rw-r--r--Build/source/utils/asymptote/runhistory.in232
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
+}