cinap_lenrekadd hg and python4bb9e2215 years agoHistory
3768 lines · 138.6 KB · Emacs Lisp
RawDownload
  (interactive)  (let ((start (point))	(found nil)	initial-indent)    (py-goto-initial-line)    ;; if on blank or non-indenting comment line, use the preceding stmt    (if (looking-at "[ \t]*\\($\\|#[^ \t\n]\\)")	(progn	  (py-goto-statement-at-or-above)	  (setq found (py-statement-opens-block-p))))    ;; search back for colon line indented less    (setq initial-indent (current-indentation))    (if (zerop initial-indent)	;; force fast exit	(goto-char (point-min)))    (while (not (or found (bobp)))      (setq found	    (and	     (re-search-backward ":[ \t]*\\($\\|[#\\]\\)" nil 'move)	     (or (py-goto-initial-line) t) ; always true -- side effect	     (< (current-indentation) initial-indent)	     (py-statement-opens-block-p))))    (if found	(progn	  (or nomark (push-mark start))	  (back-to-indentation))      (goto-char start)      (error "Enclosing block not found")))) (defun py-beginning-of-def-or-class (&optional class count)  "Move point to start of `def' or `class'. Searches back for the closest preceding `def'.  If you supply a prefixarg, looks for a `class' instead.  The docs below assume the `def'case; just substitute `class' for `def' for the other case.Programmatically, if CLASS is `either', then moves to either `class'or `def'. When second optional argument is given programmatically, move to theCOUNTth start of `def'. If point is in a `def' statement already, and after the `d', simplymoves point to the start of the statement. Otherwise (i.e. when point is not in a `def' statement, or at orbefore the `d' of a `def' statement), searches for the closestpreceding `def' statement, and leaves point at its start.  If no suchstatement can be found, leaves point at the start of the buffer. Returns t iff a `def' statement is found by these rules. Note that doing this command repeatedly will take you closer to thestart of the buffer each time. To mark the current `def', see `\\[py-mark-def-or-class]'."  (interactive "P")			; raw prefix arg  (setq count (or count 1))  (let ((at-or-before-p (<= (current-column) (current-indentation)))	(start-of-line (goto-char (py-point 'bol)))	(start-of-stmt (goto-char (py-point 'bos)))	(start-re (cond ((eq class 'either) "^[ \t]*\\(class\\|def\\)\\>")			(class "^[ \t]*class\\>")			(t "^[ \t]*def\\>")))	)    ;; searching backward    (if (and (< 0 count)	     (or (/= start-of-stmt start-of-line)		 (not at-or-before-p)))	(end-of-line))    ;; search forward    (if (and (> 0 count)	     (zerop (current-column))	     (looking-at start-re))	(end-of-line))    (if (re-search-backward start-re nil 'move count)	(goto-char (match-beginning 0))))) ;; Backwards compatibility(defalias 'beginning-of-python-def-or-class 'py-beginning-of-def-or-class) (defun py-end-of-def-or-class (&optional class count)  "Move point beyond end of `def' or `class' body. By default, looks for an appropriate `def'.  If you supply a prefixarg, looks for a `class' instead.  The docs below assume the `def'case; just substitute `class' for `def' for the other case.Programmatically, if CLASS is `either', then moves to either `class'or `def'. When second optional argument is given programmatically, move to theCOUNTth end of `def'. If point is in a `def' statement already, this is the `def' we use. Else, if the `def' found by `\\[py-beginning-of-def-or-class]'contains the statement you started on, that's the `def' we use. Otherwise, we search forward for the closest following `def', and use that. If a `def' can be found by these rules, point is moved to the start ofthe line immediately following the `def' block, and the position of thestart of the `def' is returned. Else point is moved to the end of the buffer, and nil is returned. Note that doing this command repeatedly will take you closer to theend of the buffer each time. To mark the current `def', see `\\[py-mark-def-or-class]'."  (interactive "P")			; raw prefix arg  (if (and count (/= count 1))      (py-beginning-of-def-or-class (- 1 count)))  (let ((start (progn (py-goto-initial-line) (point)))	(which (cond ((eq class 'either) "\\(class\\|def\\)")		     (class "class")		     (t "def")))	(state 'not-found))    ;; move point to start of appropriate def/class    (if (looking-at (concat "[ \t]*" which "\\>")) ; already on one	(setq state 'at-beginning)      ;; else see if py-beginning-of-def-or-class hits container      (if (and (py-beginning-of-def-or-class class)	       (progn (py-goto-beyond-block)		      (> (point) start)))	  (setq state 'at-end)	;; else search forward	(goto-char start)	(if (re-search-forward (concat "^[ \t]*" which "\\>") nil 'move)	    (progn (setq state 'at-beginning)		   (beginning-of-line)))))    (cond     ((eq state 'at-beginning) (py-goto-beyond-block) t)     ((eq state 'at-end) t)     ((eq state 'not-found) nil)     (t (error "Internal error in `py-end-of-def-or-class'"))))) ;; Backwards compabitility(defalias 'end-of-python-def-or-class 'py-end-of-def-or-class) ;; Functions for marking regions(defun py-mark-block (&optional extend just-move)  "Mark following block of lines.  With prefix arg, mark structure.Easier to use than explain.  It sets the region to an `interesting'block of succeeding lines.  If point is on a blank line, it goes down tothe next non-blank line.  That will be the start of the region.  The endof the region depends on the kind of line at the start:  - If a comment, the region will include all succeeding comment lines up   to (but not including) the next non-comment line (if any).  - Else if a prefix arg is given, and the line begins one of these   structures:      if elif else try except finally for while def class    the region will be set to the body of the structure, including   following blocks that `belong' to it, but excluding trailing blank   and comment lines.  E.g., if on a `try' statement, the `try' block   and all (if any) of the following `except' and `finally' blocks   that belong to the `try' structure will be in the region.  Ditto   for if/elif/else, for/else and while/else structures, and (a bit   degenerate, since they're always one-block structures) def and   class blocks.  - Else if no prefix argument is given, and the line begins a Python   block (see list above), and the block is not a `one-liner' (i.e.,   the statement ends with a colon, not with code), the region will   include all succeeding lines up to (but not including) the next   code statement (if any) that's indented no more than the starting   line, except that trailing blank and comment lines are excluded.   E.g., if the starting line begins a multi-statement `def'   structure, the region will be set to the full function definition,   but without any trailing `noise' lines.  - Else the region will include all succeeding lines up to (but not   including) the next blank line, or code or indenting-comment line   indented strictly less than the starting line.  Trailing indenting   comment lines are included in this case, but not trailing blank   lines. A msg identifying the location of the mark is displayed in the echoarea; or do `\\[exchange-point-and-mark]' to flip down to the end. If called from a program, optional argument EXTEND plays the role ofthe prefix arg, and if optional argument JUST-MOVE is not nil, justmoves to the end of the block (& does not set mark or display a msg)."  (interactive "P")			; raw prefix arg  (py-goto-initial-line)  ;; skip over blank lines  (while (and	  (looking-at "[ \t]*$")	; while blank line	  (not (eobp)))			; & somewhere to go    (forward-line 1))  (if (eobp)      (error "Hit end of buffer without finding a non-blank stmt"))  (let ((initial-pos (point))	(initial-indent (current-indentation))	last-pos			; position of last stmt in region	(followers	 '((if elif else) (elif elif else) (else)	   (try except finally) (except except) (finally)	   (for else) (while else)	   (def) (class) ) )	first-symbol next-symbol)     (cond     ;; if comment line, suck up the following comment lines     ((looking-at "[ \t]*#")      (re-search-forward "^[ \t]*[^ \t#]" nil 'move) ; look for non-comment      (re-search-backward "^[ \t]*#")	; and back to last comment in block      (setq last-pos (point)))      ;; else if line is a block line and EXTEND given, suck up     ;; the whole structure     ((and extend	   (setq first-symbol (py-suck-up-first-keyword) )	   (assq first-symbol followers))      (while (and	      (or (py-goto-beyond-block) t) ; side effect	      (forward-line -1)		; side effect	      (setq last-pos (point))	; side effect	      (py-goto-statement-below)	      (= (current-indentation) initial-indent)	      (setq next-symbol (py-suck-up-first-keyword))	      (memq next-symbol (cdr (assq first-symbol followers))))	(setq first-symbol next-symbol)))      ;; else if line *opens* a block, search for next stmt indented <=     ((py-statement-opens-block-p)      (while (and	      (setq last-pos (point))	; always true -- side effect	      (py-goto-statement-below)	      (> (current-indentation) initial-indent)	      )))      ;; else plain code line; stop at next blank line, or stmt or     ;; indenting comment line indented <     (t      (while (and	      (setq last-pos (point))	; always true -- side effect	      (or (py-goto-beyond-final-line) t)	      (not (looking-at "[ \t]*$")) ; stop at blank line	      (or	       (>= (current-indentation) initial-indent)	       (looking-at "[ \t]*#[^ \t\n]"))) ; ignore non-indenting #	nil)))     ;; skip to end of last stmt    (goto-char last-pos)    (py-goto-beyond-final-line)     ;; set mark & display    (if just-move	()				; just return      (push-mark (point) 'no-msg)      (forward-line -1)      (message "Mark set after: %s" (py-suck-up-leading-text))      (goto-char initial-pos)))) (defun py-mark-def-or-class (&optional class)  "Set region to body of def (or class, with prefix arg) enclosing point.Pushes the current mark, then point, on the mark ring (all languagemodes do this, but although it's handy it's never documented ...). In most Emacs language modes, this function bears at least ahallucinogenic resemblance to `\\[py-end-of-def-or-class]' and`\\[py-beginning-of-def-or-class]'. And in earlier versions of Python mode, all 3 were tightly connected.Turned out that was more confusing than useful: the `goto start' and`goto end' commands are usually used to search through a file, andpeople expect them to act a lot like `search backward' and `searchforward' string-search commands.  But because Python `def' and `class'can nest to arbitrary levels, finding the smallest def containingpoint cannot be done via a simple backward search: the def containingpoint may not be the closest preceding def, or even the closestpreceding def that's indented less.  The fancy algorithm required isappropriate for the usual uses of this `mark' command, but not for the`goto' variations. So the def marked by this command may not be the one either of the`goto' commands find: If point is on a blank or non-indenting commentline, moves back to start of the closest preceding code statement orindenting comment line.  If this is a `def' statement, that's the defwe use.  Else searches for the smallest enclosing `def' block and usesthat.  Else signals an error. When an enclosing def is found: The mark is left immediately beyondthe last line of the def block.  Point is left at the start of thedef, except that: if the def is preceded by a number of comment linesfollowed by (at most) one optional blank line, point is left at thestart of the comments; else if the def is preceded by a blank line,point is left at its start. The intent is to mark the containing def/class and its associateddocumentation, to make moving and duplicating functions and classespleasant."  (interactive "P")			; raw prefix arg  (let ((start (point))	(which (cond ((eq class 'either) "\\(class\\|def\\)")		     (class "class")		     (t "def"))))    (push-mark start)    (if (not (py-go-up-tree-to-keyword which))	(progn (goto-char start)	       (error "Enclosing %s not found"		      (if (eq class 'either)			  "def or class"			which)))      ;; else enclosing def/class found      (setq start (point))      (py-goto-beyond-block)      (push-mark (point))      (goto-char start)      (if (zerop (forward-line -1))	; if there is a preceding line	  (progn	    (if (looking-at "[ \t]*$")	; it's blank		(setq start (point))	; so reset start point	      (goto-char start))	; else try again	    (if (zerop (forward-line -1))		(if (looking-at "[ \t]*#") ; a comment		    ;; look back for non-comment line		    ;; tricky: note that the regexp matches a blank		    ;; line, cuz \n is in the 2nd character class		    (and		     (re-search-backward "^[ \t]*[^ \t#]" nil 'move)		     (forward-line 1))		  ;; no comment, so go back		  (goto-char start)))))))  (exchange-point-and-mark)  (py-keep-region-active)) ;; ripped from cc-mode(defun py-forward-into-nomenclature (&optional arg)  "Move forward to end of a nomenclature section or word.With \\[universal-argument] (programmatically, optional argument ARG), do it that many times. A `nomenclature' is a fancy way of saying AWordWithMixedCaseNotUnderscores."  (interactive "p")  (let ((case-fold-search nil))    (if (> arg 0)	(re-search-forward	 "\\(\\W\\|[_]\\)*\\([A-Z]*[a-z0-9]*\\)"	 (point-max) t arg)      (while (and (< arg 0)		  (re-search-backward		   "\\(\\W\\|[a-z0-9]\\)[A-Z]+\\|\\(\\W\\|[_]\\)\\w+"		   (point-min) 0))	(forward-char 1)	(setq arg (1+ arg)))))  (py-keep-region-active)) (defun py-backward-into-nomenclature (&optional arg)  "Move backward to beginning of a nomenclature section or word.With optional ARG, move that many times.  If ARG is negative, moveforward. A `nomenclature' is a fancy way of saying AWordWithMixedCaseNotUnderscores."  (interactive "p")  (py-forward-into-nomenclature (- arg))  (py-keep-region-active))  ;; pdbtrack functions(defun py-pdbtrack-toggle-stack-tracking (arg)  (interactive "P")  (if (not (get-buffer-process (current-buffer)))      (error "No process associated with buffer '%s'" (current-buffer)))  ;; missing or 0 is toggle, >0 turn on, <0 turn off  (if (or (not arg)	  (zerop (setq arg (prefix-numeric-value arg))))      (setq py-pdbtrack-do-tracking-p (not py-pdbtrack-do-tracking-p))    (setq py-pdbtrack-do-tracking-p (> arg 0)))  (message "%sabled Python's pdbtrack"           (if py-pdbtrack-do-tracking-p "En" "Dis"))) (defun turn-on-pdbtrack ()  (interactive)  (py-pdbtrack-toggle-stack-tracking 1)) (defun turn-off-pdbtrack ()  (interactive)  (py-pdbtrack-toggle-stack-tracking 0))  ;; Pychecker(defun py-pychecker-run (command)  "*Run pychecker (default on the file currently visited)."  (interactive   (let ((default           (format "%s %s %s" py-pychecker-command		   (mapconcat 'identity py-pychecker-command-args " ")		   (buffer-file-name)))	 (last (when py-pychecker-history		 (let* ((lastcmd (car py-pychecker-history))			(cmd (cdr (reverse (split-string lastcmd))))			(newcmd (reverse (cons (buffer-file-name) cmd))))		   (mapconcat 'identity newcmd " ")))))      (list      (if (fboundp 'read-shell-command)	  (read-shell-command "Run pychecker like this: "			      (if last				  last				default)			      'py-pychecker-history)	(read-string "Run pychecker like this: "		     (if last			 last		       default)		     'py-pychecker-history))	)))  (save-some-buffers (not py-ask-about-save) nil)  (compile-internal command "No more errors"))  ;; pydoc commands. The guts of this function is stolen from XEmacs's;; symbol-near-point, but without the useless regexp-quote call on the;; results, nor the interactive bit.  Also, we've added the temporary;; syntax table setting, which Skip originally had broken out into a;; separate function.  Note that Emacs doesn't have the original;; function.(defun py-symbol-near-point ()  "Return the first textual item to the nearest point."  ;; alg stolen from etag.el  (save-excursion    (with-syntax-table py-dotted-expression-syntax-table      (if (or (bobp) (not (memq (char-syntax (char-before)) '(?w ?_))))	  (while (not (looking-at "\\sw\\|\\s_\\|\\'"))	    (forward-char 1)))      (while (looking-at "\\sw\\|\\s_")	(forward-char 1))      (if (re-search-backward "\\sw\\|\\s_" nil t)	  (progn (forward-char 1)		 (buffer-substring (point)				   (progn (forward-sexp -1)					  (while (looking-at "\\s'")					    (forward-char 1))					  (point))))	nil)))) (defun py-help-at-point ()  "Get help from Python based on the symbol nearest point."  (interactive)  (let* ((sym (py-symbol-near-point))	 (base (substring sym 0 (or (search "." sym :from-end t) 0)))	 cmd)    (if (not (equal base ""))        (setq cmd (concat "import " base "\n")))    (setq cmd (concat "import pydoc\n"                      cmd		      "try: pydoc.help('" sym "')\n"		      "except: print 'No help available on:', \"" sym "\""))    (message cmd)    (py-execute-string cmd)    (set-buffer "*Python Output*")    ;; BAW: Should we really be leaving the output buffer in help-mode?    (help-mode)))  ;; Documentation functions ;; dump the long form of the mode blurb; does the usual doc escapes,;; plus lines of the form ^[vc]:name$ to suck variable & command docs;; out of the right places, along with the keys they're on & current;; values(defun py-dump-help-string (str)  (with-output-to-temp-buffer "*Help*"    (let ((locals (buffer-local-variables))	  funckind funcname func funcdoc	  (start 0) mstart end	  keys )      (while (string-match "^%\\([vc]\\):\\(.+\\)\n" str start)	(setq mstart (match-beginning 0)  end (match-end 0)	      funckind (substring str (match-beginning 1) (match-end 1))	      funcname (substring str (match-beginning 2) (match-end 2))	      func (intern funcname))	(princ (substitute-command-keys (substring str start mstart)))	(cond	 ((equal funckind "c")		; command	  (setq funcdoc (documentation func)		keys (concat		      "Key(s): "		      (mapconcat 'key-description				 (where-is-internal func py-mode-map)				 ", "))))	 ((equal funckind "v")		; variable	  (setq funcdoc (documentation-property func 'variable-documentation)		keys (if (assq func locals)			 (concat			  "Local/Global values: "			  (prin1-to-string (symbol-value func))			  " / "			  (prin1-to-string (default-value func)))

Lines 2501–3000 of 3768. Previous lines