home *** CD-ROM | disk | FTP | other *** search
/ Big Green CD 8 / BGCD_8_Dev.iso / OPENSTEP / Languages / Python / python-14-src / Modules / pyrl.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-01-17  |  12.7 KB  |  602 lines

  1. /* Copyright (c) 1996 by Lele Gaifax.  All Rights Reserved
  2.  *
  3.  * This file is part of Nothing (yet).
  4.  *
  5.  * $RCSfile: pyrl.c,v $
  6.  * $Revision: 1.1.1.1 $
  7.  * $Date: 1997/01/18 03:52:15 $
  8.  *
  9.  * Created Tue Oct  1 12:04:57 1996.
  10.  */
  11.  
  12. /* Lele Gaifax <lele@nautilus.eclipse.it> on 28 September 1996:
  13.  
  14.    I added a completer function for the readline library, bound on
  15.    M-Tab (aka ESC-Tab). By doing a simple parse of the current line
  16.    it's able to expand names of builtins, locals, members, methods... */
  17.  
  18. #include "Python.h"
  19.  
  20. #ifdef WITH_READLINE
  21.  
  22. #include <stdio.h>
  23. #include <string.h>
  24. #include <errno.h>
  25.  
  26. #include "myproto.h"
  27. #include "mymalloc.h"
  28. #include "intrcheck.h"
  29.  
  30. #include <readline/readline.h>
  31. #include <readline/history.h>
  32. #include <setjmp.h>
  33. #include <signal.h>
  34.  
  35.  
  36. /* AIX requires this to be the first thing in the file.  */
  37. #ifdef __GNUC__
  38. #ifndef alloca            /* predefined by NeXT's header */
  39. # define alloca __builtin_alloca
  40. #endif
  41. #else
  42. # if HAVE_ALLOCA_H
  43. #  include <alloca.h>
  44. # else
  45. #  ifdef _AIX
  46. #pragma alloca
  47. #  else
  48. #   ifndef alloca /* predefined by HP cc +Olibcalls */
  49. char *alloca ();
  50. #   endif
  51. #  endif
  52. # endif
  53. #endif
  54.  
  55. static inline char *
  56. strdup (const char *s)
  57. {
  58.   char *dup = malloc (strlen (s) + 1);
  59.  
  60.  
  61.   return strcpy (dup, s);
  62. }
  63.  
  64. static jmp_buf jbuf;
  65.  
  66. /* ARGSUSED */
  67. static RETSIGTYPE
  68. onintr(sig)
  69.     int sig;
  70. {
  71.     longjmp(jbuf, sig);
  72. }
  73.  
  74. /* Appends to LIST the ``papabile'' symbols in DICT, that may actually
  75.    be a dictionary, a list, or an object responding to .keys().
  76.    Returns the number of added symbols, or 0 on errors. */
  77. static int
  78. append_papabile_symbols (PyObject *list,
  79.              PyObject *dict,
  80.              const char *text,
  81.              int len)
  82. {
  83.   PyObject *keys;
  84.   int count;
  85.  
  86.   if (PyDict_Check (dict))
  87.     {
  88.       keys = PyDict_Keys (dict);
  89.       if (!keys)
  90.     return 0;
  91.       
  92.       if (PyList_Sort (keys) != 0)
  93.     {
  94.       Py_DECREF (keys);
  95.       return 0;
  96.     }
  97.     }
  98.   else if (PyList_Check (dict))
  99.     {
  100.       keys = dict;
  101.       Py_INCREF (keys);
  102.     }
  103.   else
  104.     keys = PyObject_CallMethod (dict, "keys", NULL);
  105.  
  106.   count = 0;
  107.   if (keys)
  108.     {
  109.       unsigned int idx = PyList_Size (keys);
  110.       
  111.       while (idx--)
  112.     {
  113.       PyObject *localsym = PyList_GetItem (keys, idx);
  114.       
  115.       if (strncmp (text, PyString_AsString (localsym), len) == 0)
  116.         {
  117.           PyList_Append (list, localsym);
  118.           count++;
  119.         }
  120.     }
  121.  
  122.       Py_DECREF (keys);
  123.     }
  124.   else
  125.     PyErr_Clear();
  126.       
  127.   return count;
  128. }
  129.  
  130. /* If STATUS==0, collects the symbols from __main__.__dict__ and from
  131.    __builtins__.__dict__, then build a list of those beginning with
  132.    TEXT.
  133.    Returns the next symbol's name if there is one, NULL otherwise.
  134.    
  135.    This is called from the readline's completer function. */
  136. static char *
  137. try_complete_local_symbol (char *text, int state)
  138. {
  139.   static PyObject *symbols_list = NULL;
  140.   static int symbols_list_idx;
  141.   
  142.   if (!state)
  143.     {
  144.       PyObject *symbols;
  145.       int len;
  146.       
  147.       Py_XDECREF (symbols_list);
  148.       symbols_list = NULL;
  149.       symbols_list_idx = 0;
  150.  
  151.       symbols_list = PyList_New(0);
  152.       if (!symbols_list)
  153.     return NULL;
  154.  
  155.       len = strlen (text);
  156.       
  157.       symbols = PyObject_GetAttrString (PyImport_AddModule ("__main__"), "__dict__");
  158.       if (symbols)
  159.     {
  160.       symbols_list_idx += append_papabile_symbols (symbols_list,
  161.                                symbols,
  162.                                text,
  163.                                len);
  164.       Py_DECREF (symbols);
  165.     }
  166.       else
  167.     PyErr_Clear();
  168.  
  169.       symbols = PyObject_GetAttrString (PyEval_GetBuiltins(), "__dict__");
  170.       if (symbols)
  171.     {
  172.       symbols_list_idx += append_papabile_symbols (symbols_list,
  173.                                symbols,
  174.                                text,
  175.                                len);
  176.       Py_DECREF (symbols);
  177.     }
  178.       else
  179.     PyErr_Clear();
  180.     }
  181.  
  182.   if (symbols_list_idx > 0)
  183.     {
  184.       PyObject *localsym = PyList_GetItem (symbols_list, --symbols_list_idx);
  185.       
  186.       return strdup (PyString_AsString (localsym));
  187.     }
  188.  
  189.   return NULL;
  190. }
  191.  
  192. /* If STATUS==0, tries to understand from the entered TEXT the object
  193.    we are writing the name, and then collects in a list the name of the
  194.    symbols in both ``__dict__'' and ``__members__'' slots of it.
  195.  
  196.    Returns the next symbol's name if there is one, NULL otherwise.
  197.    
  198.    This is called from the readline's completer function. */
  199. static char *
  200. try_complete_member_symbol (char *text, int state)
  201. {
  202.   static PyObject *symbols_list = NULL;
  203.   static int symbols_list_idx;
  204.   static int prefix_len;
  205.   
  206.   if (!state)
  207.     {
  208.       int len;
  209.       PyObject *symbols = PyImport_AddModule ("__main__");
  210.       PyObject *list;
  211.       const char *point, *start;
  212.       
  213.       Py_XDECREF (symbols_list);
  214.       symbols_list = NULL;
  215.       symbols_list_idx = 0;
  216.  
  217.       symbols_list = PyList_New(0);
  218.       if (!symbols_list)
  219.     return NULL;
  220.  
  221.       /* PyImport_AddModule() does not return a new reference! */
  222.       Py_INCREF (symbols);
  223.       
  224.       start = text;
  225.       while ((point = strchr (start, '.')))
  226.     {
  227.       int symlen = point-start;
  228.       char *symname;
  229.  
  230.       if (!symlen)
  231.         return NULL;
  232.  
  233.       symname = alloca (symlen+1);
  234.       strncpy (symname, start, symlen);
  235.       symname[symlen] = '\0';
  236.  
  237.       /* This is safe: if this is the first time, we INCREFed the
  238.          module before the loop; if not, the previous GetAttrString()
  239.          returned a new reference to a surely-existing-somewhere object. */
  240.       Py_DECREF (symbols);
  241.       
  242.       symbols = PyObject_GetAttrString (symbols, symname);
  243.       if (!symbols)
  244.         {
  245.           PyErr_Clear();
  246.           return NULL;
  247.         }
  248.  
  249.       start = point+1;
  250.     }
  251.  
  252.       prefix_len = start-text;
  253.       len = strlen (start);
  254.  
  255.       list = PyObject_GetAttrString (symbols, "__dict__");
  256.       if (list)
  257.     {
  258.       symbols_list_idx += append_papabile_symbols (symbols_list,
  259.                                list,
  260.                                start,
  261.                                len);
  262.       Py_DECREF (list);
  263.     }
  264.       else
  265.     PyErr_Clear();
  266.  
  267.       list = PyObject_GetAttrString (symbols, "__members__");
  268.       if (list)
  269.     {
  270.       symbols_list_idx += append_papabile_symbols (symbols_list,
  271.                                list,
  272.                                start,
  273.                                len);
  274.       Py_DECREF (list);
  275.     }
  276.       else
  277.     PyErr_Clear();
  278.  
  279.       list = PyObject_GetAttrString (symbols, "__methods__");
  280.       if (list)
  281.     {
  282.       symbols_list_idx += append_papabile_symbols (symbols_list,
  283.                                list,
  284.                                start,
  285.                                len);
  286.       Py_DECREF (list);
  287.     }
  288.       else
  289.     PyErr_Clear();
  290.     }
  291.  
  292.   if (symbols_list_idx > 0)
  293.     {
  294.       PyObject *localsym = PyList_GetItem (symbols_list, --symbols_list_idx);
  295.       extern char *strdup (const char *);
  296.       const char *ls = PyString_AsString (localsym);
  297.       char *complete;
  298.  
  299.       complete = alloca (prefix_len + PyString_Size (localsym) + 1);
  300.       strncpy (complete, text, prefix_len);
  301.       strcpy (complete+prefix_len, ls);
  302.       return strdup (complete);
  303.     }
  304.  
  305.   return NULL;
  306. }
  307.  
  308. static inline char **
  309. builtin_completion (char *text, int start, int end)
  310. {
  311.   if (end > start && strchr (text, '.'))
  312.     return completion_matches (text, try_complete_member_symbol);
  313.   else
  314.     return completion_matches (text, try_complete_local_symbol);
  315. }
  316.  
  317. static PyObject *python_completion_in_python;
  318.  
  319. /* If the current TEXT contains a point '.', assume we are accessing a
  320.    member of an object and attempt to complete that; otherwise try to
  321.    complete a local symbol. */
  322. static char **
  323. python_completion (char *text, int start, int end)
  324. {
  325.   /* Do not perform standard filename completion, even if we can't complete
  326.      the symbol. */
  327.   rl_attempted_completion_over = 1;
  328.  
  329.   if (python_completion_in_python)
  330.     {
  331.       PyTupleObject *args;
  332.       PyObject *result;
  333.       
  334.       args = (PyTupleObject *) PyTuple_New (3);
  335.       if (!args)
  336.     return NULL;
  337.  
  338.       PyTuple_SET_ITEM (args, 0, PyString_FromString (text));
  339.       PyTuple_SET_ITEM (args, 1, PyInt_FromLong (start));
  340.       PyTuple_SET_ITEM (args, 2, PyInt_FromLong (end));
  341.  
  342.       result = PyEval_CallObject (python_completion_in_python, (PyObject *) args);
  343.  
  344.       Py_DECREF (args);
  345.  
  346.       if (result && PyList_Check (result))
  347.     {
  348.       int midx = PyList_Size (result);
  349.       char **matches = malloc ((midx+1) * sizeof (char *));
  350.       
  351.       if (!matches)
  352.         {
  353.           PyErr_NoMemory();
  354.           return NULL;
  355.         }
  356.  
  357.       matches[midx] = NULL;
  358.       while (midx--)
  359.         matches[midx] = strdup (PyString_AsString (PyList_GetItem (result, midx)));
  360.  
  361.       Py_DECREF (result);
  362.  
  363.       return matches;
  364.     }
  365.       else
  366.     {
  367.       if (! result)
  368.         {
  369.           PyErr_Print();
  370.  
  371.           Py_DECREF (python_completion_in_python);
  372.           python_completion_in_python = NULL;
  373.         }
  374.       else
  375.         Py_DECREF (result);
  376.       return NULL;
  377.     }
  378.     }
  379.   else
  380.     return builtin_completion (text, start, end);
  381. }
  382.  
  383. static char *
  384. py_readline (prompt)
  385.     char *prompt;
  386. {
  387.   int n;
  388.   char *p;
  389.   RETSIGTYPE (*old_inthandler)();
  390.   int sig;
  391.   
  392. #ifdef NeXT
  393.   RETSIGTYPE (*old_conthandler)();
  394.  
  395. sigcont_received:
  396.   old_conthandler = signal (SIGCONT, onintr);
  397. #endif
  398.   old_inthandler = signal (SIGINT, onintr);
  399.   if ((sig = setjmp (jbuf)))
  400.     {
  401. #ifdef HAVE_SIGRELSE
  402.       /* This seems necessary on SunOS 4.1 (Rasmus Hahn) */
  403.       sigrelse(SIGINT);
  404. #endif
  405.       signal(SIGINT, old_inthandler);
  406. #ifdef NeXT
  407.       signal (SIGCONT, old_conthandler);
  408.       if (sig == SIGCONT)
  409.     goto sigcont_received;
  410. #endif
  411.       return NULL;
  412.     }
  413.   
  414.   p = readline (prompt);
  415.   signal (SIGINT, old_inthandler);
  416. #ifdef NeXT
  417.   signal (SIGCONT, old_conthandler);
  418. #endif
  419.   
  420.   if (p == NULL)
  421.     {
  422.       p = malloc(1);
  423.       if (p != NULL)
  424.     *p = '\0';
  425.       return p;
  426.     }
  427.   n = strlen (p);
  428.   if (n > 0)
  429.     add_history (p);
  430.   if ((p = realloc (p, n+2)) != NULL)
  431.     {
  432.       p[n] = '\n';
  433.       p[n+1] = '\0';
  434.     }
  435.   return p;
  436. }
  437.  
  438. static char pyrl_set_completer_doc[] =
  439. "Set a new completer function. The COMPLETER argument must be a callable\n\
  440. object, and will be called with three arguments: the TEXT entered so far,\n\
  441. START and END show the region of TEXT that contains the word to complete.\n\
  442. Returns the previous completer object, or None if it was the builtin one.";
  443.  
  444. static PyObject *
  445. pyrl_set_completer (PyObject *self, PyObject *args)
  446. {
  447.   PyObject *new;
  448.   
  449.   if (PyArg_ParseTuple (args, "O;completer", &new))
  450.     {
  451.       if (new == Py_None || PyCallable_Check (new))
  452.     {
  453.       PyObject *old = python_completion_in_python;
  454.  
  455.       if (new != Py_None)
  456.         {
  457.           python_completion_in_python = new;
  458.           Py_INCREF (python_completion_in_python);
  459.         }
  460.       else
  461.         python_completion_in_python = NULL;
  462.       
  463.       if (!old)
  464.         {
  465.           old = Py_None;
  466.           Py_INCREF (old);
  467.         }
  468.       
  469.       return old;
  470.     }
  471.       else
  472.     PyErr_BadArgument();
  473.     }
  474.  
  475.   return NULL;
  476. }
  477.  
  478. static char pyrl_readline_doc[] =
  479. "Read a line of input from the user with the GNU readline facility. If the\n\
  480. optional PROMPT is not given, sys.ps1 is used instead.";
  481.  
  482. static PyObject *
  483. pyrl_readline (PyObject *self, PyObject *args)
  484. {
  485.   char *prompt = NULL;
  486.  
  487.   if (PyArg_ParseTuple (args, "|s;prompt", &prompt))
  488.     {
  489.       char *line;
  490.       
  491.       if (prompt == NULL)
  492.     {
  493.       PyObject *ps1 = PySys_GetObject ("ps1");
  494.  
  495.       prompt = PyString_AsString (ps1);
  496.     }
  497.  
  498.       line = py_readline (prompt);
  499.       if (line)
  500.     {
  501.       PyObject *ret = PyString_FromString (line);
  502.  
  503.       free (line);
  504.       return ret;
  505.     }
  506.       else
  507.     {
  508.       PyErr_NoMemory();
  509.       return NULL;
  510.     }
  511.     }
  512.  
  513.   return NULL;
  514. }
  515.  
  516. static char pyrl_builtin_completer_doc[] = "The builtin completer function";
  517. static PyObject *
  518. pyrl_builtin_completer (PyObject *self, PyObject *args)
  519. {
  520.   char *text;
  521.   int start, end;
  522.  
  523.   if (PyArg_ParseTuple (args, "sii", &text, &start, &end))
  524.     {
  525.       char **result = builtin_completion (text, start, end);
  526.  
  527.       if (result)
  528.     {
  529.       PyObject *list;
  530.       int ncompl;
  531.       
  532.       for (ncompl=0; result[ncompl]; ncompl++)
  533.         /* do nothing */;
  534.  
  535.       list = PyList_New (ncompl);
  536.       if (!list)
  537.         return NULL;
  538.  
  539.       while (ncompl--)
  540.         {
  541.           PyObject *str = PyString_FromString (result[ncompl]);
  542.  
  543.           PyList_SetItem (list, ncompl, str);
  544.           free (result[ncompl]);
  545.         }
  546.       free (result);
  547.       
  548.       return list;
  549.     }
  550.       else
  551.     {
  552.       Py_INCREF (Py_None);
  553.       return Py_None;
  554.     }
  555.     }
  556.   
  557.   return NULL;
  558. }    
  559.       
  560. extern char * (*PyOS_Readline)();
  561.  
  562. #endif /* WITH_READLINE */
  563.  
  564. static PyMethodDef pyrl_methods[] =
  565. {
  566. #ifdef WITH_READLINE
  567.   { "set_completer",    (PyCFunction) pyrl_set_completer,     METH_VARARGS,    pyrl_set_completer_doc },
  568.   { "builtin_completer",(PyCFunction) pyrl_builtin_completer,     METH_VARARGS,    pyrl_builtin_completer_doc },
  569.   { "readline",        (PyCFunction) pyrl_readline,        METH_VARARGS,    pyrl_readline_doc },
  570. #endif
  571.   { 0, 0, 0, 0 }
  572. };
  573.  
  574. static char pyrl_doc[] =
  575. #ifdef WITH_READLINE
  576. "A replacement for the builtin readline implementation that uses GNU readline.";
  577. #else
  578. "A placehold empty module";
  579. #endif
  580.  
  581. void initpyrl()
  582. {
  583.   static int been_here = 0;
  584.  
  585.   if (!been_here)
  586.     {
  587.       Py_InitModule4 ("pyrl", pyrl_methods, pyrl_doc, NULL, PYTHON_API_VERSION);
  588.  
  589.       been_here++;
  590.  
  591. #ifdef WITH_READLINE
  592.       /* Force rebind of TAB to insert-tab */
  593.       rl_bind_key ('\t', rl_insert);
  594.       rl_bind_key_in_map ('\t', rl_complete, emacs_meta_keymap);
  595.       rl_readline_name = "Python";
  596.       rl_attempted_completion_function = (CPPFunction *) python_completion;
  597.       rl_basic_word_break_characters = " \t\"'`<>=()[]{}";
  598.       PyOS_Readline = py_readline;
  599. #endif
  600.     }
  601. }
  602.