help-gnu-emacs
[Top][All Lists]
Advanced

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

Re: writing Python in Emacs


From: Thierry Volpiatto
Subject: Re: writing Python in Emacs
Date: Mon, 21 Jan 2008 08:59:36 +0100
User-agent: Gnus/5.13 (Gnus v5.13) Emacs/23.0.60 (gnu/linux)

Oops, i have an error when i launch ipython with C-c !

Traceback (most recent call last):
  File "<string>", line 1, in ?
NameError: name 'olors' is not defined

Where is this string ?
It seem to be 'colors'.
I didn't find it in your files

Rob Wolfe <rw@smsnet.pl> writes:

> Terry Jones <terry@jon.es> writes:
>
>>>>>>> "Richard" == Richard Szopa <ryszard.szopa@gmail.com> writes:
>
> I don't see Richard's original post, so I reply to Terry.
>
>>
>> Richard> I am a devoted Emacs user and I write a lot in Python.
>>
>> Me too.
>
> The good news is that I managed to configure completion for Python 
> in Emacs using pymacs, python-mode.el, pycomplete.el and pycomplete.py.
> For contents of my pycomplete.el, pycomplete.py and necessary
> settings in .emacs see below.
>
>>
>> Richard> I need the following features:
>>
>> Richard> 1) Tab completion, ideally Slime like. That is, when there's not
>> Richard> enough letters to unambiguously complete a symbol, I want it to
>> Richard> show a buffer (w/o taking the focus) w/ the possible
>> Richard> completions. In an ideal world, it would be able to complete
>> Richard> fo.ba<TAB> to foo.bar. I imagine this would require quite tight
>> Richard> Emacs-Python integration.
>
> Works for me.
>
> [...]
>
>> Richard> 2) Sending the toplevel definition (class or function) to the Python
>> Richard> buffer.
>
> That feature is defined in python-mode.el:
> "\e\C-x"    'py-execute-def-or-class
> "\C-c|"     'py-execute-region
>
>
> [...]
>
>> Richard> 3) Hints on function/method arguments. IDLE has this done nearly
>> Richard> right, but the hints are a bit too intrusive for me. I would like to
>> Richard> see them in the minibuffer.
>
> Works for me, but only for pure python functions 
> (`inspect.getargspec` constraint).
>
> [...]
>
>> Richard> I have tried a couple of times both python-modes (the one shipped w/
>> Richard> Python and the one shipped w/ Emacs), pymacs and stuff like that...
>> Richard> And, as I said, never got it right. But, maybe I just cannot find 
>> the
>> Richard> way to configure it, and some configuration hints will be enough...
>
> I mixed solutions found around the net and finally got it working:
> - hitting TAB complete function/method name
> - f1 shows description of object at point
> - hitting '(' and ',' shows function parameters
>
> Copy `pycomplete.py` on your PYTHONPATH (e.g. 
> /usr/lib/python2.5/site-packages)
> and `pycomplete.el` on your Emacs load_path (e.g. /usr/share/emacs/site-lisp).
> Copy my settings to your `.emacs` file and hopefully it will work. ;)
>
> My files:
>
> # .emacs
> (require 'pycomplete)
> (setq auto-mode-alist (cons '("\\.py$" . python-mode) auto-mode-alist))
> (autoload 'python-mode "python-mode" "Python editing mode." t)
>
> (autoload 'pymacs-load "pymacs" nil t)
> (autoload 'pymacs-eval "pymacs" nil t)
> (autoload 'pymacs-apply "pymacs")
> (autoload 'pymacs-call "pymacs")
>
> (setq interpreter-mode-alist(cons '("python" . python-mode) 
>                                   interpreter-mode-alist))
> (setq python-mode-hook
>       '(lambda () (progn
>                     (set-variable 'py-python-command "/usr/bin/python2.5")
>                     (set-variable 'py-indent-offset 4)
>                     (set-variable 'py-smart-indentation nil)
>                     (set-variable 'indent-tabs-mode nil))))
> # end of .emacs
>
>
> # pycomplete.el
> (require 'pymacs)
> (require 'python-mode)
>
> (pymacs-load "pycomplete")
>
>
> ;;check if prev character is blank-type
> (defun char-before-blank ()
>   (save-excursion
>   (forward-char -1)
>   (looking-at "[\n\t\r]")))
>
> (defun py-complete ()
>   (interactive)
>   (let ((pymacs-forget-mutability t))
>     (if (and 
>          (and (eolp) (not (bolp)) 
>          (not (char-before-blank))))
>       (insert (pycomplete-pycomplete (py-symbol-near-point) 
> (py-find-global-imports)))
>       (indent-for-tab-command))))
>
> (defun py-find-global-imports ()
>   (save-excursion
>     (let ((imports nil))
>       (goto-char (point-min))
>       (while (re-search-forward
>           "\\(import \\|from \\([A-Za-z_][A-Za-z_0-9\\.]*\\) import \\).*"
>           nil t)
>         (setq imports 
>               (append imports (list (buffer-substring
>                                      (match-beginning 0) 
>                                      (match-end 0))))))
>       imports)))
>
>
> (defun py-complete-python-dotexpr-begin nil
>   (interactive)
>   (re-search-backward "[^a-zA-Z_0-9\\.]")
>   (forward-char))
>
>
> (defun py-complete-python-dotexpr-end nil
>   (interactive)
>   (re-search-forward "[a-zA-Z_0-9\\.]*"))
>
> (put 'python-dotexpr 'beginning-op 'py-complete-python-dotexpr-begin)
> (put 'python-dotexpr 'end-op 'py-complete-python-dotexpr-end)
>
>
> (defun py-complete-show (string)
>   (display-message-or-buffer string "*PythonHelp*"))
>
>
> (defun py-complete-help (string)
>   "get help on a python expression"
>   (let ((help-string 
>          (pycomplete-pyhelp string (py-find-global-imports))))
>     (if (and help-string (> (length help-string) 300))
>         (with-output-to-temp-buffer "*Python Help*"
>           (print help-string))
>       (py-complete-show help-string))))
>
>
> (defun py-complete-help-thing-at-point nil
>   (interactive)
>   (require 'thingatpt)
>   (let ((sym (thing-at-point 'python-dotexpr)))
>     (if sym
>         (py-complete-help sym))))
>
>
> (set 'py-complete-current-signature nil)
>
> (defun py-complete-signature (function)
>   "get signature of a python function or method"
>   (interactive)
>   (set 'py-complete-current-signature
>        (pycomplete-pysignature function)))
>
>
> (defun py-complete-signature-show nil
>   (interactive)
>   (require 'thingatpt) 
>   (let ((sym (thing-at-point 'python-dotexpr)))
>     (if sym
>         (progn 
>           (py-complete-show (py-complete-signature sym))))))
>
>
> (defun py-complete-signature-expr nil
>   (interactive)
>   (require 'thingatpt)
>   (let ((dotexpr (read-string "signature on: "
>                               (thing-at-point 'python-dotexpr))))
>     (if dotexpr
>         (py-complete-show
>          (py-complete-signature dotexpr)))))
>
>
> (defun py-complete-electric-lparen nil
>   "electricly insert '(', and try to get a signature for the stuff to the 
> left"
>   (interactive)
>   (py-complete-signature-show)
>   (self-insert-command 1))
>
>
> (defun py-complete-electric-comma nil
>   "electricly insert ',', and redisplay latest signature"
>   (interactive)
>   (self-insert-command 1)
>   (if py-complete-current-signature
>       (py-complete-show (format "%s" py-complete-current-signature))))
>
>
> (define-key py-mode-map "\M-\C-i" 'py-complete)
> (define-key py-mode-map "\t" 'py-complete)
> (define-key py-mode-map [f1] 'py-complete-help-thing-at-point)
> (define-key py-mode-map "(" 'py-complete-electric-lparen)
> (define-key py-mode-map "," 'py-complete-electric-comma)
> (define-key py-mode-map [f2] 'py-complete-signature-expr)
>
> (provide 'pycomplete)
> # end of pycomplete.el
>
>
> # pycomplete.py
> import sys
> import inspect
> from StringIO import StringIO
> import os.path
>
> try:
>     x = set
> except NameError:
>     from sets import Set as set
> else:
>     del x
>
> from Pymacs import lisp
>
>
> sys.path.append('.')
>
>
> def pycomplete(s, imports=None, debug=False):
>     """Display completion in Emacs window"""
>     completions = _get_all_completions(s, imports)
>     dots = s.split(".")
>     result = os.path.commonprefix([k[len(dots[-1]):] for k in completions])
>
>     if result == "":
>         if completions:
>             if debug:
>                 width = 80
>             else:
>                 width = lisp.window_width() - 2
>
>             column = width / 20
>             white = " " * 20
>             msg = ""
>
>             counter = 0
>             for completion in completions :
>                 if len(completion) < 20 :
>                     msg += completion + white[len(completion):]
>                     counter += 1
>                 else :
>                     msg += completion + white[len(completion) - 20:]
>                     counter += 2
>
>                 if counter >= column:
>                     counter = 0
>                     msg += '\n'
>
>         else:
>             msg = "no completions!"
>         if debug:
>             print msg
>         else:
>             lisp.message(msg)
>     return result       
>
>
> def pyhelp(s, imports=None):
>     """Return object description"""
>     _import_modules(imports, globals(), None)
>     return _getdoc(s)
>         
>
> def pysignature(s):
>     """Return info about function parameters"""
>     f = None
>     try:
>         f = eval(s)
>     except Exception, ex:
>         return "%s" % ex
>
>     if inspect.ismethod(f):
>         f = f.im_func
>     if not inspect.isfunction(f):
>         return ''
>     (args, varargs, varkw, defaults) = inspect.getargspec(f)
>     return('%s: %s'
>            % (f.__name__, inspect.formatargspec(args,varargs,varkw,defaults)))
>
>
> def _getdoc(s):
>     """Return string printed by `help` function"""
>     obj = None
>     try:
>         obj = eval(s)
>     except Exception, ex:
>         return "%s" % ex
>     out = StringIO()
>     old = sys.stdout
>     sys.stdout = out
>     help(obj)
>     sys.stdout = old
>     return out.getvalue()
>
>
> def _import_modules(imports, dglobals, dlocals):
>     """If given, execute import statements"""
>     
>     if imports is not None:
>         for stmt in imports:
>             try:
>                 exec stmt in dglobals, dlocals
>             except TypeError:
>                 raise TypeError, 'invalid type: %s' % stmt
>             except:
>                 continue
>
>
> def _get_all_completions(s, imports=None):
>     """Return contextual completion of s (string of >= zero chars)"""
>     
>     dlocals = {}
>     _import_modules(imports, globals(), dlocals)
>     dots = s.split(".") 
>     if not s or len(dots) == 1:
>         keys = set()
>         keys.update(dlocals.keys())
>         keys.update(globals().keys())
>         import __builtin__
>         keys.update(dir(__builtin__))
>         keys = list(keys)
>         keys.sort()
>         if s:
>             return [k for k in keys if k.startswith(s)]
>         else:
>             return keys
>
>     sym = None
>     for i in range(1, len(dots)):
>         s = ".".join(dots[:i])   
>         try:
>             sym = eval(s, globals(), dlocals)
>         except NameError:
>             try:
>                 sym = __import__(s, globals(), dlocals, [])
>             except ImportError:
>                 return []
>     if sym is not None:  
>         s = dots[-1]     
>         return [k for k in dir(sym) if k.startswith(s)]
>
>
> def _test():
>     print ' ->', pycomplete('', debug=True)
>     print 'sys.get ->', pycomplete('sys.get', debug=True)
>     print 'settr ->', pycomplete('settr', debug=True)
>     print 'settr (plat in context) ->',
>     print pycomplete('settr', imports=['from sys import settrace'], 
> debug=True)
>     print 'foo. ->', pycomplete('foo.', debug=True)
>     print 'Enc (email * imported) ->', 
>     print pycomplete('Enc', imports=['from email import *'], debug=True)
>     print 'E (email * imported) ->',
>     print pycomplete('E', imports=['from email import *'], debug=True)
>     print 'Enc ->', pycomplete('Enc', debug=True)
>     print 'E ->', pycomplete('E', debug=True)
>
>
> if __name__ == "__main__":
>     _test()
> # end of pycomplete.py
>
>
> HTH,
> Rob
> _______________________________________________
> help-gnu-emacs mailing list
> help-gnu-emacs@gnu.org
> http://lists.gnu.org/mailman/listinfo/help-gnu-emacs
>

-- 
A + Thierry
Pub key: http://pgp.mit.edu




reply via email to

[Prev in Thread] Current Thread [Next in Thread]