summaryrefslogtreecommitdiff
path: root/lisp/progmodes
diff options
context:
space:
mode:
Diffstat (limited to 'lisp/progmodes')
-rw-r--r--lisp/progmodes/compile.el51
-rw-r--r--lisp/progmodes/gdb-ui.el91
-rw-r--r--lisp/progmodes/python.el454
-rw-r--r--lisp/progmodes/sql.el96
4 files changed, 427 insertions, 265 deletions
diff --git a/lisp/progmodes/compile.el b/lisp/progmodes/compile.el
index 4c6f88813c0..ec381ad8a15 100644
--- a/lisp/progmodes/compile.el
+++ b/lisp/progmodes/compile.el
@@ -944,6 +944,7 @@ Returns the compilation buffer created."
;; Fake modeline display as if `start-process' were run.
(setq mode-line-process ":run")
(force-mode-line-update)
+ (sit-for 0) ; Force redisplay
(let ((status (call-process shell-file-name nil outbuf nil "-c"
command)))
(cond ((numberp status)
@@ -958,6 +959,10 @@ exited abnormally with code %d\n"
(concat status "\n")))
(t
(compilation-handle-exit 'bizarre status status))))
+ ;; Without async subprocesses, the buffer is not yet
+ ;; fontified, so fontify it now.
+ (let ((font-lock-verbose nil)) ; shut up font-lock messages
+ (font-lock-fontify-buffer))
(message "Executing `%s'...done" command)))
(if (buffer-local-value 'compilation-scroll-output outbuf)
(save-selected-window
@@ -1095,10 +1100,6 @@ Runs `compilation-mode-hook' with `run-hooks' (which see)."
(set (make-local-variable 'page-delimiter)
compilation-page-delimiter)
(compilation-setup)
- ;; note that compilation-next-error-function is for interfacing
- ;; with the next-error function in simple.el, and it's only
- ;; coincidentally named similarly to compilation-next-error
- (setq next-error-function 'compilation-next-error-function)
(run-mode-hooks 'compilation-mode-hook))
(defmacro define-compilation-mode (mode name doc &rest body)
@@ -1150,6 +1151,10 @@ variable exists."
"Marker to the location from where the next error will be found.
The global commands next/previous/first-error/goto-error use this.")
+(defvar compilation-messages-start nil
+ "Buffer position of the beginning of the compilation messages.
+If nil, use the beginning of buffer.")
+
;; A function name can't be a hook, must be something with a value.
(defconst compilation-turn-on-font-lock 'turn-on-font-lock)
@@ -1158,8 +1163,13 @@ The global commands next/previous/first-error/goto-error use this.")
Optional argument MINOR indicates this is called from
`compilation-minor-mode'."
(make-local-variable 'compilation-current-error)
+ (make-local-variable 'compilation-messages-start)
(make-local-variable 'compilation-error-screen-columns)
(make-local-variable 'overlay-arrow-position)
+ ;; Note that compilation-next-error-function is for interfacing
+ ;; with the next-error function in simple.el, and it's only
+ ;; coincidentally named similarly to compilation-next-error.
+ (setq next-error-function 'compilation-next-error-function)
(set (make-local-variable 'font-lock-extra-managed-props)
'(directory message help-echo mouse-face debug))
(set (make-local-variable 'compilation-locs)
@@ -1404,16 +1414,16 @@ Use this command in a compilation log buffer. Sets the mark at point there."
(let* ((columns compilation-error-screen-columns) ; buffer's local value
(last 1)
(loc (compilation-next-error (or n 1) nil
- (or compilation-current-error (point-min))))
+ (or compilation-current-error
+ compilation-messages-start
+ (point-min))))
(end-loc (nth 2 loc))
(marker (point-marker)))
(setq compilation-current-error (point-marker)
overlay-arrow-position
(if (bolp)
compilation-current-error
- (save-excursion
- (beginning-of-line)
- (point-marker)))
+ (copy-marker (line-beginning-position)))
loc (car loc))
;; If loc contains no marker, no error in that file has been visited. If
;; the marker is invalid the buffer has been killed. So, recalculate all
@@ -1447,6 +1457,10 @@ Use this command in a compilation log buffer. Sets the mark at point there."
(compilation-goto-locus marker (nth 3 loc) (nth 3 end-loc))
(setcdr (nthcdr 3 loc) t))) ; Set this one as visited.
+(defvar compilation-gcpro nil
+ "Internal variable used to keep some values from being GC'd.")
+(make-variable-buffer-local 'compilation-gcpro)
+
(defun compilation-fake-loc (marker file &optional line col)
"Preassociate MARKER with FILE.
FILE should be ABSOLUTE-FILENAME or (RELATIVE-FILENAME . DIRNAME).
@@ -1466,6 +1480,11 @@ call this several times, once each for the last line of one
region and the first line of the next region."
(or (consp file) (setq file (list file)))
(setq file (compilation-get-file-structure file))
+ ;; Between the current call to compilation-fake-loc and the first occurrence
+ ;; of an error message referring to `file', the data is only kept is the
+ ;; weak hash-table compilation-locs, so we need to prevent this entry
+ ;; in compilation-locs from being GC'd away. --Stef
+ (push file compilation-gcpro)
(let ((loc (compilation-assq (or line 1) (cdr file))))
(setq loc (compilation-assq col loc))
(if (cdr loc)
@@ -1715,10 +1734,12 @@ FILE should be (ABSOLUTE-FILENAME) or (RELATIVE-FILENAME . DIRNAME)."
(goto-char limit)
nil)
+;; Beware: this is not only compatiblity code. New code stil uses it. --Stef
(defun compilation-forget-errors ()
;; In case we hit the same file/line specs, we want to recompute a new
;; marker for them, so flush our cache.
(setq compilation-locs (make-hash-table :test 'equal :weakness 'value))
+ (setq compilation-gcpro nil)
;; FIXME: the old code reset the directory-stack, so maybe we should
;; put a `directory change' marker of some sort, but where? -stef
;;
@@ -1730,9 +1751,19 @@ FILE should be (ABSOLUTE-FILENAME) or (RELATIVE-FILENAME . DIRNAME)."
;; something equivalent to point-max. So we speculatively move
;; compilation-current-error to point-max (since the external package
;; won't know that it should do it). --stef
- (setq compilation-current-error (point-max)))
+ (setq compilation-current-error nil)
+ (let* ((proc (get-buffer-process (current-buffer)))
+ (mark (if proc (process-mark proc)))
+ (pos (or mark (point-max))))
+ (setq compilation-messages-start
+ ;; In the future, ignore the text already present in the buffer.
+ ;; Since many process filter functions insert before markers,
+ ;; we need to put ours just before the insertion point rather
+ ;; than at the insertion point. If that's not possible, then
+ ;; don't use a marker. --Stef
+ (if (> pos (point-min)) (copy-marker (1- pos)) pos))))
(provide 'compile)
-;;; arch-tag: 12465727-7382-4f72-b234-79855a00dd8c
+;; arch-tag: 12465727-7382-4f72-b234-79855a00dd8c
;;; compile.el ends here
diff --git a/lisp/progmodes/gdb-ui.el b/lisp/progmodes/gdb-ui.el
index 2e836fb82b2..fc3196cdb4f 100644
--- a/lisp/progmodes/gdb-ui.el
+++ b/lisp/progmodes/gdb-ui.el
@@ -217,9 +217,10 @@ speedbar."
(gdb-enqueue-input
(list (concat "server interpreter mi \"-var-create - * " expr "\"\n")
`(lambda () (gdb-var-create-handler ,expr))))))
- (select-window (get-buffer-window gud-comint-buffer)))
+ (select-window (get-buffer-window gud-comint-buffer 'visible)))
(defun gdb-goto-info ()
+ "Go to Emacs info node: GDB Graphical Interface."
(interactive)
(select-frame (make-frame))
(require 'info)
@@ -1117,7 +1118,7 @@ static char *magick[] = {
(if (gdb-get-buffer 'gdb-assembler-buffer) (gdb-assembler-custom)))
(defun gdb-mouse-toggle-breakpoint (event)
- "Toggle breakpoint with mouse click in left margin."
+ "Toggle breakpoint in left fringe/margin with mouse click"
(interactive "e")
(mouse-minibuffer-check event)
(let ((posn (event-end event)))
@@ -1137,6 +1138,7 @@ static char *magick[] = {
(concat "*breakpoints of " (gdb-get-target-string) "*")))
(defun gdb-display-breakpoints-buffer ()
+ "Display status of user-settable breakpoints."
(interactive)
(gdb-display-buffer
(gdb-get-create-buffer 'gdb-breakpoints-buffer)))
@@ -1149,6 +1151,7 @@ static char *magick[] = {
(minibuffer . nil)))
(defun gdb-frame-breakpoints-buffer ()
+ "Display status of user-settable breakpoints in a new frame."
(interactive)
(select-frame (make-frame gdb-frame-parameters))
(switch-to-buffer (gdb-get-create-buffer 'gdb-breakpoints-buffer))
@@ -1205,8 +1208,7 @@ static char *magick[] = {
(list (concat "server delete " (match-string 1) "\n") 'ignore))))
(defun gdb-goto-breakpoint ()
- "Display the file in the source buffer at the breakpoint specified on the
-current line."
+ "Display the breakpoint location specified at current line."
(interactive)
(save-excursion
(beginning-of-line 1)
@@ -1216,14 +1218,16 @@ current line."
(let ((line (match-string 2))
(file (match-string 1)))
(save-selected-window
- (gdb-display-buffer (find-file-noselect
- (if (file-exists-p file)
- file
- (expand-file-name file gdb-cdir))))
- (goto-line (string-to-number line))))))
+ (let* ((buf (find-file-noselect (if (file-exists-p file)
+ file
+ (expand-file-name file gdb-cdir))))
+ (window (gdb-display-buffer buf)))
+ (with-current-buffer buf
+ (goto-line (string-to-number line))
+ (set-window-point window (point))))))))
(defun gdb-mouse-goto-breakpoint (event)
- "Display the file in the source buffer at the selected breakpoint."
+ "Display the breakpoint location that you click on."
(interactive "e")
(mouse-set-point event)
(gdb-goto-breakpoint))
@@ -1266,11 +1270,13 @@ current line."
(concat "*stack frames of " (gdb-get-target-string) "*")))
(defun gdb-display-stack-buffer ()
+ "Display backtrace of current stack."
(interactive)
(gdb-display-buffer
(gdb-get-create-buffer 'gdb-stack-buffer)))
(defun gdb-frame-stack-buffer ()
+ "Display backtrace of current stack in a new frame."
(interactive)
(select-frame (make-frame gdb-frame-parameters))
(switch-to-buffer (gdb-get-create-buffer 'gdb-stack-buffer))
@@ -1301,16 +1307,14 @@ current line."
n)))
(defun gdb-frames-select ()
- "Make the frame on the current line become the current frame and display the
-source in the source buffer."
+ "Select the frame and display the relevant source."
(interactive)
(gdb-enqueue-input
(list (concat "server frame " (gdb-get-frame-number) "\n") 'ignore))
(gud-display-frame))
(defun gdb-frames-mouse-select (event)
- "Make the selected frame become the current frame and display the source in
-the source buffer."
+ "Select the frame you click on and display the relevant source."
(interactive "e")
(mouse-set-point event)
(gdb-frames-select))
@@ -1343,11 +1347,13 @@ the source buffer."
(concat "*threads of " (gdb-get-target-string) "*")))
(defun gdb-display-threads-buffer ()
+ "Display IDs of currently known threads."
(interactive)
(gdb-display-buffer
(gdb-get-create-buffer 'gdb-threads-buffer)))
(defun gdb-frame-threads-buffer ()
+ "Display IDs of currently known threads in a new frame."
(interactive)
(select-frame (make-frame gdb-frame-parameters))
(switch-to-buffer (gdb-get-create-buffer 'gdb-threads-buffer))
@@ -1376,16 +1382,14 @@ the source buffer."
(match-string-no-properties 1)))
(defun gdb-threads-select ()
- "Make the thread on the current line become the current thread and display the
-source in the source buffer."
+ "Select the thread and display the relevant source."
(interactive)
(gdb-enqueue-input
(list (concat "thread " (gdb-get-thread-number) "\n") 'ignore))
(gud-display-frame))
(defun gdb-threads-mouse-select (event)
- "Make the selected frame become the current frame and display the source in
-the source buffer."
+ "Select the thread you click on and display the relevant source."
(interactive "e")
(mouse-set-point event)
(gdb-threads-select))
@@ -1425,11 +1429,13 @@ the source buffer."
(concat "*registers of " (gdb-get-target-string) "*")))
(defun gdb-display-registers-buffer ()
+ "Display integer register contents."
(interactive)
(gdb-display-buffer
(gdb-get-create-buffer 'gdb-registers-buffer)))
(defun gdb-frame-registers-buffer ()
+ "Display integer register contents in a new frame."
(interactive)
(select-frame (make-frame gdb-frame-parameters))
(switch-to-buffer (gdb-get-create-buffer 'gdb-registers-buffer))
@@ -1497,11 +1503,13 @@ the source buffer."
(concat "*locals of " (gdb-get-target-string) "*")))
(defun gdb-display-locals-buffer ()
+ "Display local variables of current stack and their values."
(interactive)
(gdb-display-buffer
(gdb-get-create-buffer 'gdb-locals-buffer)))
(defun gdb-frame-locals-buffer ()
+ "Display local variables of current stack and their values in a new frame."
(interactive)
(select-frame (make-frame gdb-frame-parameters))
(switch-to-buffer (gdb-get-create-buffer 'gdb-locals-buffer))
@@ -1524,7 +1532,7 @@ the source buffer."
#'(lambda (win)
(if (eq gud-comint-buffer (window-buffer win))
(set-window-dedicated-p win t))))
- (setq answer (get-buffer-window buf))
+ (setq answer (get-buffer-window buf 'visible))
(if (not answer)
(let ((window (get-lru-window 'visible)))
(if window
@@ -1548,7 +1556,7 @@ the source buffer."
(if (eq gdb-selected-view 'source)
(gdb-display-buffer buffer)
(gdb-display-buffer (gdb-get-buffer 'gdb-assembler-buffer)))
- (get-buffer-window buffer))
+ (get-buffer-window buffer 'visible))
;;; Shared keymap initialization:
@@ -1557,11 +1565,11 @@ the source buffer."
(define-key gud-menu-map [frames]
`(menu-item "GDB-Frames" ,menu :visible (eq gud-minor-mode 'gdba)))
(define-key menu [gdb] '("Gdb" . gdb-frame-gdb-buffer))
- (define-key menu [locals] '("Locals" . gdb-frame-locals-buffer))
+ (define-key menu [threads] '("Threads" . gdb-frame-threads-buffer))
(define-key menu [registers] '("Registers" . gdb-frame-registers-buffer))
+ (define-key menu [locals] '("Locals" . gdb-frame-locals-buffer))
(define-key menu [frames] '("Stack" . gdb-frame-stack-buffer))
(define-key menu [breakpoints] '("Breakpoints" . gdb-frame-breakpoints-buffer))
- (define-key menu [threads] '("Threads" . gdb-frame-threads-buffer))
; (define-key menu [assembler] '("Machine" . gdb-frame-assembler-buffer))
)
@@ -1569,11 +1577,11 @@ the source buffer."
(define-key gud-menu-map [displays]
`(menu-item "GDB-Windows" ,menu :visible (eq gud-minor-mode 'gdba)))
(define-key menu [gdb] '("Gdb" . gdb-display-gdb-buffer))
- (define-key menu [locals] '("Locals" . gdb-display-locals-buffer))
+ (define-key menu [threads] '("Threads" . gdb-display-threads-buffer))
(define-key menu [registers] '("Registers" . gdb-display-registers-buffer))
+ (define-key menu [locals] '("Locals" . gdb-display-locals-buffer))
(define-key menu [frames] '("Stack" . gdb-display-stack-buffer))
(define-key menu [breakpoints] '("Breakpoints" . gdb-display-breakpoints-buffer))
- (define-key menu [threads] '("Threads" . gdb-display-threads-buffer))
; (define-key menu [assembler] '("Machine" . gdb-display-assembler-buffer))
)
@@ -1601,12 +1609,14 @@ the source buffer."
"Display locals, stack and breakpoint information")))
(defun gdb-frame-gdb-buffer ()
+ "Display GUD buffer in a new frame."
(interactive)
(select-frame (make-frame gdb-frame-parameters))
(switch-to-buffer (gdb-get-create-buffer 'gdba))
(set-window-dedicated-p (selected-window) t))
(defun gdb-display-gdb-buffer ()
+ "Display GUD buffer."
(interactive)
(gdb-display-buffer
(gdb-get-create-buffer 'gdba)))
@@ -1614,6 +1624,7 @@ the source buffer."
(defvar gdb-main-file nil "Source file from which program execution begins.")
(defun gdb-view-source-function ()
+ "Select source view."
(interactive)
(if gdb-view-source
(gdb-display-buffer
@@ -1623,6 +1634,7 @@ the source buffer."
(setq gdb-selected-view 'source))
(defun gdb-view-assembler()
+ "Select disassembly view."
(interactive)
(gdb-display-buffer (gdb-get-create-buffer 'gdb-assembler-buffer))
(gdb-invalidate-assembler)
@@ -1805,11 +1817,10 @@ BUFFER nil or omitted means use the current buffer."
(when (< left-margin-width 2)
(save-current-buffer
(setq left-margin-width 2)
- (if (get-buffer-window (current-buffer))
- (set-window-margins (get-buffer-window
- (current-buffer))
- left-margin-width
- right-margin-width))))
+ (if (get-buffer-window (current-buffer) 'visible)
+ (set-window-margins
+ (get-buffer-window (current-buffer) 'visible)
+ left-margin-width right-margin-width))))
(put-image
(if enabled
(or breakpoint-enabled-icon
@@ -1833,11 +1844,10 @@ BUFFER nil or omitted means use the current buffer."
(when (< left-margin-width 2)
(save-current-buffer
(setq left-margin-width 2)
- (if (get-buffer-window (current-buffer))
- (set-window-margins (get-buffer-window
- (current-buffer))
- left-margin-width
- right-margin-width))))
+ (if (get-buffer-window (current-buffer) 'visible)
+ (set-window-margins
+ (get-buffer-window (current-buffer) 'visible)
+ left-margin-width right-margin-width))))
(gdb-put-string (if enabled "B" "b") (1+ start)))))
(defun gdb-remove-breakpoint-icons (start end &optional remove-margin)
@@ -1846,11 +1856,10 @@ BUFFER nil or omitted means use the current buffer."
(remove-images start end))
(when remove-margin
(setq left-margin-width 0)
- (if (get-buffer-window (current-buffer))
- (set-window-margins (get-buffer-window
- (current-buffer))
- left-margin-width
- right-margin-width))))
+ (if (get-buffer-window (current-buffer) 'visible)
+ (set-window-margins
+ (get-buffer-window (current-buffer) 'visible)
+ left-margin-width right-margin-width))))
;;
@@ -1901,7 +1910,7 @@ BUFFER nil or omitted means use the current buffer."
(if (re-search-forward address nil t)
(gdb-put-breakpoint-icon (eq flag ?y))))))))
(if (not (equal gdb-current-address "main"))
- (set-window-point (get-buffer-window buffer) pos))))
+ (set-window-point (get-buffer-window buffer 'visible) pos))))
(defvar gdb-assembler-mode-map
(let ((map (make-sparse-keymap)))
@@ -1927,11 +1936,13 @@ BUFFER nil or omitted means use the current buffer."
(concat "*Machine Code " (gdb-get-target-string) "*")))
(defun gdb-display-assembler-buffer ()
+ "Display disassembly view."
(interactive)
(gdb-display-buffer
(gdb-get-create-buffer 'gdb-assembler-buffer)))
(defun gdb-frame-assembler-buffer ()
+ "Display disassembly view in a new frame."
(interactive)
(select-frame (make-frame gdb-frame-parameters))
(switch-to-buffer (gdb-get-create-buffer 'gdb-assembler-buffer))
diff --git a/lisp/progmodes/python.el b/lisp/progmodes/python.el
index 9eaba9027b8..0fdaf652e50 100644
--- a/lisp/progmodes/python.el
+++ b/lisp/progmodes/python.el
@@ -46,19 +46,18 @@
;; I've installed a minor mode to do the job properly in Emacs 22.
;; Other things seem more natural or canonical here, e.g. the
;; {beginning,end}-of-defun implementation dealing with nested
-;; definitions, and the inferior mode following `cmuscheme'. (The
-;; inferior mode should be able to find the source of errors from
-;; `python-send-region' & al via `compilation-minor-mode', but I can't
-;; make that work with the current (March '04) compile.el.)
-;; Successive TABs cycle between possible indentations for the line.
+;; definitions, and the inferior mode following `cmuscheme'. The
+;; inferior mode can find the source of errors from
+;; `python-send-region' & al via `compilation-minor-mode'. Successive
+;; TABs cycle between possible indentations for the line. There is
+;; symbol completion using lookup in Python.
;; Even where it has similar facilities, this is incompatible with
;; python-mode.el in various respects. For instance, various key
;; bindings are changed to obey Emacs conventions, and things like
;; marking blocks and `beginning-of-defun' behave differently.
-;; TODO: See various Fixmes below. It should be possible to arrange
-;; some sort of completion using the inferior interpreter.
+;; TODO: See various Fixmes below.
;;; Code:
@@ -203,6 +202,8 @@ Used for syntactic keywords. N is the match number (1, 2 or 3)."
(define-key map "\C-c\C-z" 'python-switch-to-python)
(define-key map "\C-c\C-m" 'python-load-file)
(define-key map "\C-c\C-l" 'python-load-file) ; a la cmuscheme
+ (substitute-key-definition 'complete-symbol 'python-complete-symbol
+ map global-map)
;; Fixme: Add :help to menu.
(easy-menu-define python-menu map "Python Mode menu"
'("Python"
@@ -261,9 +262,7 @@ Used for syntactic keywords. N is the match number (1, 2 or 3)."
;;;; Utility stuff
(defsubst python-in-string/comment ()
- "Return non-nil if point is in a Python literal (a comment or string).
-Optional argument LIM indicates the beginning of the containing form,
-i.e. the limit on how far back to scan."
+ "Return non-nil if point is in a Python literal (a comment or string)."
(syntax-ppss-context (syntax-ppss)))
(defconst python-space-backslash-table
@@ -300,14 +299,17 @@ comments and strings, or that the bracket/paren nesting depth is nonzero."
(defun python-comment-line-p ()
"Return non-nil if current line has only a comment or is blank."
(save-excursion
- (back-to-indentation)
- (looking-at (rx (or (syntax comment-start) line-end)))))
+ (end-of-line)
+ ;; FIXME: This looks wrong because it returns nil for empty lines. --Stef
+ (when (eq 'comment (syntax-ppss-context (syntax-ppss)))
+ (back-to-indentation)
+ (looking-at (rx (or (syntax comment-start) line-end))))))
(defun python-beginning-of-string ()
"Go to beginning of string around point.
Do nothing if not in string."
(let ((state (syntax-ppss)))
- (when (nth 3 state)
+ (when (eq 'string (syntax-ppss-context state))
(goto-char (nth 8 state)))))
(defun python-open-block-statement-p (&optional bos)
@@ -383,7 +385,8 @@ Otherwise indent them to column zero."
(defcustom python-honour-comment-indentation nil
"Non-nil means indent relative to preceding comment line.
Only do this for comments where the leading comment character is followed
-by space."
+by space. This doesn't apply to comment lines, which are always indented
+in lines with preceding comments."
:type 'boolean
:group 'python)
@@ -513,6 +516,16 @@ Set `python-indent' locally to the value guessed."
(- python-indent)))
0)))))))))
+(defun python-comment-indent ()
+ "`comment-indent-function' for Python."
+ ;; If previous non-blank line was a comment, use its indentation.
+ ;; FIXME: This seems unnecessary since the default code delegates to
+ ;; indent-according-to-mode. --Stef
+ (unless (bobp)
+ (save-excursion
+ (forward-comment -1)
+ (if (eq ?# (char-after)) (current-column)))))
+
;;;; Cycling through the possible indentations with successive TABs.
;; These don't need to be buffer-local since they're only relevant
@@ -537,11 +550,17 @@ Set `python-indent' locally to the value guessed."
(point))))
(defun python-indentation-levels ()
- "Return a list of possible indentations for this statement.
+ "Return a list of possible indentations for this line.
Includes the default indentation and those which would close all
-enclosing blocks."
+enclosing blocks. Assumes the line has already been indented per
+`python-indent-line'. Elements of the list are actually pairs:
+\(INDENTATION . TEXT), where TEXT is the initial text of the
+corresponding block opening (or nil)."
(save-excursion
- (let ((levels (list (cons (current-indentation) nil))))
+ (let ((levels (list (cons (current-indentation)
+ (save-excursion
+ (if (python-beginning-of-block)
+ (python-initial-text)))))))
;; Only one possibility if we immediately follow a block open or
;; are in a continuation line.
(unless (or (python-continuation-line-p)
@@ -567,8 +586,7 @@ enclosing blocks."
(if (> (- (point-max) pos) (point))
(goto-char (- (point-max) pos))))))
-;; Fixme: Is the arg necessary?
-(defun python-indent-line (&optional arg)
+(defun python-indent-line ()
"Indent current line as Python code.
When invoked via `indent-for-tab-command', cycle through possible
indentations for current line. The cycle is broken by a command different
@@ -585,13 +603,30 @@ from `indent-for-tab-command', i.e. successive TABs do the cycling."
(beginning-of-line)
(delete-horizontal-space)
(indent-to (car (nth python-indent-index python-indent-list)))
- (let ((text (cdr (nth python-indent-index
- python-indent-list))))
- (if text (message "Closes: %s" text)))))
+ (if (python-block-end-p)
+ (let ((text (cdr (nth python-indent-index
+ python-indent-list))))
+ (if text
+ (message "Closes: %s" text))))))
(python-indent-line-1)
(setq python-indent-list (python-indentation-levels)
python-indent-list-length (length python-indent-list)
python-indent-index (1- python-indent-list-length)))))
+
+(defun python-block-end-p ()
+ "Non-nil if this is a line in a statement closing a block,
+or a blank line indented to where it would close a block."
+ (and (not (python-comment-line-p))
+ (or (python-close-block-statement-p t)
+ (< (current-indentation)
+ (save-excursion
+ (python-previous-statement)
+ (current-indentation))))))
+
+;; Fixme: Define an indent-region-function. It should probably leave
+;; lines alone if the indentation is already at one of the allowed
+;; levels. Otherwise, M-C-\ typically keeps indenting more deeply
+;; down a function.
;;;; Movement.
@@ -628,8 +663,7 @@ start of buffer."
"`end-of-defun-function' for Python.
Finds end of innermost nested class or method definition."
(let ((orig (point))
- (pattern (rx (and line-start (0+ space)
- (or "def" "class") space))))
+ (pattern (rx (and line-start (0+ space) (or "def" "class") space))))
;; Go to start of current block and check whether it's at top
;; level. If it is, and not a block start, look forward for
;; definition statement.
@@ -914,13 +948,20 @@ See `python-check-command' for the default."
(file-name-nondirectory name))))))))
(setq python-saved-check-command command)
(save-some-buffers (not compilation-ask-about-save) nil)
- (compilation-start command))
+ (let ((compilation-error-regexp-alist
+ (cons '("(\\([^,]+\\), line \\([0-9]+\\))" 1 2)
+ compilation-error-regexp-alist)))
+ (compilation-start command)))
;;;; Inferior mode stuff (following cmuscheme).
+;; Fixme: Make sure we can work with IPython.
+
(defcustom python-python-command "python"
"*Shell command to run Python interpreter.
-Any arguments can't contain whitespace."
+Any arguments can't contain whitespace.
+Note that IPython may not work properly; it must at least be used with the
+`-cl' flag, i.e. use `ipython -cl'."
:group 'python
:type 'string)
@@ -970,12 +1011,31 @@ et al.")
)
(defconst python-compilation-regexp-alist
+ ;; FIXME: maybe these should move to compilation-error-regexp-alist-alist.
`((,(rx (and line-start (1+ (any " \t")) "File \""
(group (1+ (not (any "\"<")))) ; avoid `<stdin>' &c
"\", line " (group (1+ digit))))
- 1 python-compilation-line-number))
+ 1 2)
+ (,(rx (and " in file " (group (1+ not-newline)) " on line "
+ (group (1+ digit))))
+ 1 2))
"`compilation-error-regexp-alist' for inferior Python.")
+(defvar inferior-python-mode-map
+ (let ((map (make-sparse-keymap)))
+ ;; This will inherit from comint-mode-map.
+ (define-key map "\C-c\C-l" 'python-load-file)
+ (define-key map "\C-c\C-z" 'python-switch-to-python) ;What for? --Stef
+ (define-key map "\C-c\C-v" 'python-check)
+ ;; Note that we _can_ still use these commands which send to the
+ ;; Python process even at the prompt iff we have a normal prompt,
+ ;; i.e. '>>> ' and not '... '. See the comment before
+ ;; python-send-region. Fixme: uncomment these if we address that.
+
+ ;; (define-key map [(meta ?\t)] 'python-complete-symbol)
+ ;; (define-key map "\C-c\C-f" 'python-describe-symbol)
+ map))
+
;; Fixme: This should inherit some stuff from python-mode, but I'm not
;; sure how much: at least some keybindings, like C-c C-f; syntax?;
;; font-locking, e.g. for triple-quoted strings?
@@ -999,15 +1059,13 @@ For running multiple processes in multiple buffers, see `python-buffer'.
:group 'python
(set-syntax-table python-mode-syntax-table)
(setq mode-line-process '(":%s"))
- ;; Fixme: Maybe install some python-mode bindings too.
- (define-key inferior-python-mode-map "\C-c\C-l" 'python-load-file)
- (define-key inferior-python-mode-map "\C-c\C-z" 'python-switch-to-python)
- (add-hook 'comint-input-filter-functions 'python-input-filter nil t)
+ (set (make-local-variable 'comint-input-filter) 'python-input-filter)
(add-hook 'comint-preoutput-filter-functions #'python-preoutput-filter
nil t)
;; Still required by `comint-redirect-send-command', for instance
;; (and we need to match things like `>>> ... >>> '):
- (set (make-local-variable 'comint-prompt-regexp) "^\\([>.]\\{3\\} \\)+")
+ (set (make-local-variable 'comint-prompt-regexp)
+ (rx (and line-start (1+ (and (repeat 3 (any ">.")) ?\ )))))
(set (make-local-variable 'compilation-error-regexp-alist)
python-compilation-regexp-alist)
(compilation-shell-minor-mode 1))
@@ -1018,15 +1076,9 @@ Default ignores all inputs of 0, 1, or 2 non-blank characters."
:type 'regexp
:group 'python)
-(defvar python-orig-start nil
- "Marker to the start of the region passed to the inferior Python.
-It can also be a filename.")
-
(defun python-input-filter (str)
"`comint-input-filter' function for inferior Python.
-Don't save anything for STR matching `inferior-python-filter-regexp'.
-Also resets variables for adjusting error messages."
- (setq python-orig-start nil)
+Don't save anything for STR matching `inferior-python-filter-regexp'."
(not (string-match inferior-python-filter-regexp str)))
;; Fixme: Loses with quoted whitespace.
@@ -1039,25 +1091,8 @@ Also resets variables for adjusting error messages."
(t (let ((pos (string-match "[^ \t]" string)))
(if pos (python-args-to-list (substring string pos))))))))
-(defun python-compilation-line-number (file col)
- "Return error descriptor of error found for FILE, column COL.
-Used as line-number hook function in `python-compilation-regexp-alist'."
- (let ((line (string-to-number (match-string 2))))
- (cons (point-marker)
- (if (and (markerp python-orig-start)
- (marker-buffer python-orig-start))
- (let ((start python-orig-start))
- (with-current-buffer (marker-buffer python-orig-start)
- (goto-char start)
- (forward-line (1- line))
- (point-marker)))
- (list (if (stringp python-orig-start)
- (list python-orig-start default-directory)
- file)
- line col)))))
-
(defvar python-preoutput-result nil
- "Data from output line last `_emacs_out' line seen by the preoutput filter.")
+ "Data from last `_emacs_out' line seen by the preoutput filter.")
(defvar python-preoutput-continuation nil
"If non-nil, funcall this when `python-preoutput-filter' sees `_emacs_ok'.")
@@ -1068,7 +1103,9 @@ Used as line-number hook function in `python-compilation-regexp-alist'."
;; `python-preoutput-continuation' if we get it.
(defun python-preoutput-filter (s)
"`comint-preoutput-filter-functions' function: ignore prompts not at bol."
- (cond ((and (string-match "\\`[.>]\\{3\\} \\'" s)
+ (cond ((and (string-match (rx (and string-start (repeat 3 (any ".>"))
+ " " string-end))
+ s)
(/= (let ((inhibit-field-text-motion t))
(line-beginning-position))
(point)))
@@ -1089,10 +1126,10 @@ Used as line-number hook function in `python-compilation-regexp-alist'."
CMD is the Python command to run. NOSHOW non-nil means don't show the
buffer automatically.
If there is a process already running in `*Python*', switch to
-that buffer. Interactively a prefix arg, allows you to edit the initial
-command line (default is the value of `python-command'); `-i' etc. args
-will be added to this as appropriate. Runs the hooks
-`inferior-python-mode-hook' (after the `comint-mode-hook' is run).
+that buffer. Interactively, a prefix arg allows you to edit the initial
+command line (default is `python-command'); `-i' etc. args will be added
+to this as appropriate. Runs the hook `inferior-python-mode-hook'
+\(after the `comint-mode-hook' is run).
\(Type \\[describe-mode] in the process buffer for a list of commands.)"
(interactive (list (if current-prefix-arg
(read-string "Run Python: " python-command)
@@ -1102,47 +1139,34 @@ will be added to this as appropriate. Runs the hooks
;; Fixme: Consider making `python-buffer' buffer-local as a buffer
;; (not a name) in Python buffers from which `run-python' &c is
;; invoked. Would support multiple processes better.
- (unless (comint-check-proc "*Python*")
- (let ((cmdlist (append (python-args-to-list cmd) '("-i"))))
+ (unless (comint-check-proc python-buffer)
+ (let ((cmdlist (append (python-args-to-list cmd) '("-i")))
+ (process-environment ; to import emacs.py
+ (push (concat "PYTHONPATH=" data-directory)
+ process-environment)))
(set-buffer (apply 'make-comint "Python" (car cmdlist) nil
- (cdr cmdlist))))
+ (cdr cmdlist)))
+ (setq python-buffer "*Python*"))
(inferior-python-mode)
;; Load function defintions we need.
;; Before the preoutput function was used, this was done via -c in
;; cmdlist, but that loses the banner and doesn't run the startup
- ;; file.
- (python-send-string "\
-def _emacs_execfile (file): # execute file and remove it
- from os import remove
- try: execfile (file, globals (), globals ())
- finally: remove (file)
-
-def _emacs_args (name): # get arglist of name for eldoc &c
- import inspect
- parts = name.split ('.')
- if len (parts) > 1:
- try: exec 'import ' + parts[0]
- except: return None
- try: exec 'func='+name # lose if name is keyword or undefined
- except: return None
- if inspect.isbuiltin (func):
- doc = func.__doc__
- if doc.find (' ->') != -1:
- print '_emacs_out', doc.split (' ->')[0]
- elif doc.find ('\\n') != -1:
- print '_emacs_out', doc.split ('\\n')[0]
- return None
- if inspect.ismethod (func): func = func.im_func
- if not inspect.isfunction (func):
- return None
- (args, varargs, varkw, defaults) = inspect.getargspec (func)
- print '_emacs_out', func.__name__+inspect.formatargspec (args, varargs, varkw, defaults)
-
-print '_emacs_ok'"))
- (unless noshow (pop-to-buffer (setq python-buffer "*Python*"))))
+ ;; file. The code might be inline here, but there's enough that it
+ ;; seems worth putting in a separate file, and it's probably cleaner
+ ;; to put it in a module.
+ (python-send-string "import emacs"))
+ (unless noshow (pop-to-buffer python-buffer)))
+
+;; Fixme: We typically lose if the inferior isn't in the normal REPL,
+;; e.g. prompt is `help> '. Probably raise an error if the form of
+;; the prompt is unexpected; actually, it needs to be `>>> ', not
+;; `... ', i.e. we're not inputting a block &c. However, this may not
+;; be the place to do it, e.g. we might actually want to send commands
+;; having set up such a state.
(defun python-send-command (command)
"Like `python-send-string' but resets `compilation-minor-mode'."
+ (goto-char (point-max))
(let ((end (marker-position (process-mark (python-proc)))))
(compilation-forget-errors)
(python-send-string command)
@@ -1154,35 +1178,37 @@ print '_emacs_ok'"))
;; The region is evaluated from a temporary file. This avoids
;; problems with blank lines, which have different semantics
;; interactively and in files. It also saves the inferior process
- ;; buffer filling up with interpreter prompts. We need a function
- ;; to remove the temporary file when it has been evaluated, which
- ;; unfortunately means using a not-quite pristine interpreter
- ;; initially. Unfortunately we also get tracebacks which look like:
- ;;
- ;; >>> Traceback (most recent call last):
- ;; File "<stdin>", line 1, in ?
- ;; File "<string>", line 4, in _emacs_execfile
- ;; File "/tmp/py7734RSB", line 11
+ ;; buffer filling up with interpreter prompts. We need a Python
+ ;; function to remove the temporary file when it has been evaluated
+ ;; (though we could probably do it in Lisp with a Comint output
+ ;; filter). This function also catches exceptions and truncates
+ ;; tracebacks not to mention the frame of the function itself.
;;
;; The compilation-minor-mode parsing takes care of relating the
- ;; reference to the temporary file to the source. Fixme:
- ;; comint-filter the first two lines of the traceback?
+ ;; reference to the temporary file to the source.
+ ;;
+ ;; Fixme: Write a `coding' header to the temp file if the region is
+ ;; non-ASCII.
(interactive "r")
(let* ((f (make-temp-file "py"))
- (command (format "_emacs_execfile(%S)" f))
+ (command (format "emacs.eexecfile(%S)" f))
(orig-start (copy-marker start)))
- (if (save-excursion
- (goto-char start)
- (/= 0 (current-indentation))) ; need dummy block
- (write-region "if True:\n" nil f nil 'nomsg))
+ (when (save-excursion
+ (goto-char start)
+ (/= 0 (current-indentation))) ; need dummy block
+ (save-excursion
+ (goto-char orig-start)
+ ;; Wrong if we had indented code at buffer start.
+ (set-marker orig-start (line-beginning-position 0)))
+ (write-region "if True:\n" nil f nil 'nomsg))
(write-region start end f t 'nomsg)
- (when python-buffer
+ (let ((proc (python-proc))) ;Make sure we're running a process.
(with-current-buffer python-buffer
- (set (make-local-variable 'python-orig-start) orig-start)
- (let ((comint-input-filter-functions
- ;; Don't reset python-orig-start.
- (remq 'python-input-filter comint-input-filter-functions)))
- (python-send-command command))))))
+ (python-send-command command)
+ ;; Tell compile.el to redirect error locations in file `f' to
+ ;; positions past marker `orig-start'. It has to be done *after*
+ ;; python-send-command's call to compilation-forget-errors.
+ (compilation-fake-loc orig-start f)))))
(defun python-send-string (string)
"Evaluate STRING in inferior Python process."
@@ -1195,6 +1221,8 @@ print '_emacs_ok'"))
(interactive)
(python-send-region (point-min) (point-max)))
+;; Fixme: Try to define the function or class within the relevant
+;; module, not just at top level.
(defun python-send-defun ()
"Send the current defun (class or method) to the inferior Python process."
(interactive)
@@ -1241,11 +1269,11 @@ function location information for debugging, and supports users of
module-qualified names."
(interactive (comint-get-source "Load Python file: " python-prev-dir/file
python-source-modes
- t)) ; because execfile needs exact name
- (comint-check-source file-name) ; Check to see if buffer needs saved.
+ t)) ; because execfile needs exact name
+ (comint-check-source file-name) ; Check to see if buffer needs saving.
(setq python-prev-dir/file (cons (file-name-directory file-name)
(file-name-nondirectory file-name)))
- (when python-buffer
+ (let ((proc (python-proc))) ;Make sure we have a process.
(with-current-buffer python-buffer
;; Fixme: I'm not convinced by this logic from python-mode.el.
(python-send-command
@@ -1253,19 +1281,22 @@ module-qualified names."
;; Fixme: make sure the directory is in the path list
(let ((module (file-name-sans-extension
(file-name-nondirectory file-name))))
- (format "\
-if globals().has_key(%S): reload(%s)
-else: import %s
-" module module module))
- (format "execfile('%s')" file-name))))))
+ (format "emacs.eimport(%S,%S)"
+ module (file-name-directory file-name)))
+ (format "execfile(%S)" file-name)))
+ (message "%s loaded" file-name))))
-;; Fixme: Should this start a process if there isn't one? (Unlike cmuscheme.)
+;; Fixme: If we need to start the process, wait until we've got the OK
+;; from the startup.
(defun python-proc ()
- "Return the current Python process. See variable `python-buffer'."
- (let ((proc (get-buffer-process (if (eq major-mode 'inferior-python-mode)
- (current-buffer)
- python-buffer))))
- (or proc (error "No current process. See variable `python-buffer'"))))
+ "Return the current Python process.
+See variable `python-buffer'. Starts a new process if necessary."
+ (or (if python-buffer
+ (get-buffer-process (if (eq major-mode 'inferior-python-mode)
+ (current-buffer)
+ python-buffer)))
+ (progn (run-python nil t)
+ (python-proc))))
;;;; Context-sensitive help.
@@ -1277,33 +1308,46 @@ else: import %s
"Syntax table giving `.' symbol syntax.
Otherwise inherits from `python-mode-syntax-table'.")
+(defvar view-return-to-alist)
+
;; Fixme: Should this actually be used instead of info-look, i.e. be
-;; bound to C-h S?
+;; bound to C-h S? Can we use other pydoc stuff before python 2.2?
(defun python-describe-symbol (symbol)
- "Get help on SYMBOL using `pydoc'.
-Interactively, prompt for symbol."
- ;; Note that we do this in the inferior process, not a separate one to
+ "Get help on SYMBOL using `help'.
+Interactively, prompt for symbol.
+
+Symbol may be anything recognized by the interpreter's `help' command --
+e.g. `CALLS' -- not just variables in scope.
+This only works for Python version 2.2 or newer since earlier interpreters
+don't support `help'."
+ ;; Note that we do this in the inferior process, not a separate one, to
;; ensure the environment is appropriate.
(interactive
(let ((symbol (with-syntax-table python-dotty-syntax-table
(current-word)))
- (enable-recursive-minibuffers t)
- val)
- (setq val (read-string (if symbol
- (format "Describe symbol (default %s): "
- symbol)
- "Describe symbol: ")
- nil nil symbol))
- (list (or val symbol))))
+ (enable-recursive-minibuffers t))
+ (list (read-string (if symbol
+ (format "Describe symbol (default %s): " symbol)
+ "Describe symbol: ")
+ nil nil symbol))))
(if (equal symbol "") (error "No symbol"))
(let* ((func `(lambda ()
- (comint-redirect-send-command (format "help(%S)\n" ,symbol)
+ (comint-redirect-send-command (format "emacs.ehelp(%S)\n"
+ ,symbol)
"*Help*" nil))))
;; Ensure we have a suitable help buffer.
- (let (temp-buffer-show-hook) ; avoid xref stuff
- (with-output-to-temp-buffer "*Help*"
+ ;; Fixme: Maybe process `Related help topics' a la help xrefs and
+ ;; allow C-c C-f in help buffer.
+ (let ((temp-buffer-show-hook ; avoid xref stuff
+ (lambda ()
+ (toggle-read-only 1)
+ (setq view-return-to-alist
+ (list (cons (selected-window) help-return-method))))))
+ (help-setup-xref (list 'python-describe-symbol symbol))
+ (with-output-to-temp-buffer (help-buffer)
(with-current-buffer standard-output
- (set (make-local-variable 'comint-redirect-subvert-readonly) t))))
+ (set (make-local-variable 'comint-redirect-subvert-readonly) t)
+ (print-help-return-message))))
(if (and python-buffer (get-buffer python-buffer))
(with-current-buffer python-buffer
(funcall func))
@@ -1312,6 +1356,15 @@ Interactively, prompt for symbol."
(add-to-list 'debug-ignored-errors "^No symbol")
+(defun python-send-receive (string)
+ "Send STRING to inferior Python (if any) and return result.
+The result is what follows `_emacs_out' in the output (or nil)."
+ (let ((proc (python-proc)))
+ (python-send-string string)
+ (setq python-preoutput-result nil)
+ (accept-process-output proc 5)
+ python-preoutput-result))
+
;; Fixme: try to make it work with point in the arglist. Also, is
;; there anything reasonable we can do with random methods?
;; (Currently only works with functions.)
@@ -1320,14 +1373,9 @@ Interactively, prompt for symbol."
Only works when point is in a function name, not its arglist, for instance.
Assumes an inferior Python is running."
(let ((symbol (with-syntax-table python-dotty-syntax-table
- (current-word)))
- (proc (and python-buffer (python-proc))))
- (when (and proc symbol)
- (python-send-string
- (format "_emacs_args(%S)" symbol))
- (setq python-preoutput-result nil)
- (accept-process-output proc 1)
- python-preoutput-result)))
+ (current-word))))
+ (when symbol
+ (python-send-receive (format "emacs.eargs(%S)" symbol)))))
;;;; Info-look functionality.
@@ -1530,11 +1578,97 @@ Uses `python-beginning-of-block', `python-end-of-block'."
(python-end-of-block)
(exchange-point-and-mark))
+;;;; Completion.
+
+(defun python-symbol-completions (symbol)
+ "Return a list of completions of the string SYMBOL from Python process.
+The list is sorted."
+ (when symbol
+ (let ((completions
+ (condition-case ()
+ (car (read-from-string (python-send-receive
+ (format "emacs.complete(%S)" symbol))))
+ (error nil))))
+ (sort
+ ;; We can get duplicates from the above -- don't know why.
+ (delete-dups completions)
+ #'string<))))
+
+(defun python-partial-symbol ()
+ "Return the partial symbol before point (for completion)."
+ (let ((end (point))
+ (start (save-excursion
+ (and (re-search-backward
+ (rx (and (or buffer-start (regexp "[^[:alnum:]._]"))
+ (group (1+ (regexp "[[:alnum:]._]")))
+ point))
+ nil t)
+ (match-beginning 1)))))
+ (if start (buffer-substring-no-properties start end))))
+
+;; Fixme: We should have an abstraction of this sort of thing in the
+;; core.
+(defun python-complete-symbol ()
+ "Perform completion on the Python symbol preceding point.
+Repeating the command scrolls the completion window."
+ (interactive)
+ (let ((window (get-buffer-window "*Completions*")))
+ (if (and (eq last-command this-command)
+ window (window-live-p window) (window-buffer window)
+ (buffer-name (window-buffer window)))
+ (with-current-buffer (window-buffer window)
+ (if (pos-visible-in-window-p (point-max) window)
+ (set-window-start window (point-min))
+ (save-selected-window
+ (select-window window)
+ (scroll-up))))
+ ;; Do completion.
+ (let* ((end (point))
+ (symbol (python-partial-symbol))
+ (completions (python-symbol-completions symbol))
+ (completion (if completions
+ (try-completion symbol completions))))
+ (when symbol
+ (cond ((eq completion t))
+ ((null completion)
+ (message "Can't find completion for \"%s\"" symbol)
+ (ding))
+ ((not (string= symbol completion))
+ (delete-region (- end (length symbol)) end)
+ (insert completion))
+ (t
+ (message "Making completion list...")
+ (with-output-to-temp-buffer "*Completions*"
+ (display-completion-list completions))
+ (message "Making completion list...%s" "done"))))))))
+
+(eval-when-compile (require 'hippie-exp))
+
+(defun python-try-complete (old)
+ "Completion function for Python for use with `hippie-expand'."
+ (when (eq major-mode 'python-mode) ; though we only add it locally
+ (unless old
+ (let ((symbol (python-partial-symbol)))
+ (he-init-string (- (point) (length symbol)) (point))
+ (if (not (he-string-member he-search-string he-tried-table))
+ (push he-search-string he-tried-table))
+ (setq he-expand-list
+ (and symbol (python-symbol-completions symbol)))))
+ (while (and he-expand-list
+ (he-string-member (car he-expand-list) he-tried-table))
+ (pop he-expand-list))
+ (if he-expand-list
+ (progn
+ (he-substitute-string (pop he-expand-list))
+ t)
+ (if old (he-reset-string))
+ nil)))
+
;;;; Modes.
(defvar outline-heading-end-regexp)
(defvar eldoc-print-current-symbol-info-function)
-(defvar python-mode-running)
+
;;;###autoload
(define-derived-mode python-mode fundamental-mode "Python"
"Major mode for editing Python files.
@@ -1576,11 +1710,10 @@ lines count as headers.
))
(set (make-local-variable 'parse-sexp-lookup-properties) t)
(set (make-local-variable 'comment-start) "# ")
- ;; Fixme: define a comment-indent-function?
+ (set (make-local-variable 'comment-indent-function) #'python-comment-indent)
(set (make-local-variable 'indent-line-function) #'python-indent-line)
(set (make-local-variable 'paragraph-start) "\\s-*$")
- (set (make-local-variable 'fill-paragraph-function)
- 'python-fill-paragraph)
+ (set (make-local-variable 'fill-paragraph-function) 'python-fill-paragraph)
(set (make-local-variable 'require-final-newline) t)
(set (make-local-variable 'add-log-current-defun-function)
#'python-current-defun)
@@ -1598,6 +1731,9 @@ lines count as headers.
#'python-eldoc-function)
(add-hook 'eldoc-mode-hook
'(lambda () (run-python 0 t)) nil t) ; need it running
+ (if (featurep 'hippie-exp)
+ (set (make-local-variable 'hippie-expand-try-functions-list)
+ (cons 'python-try-complete hippie-expand-try-functions-list)))
(unless font-lock-mode (font-lock-mode 1))
(when python-guess-indent (python-guess-indent))
(set (make-local-variable 'python-command) python-python-command)
diff --git a/lisp/progmodes/sql.el b/lisp/progmodes/sql.el
index 420b5f226b0..0e0d89b07e1 100644
--- a/lisp/progmodes/sql.el
+++ b/lisp/progmodes/sql.el
@@ -4,7 +4,7 @@
;; Author: Alex Schroeder <alex@gnu.org>
;; Maintainer: Michael Mauger <mmaug@yahoo.com>
-;; Version: 2.0.0
+;; Version: 2.0.1
;; Keywords: comm languages processes
;; URL: http://savannah.gnu.org/cgi-bin/viewcvs/emacs/emacs/lisp/progmodes/sql.el
;; URL: http://www.emacswiki.org/cgi-bin/wiki.pl?SqlMode
@@ -200,8 +200,11 @@
;; Gregor Zych <zych@pool.informatik.rwth-aachen.de>
;; nino <nino@inform.dk>
;; Berend de Boer <berend@pobox.com>
-;; Michael Mauger <mmaug@yahoo.com>
;; Adam Jenkins <adam@thejenkins.org>
+;; Michael Mauger <mmaug@yahoo.com> -- improved product support
+;; Drew Adams <drew.adams@oracle.com> -- Emacs 20 support
+;; Harald Maier <maierh@myself.com> -- sql-send-string
+;; Stefan Monnier <monnier@iro.umontreal.ca> -- font-lock corrections
@@ -693,18 +696,6 @@ Starts `sql-interactive-mode' after doing some setup."
;;; Variables which do not need customization
-(defvar sql-xemacs-p
- (string-match "XEmacs\\|Lucid" emacs-version)
- "Is this a non-GNU Emacs?")
-
-(defvar sql-emacs19-p
- (string-match "GNU Emacs 19" emacs-version)
- "Is this a GNU Emacs 19?")
-
-(defvar sql-emacs20-p
- (string-match "20" emacs-version)
- "Is this a GNU Emacs 20?")
-
(defvar sql-user-history nil
"History of usernames used.")
@@ -876,9 +867,7 @@ Based on `comint-mode-map'.")
(modify-syntax-entry ?/ ". 14" table)
(modify-syntax-entry ?* ". 23" table)
;; double-dash starts comment
- (if sql-xemacs-p
- (modify-syntax-entry ?- ". 56" table)
- (modify-syntax-entry ?- ". 12b" table))
+ (modify-syntax-entry ?- ". 12b" table)
;; newline and formfeed end coments
(modify-syntax-entry ?\n "> b" table)
(modify-syntax-entry ?\f "> b" table)
@@ -905,25 +894,6 @@ The pattern matches the name in a CREATE, DROP or ALTER
statement. The format of variable should be a valid
`font-lock-keywords' entry.")
-(defvar sql-builtin-face
- (if sql-xemacs-p
- ;; XEmacs doesn't have the builtin face
- 'font-lock-preprocessor-face
- ;; GNU Emacs 19 doesn't either
- (if sql-emacs19-p
- 'font-lock-keyword-face
- ;; Emacs 2x
- 'font-lock-builtin-face))
- "Builtin face for font-lock in SQL mode.")
-
-(defvar sql-doc-face
- (if (or sql-xemacs-p
- sql-emacs19-p
- sql-emacs20-p)
- 'font-lock-string-face
- 'font-lock-doc-face)
- "Documentation face for font-lock in SQL mode.")
-
(defmacro sql-keywords-re (&rest keywords)
"Compile-time generation of regexp matching any one of KEYWORDS."
`(eval-when-compile
@@ -1020,7 +990,7 @@ statement. The format of variable should be a valid
`((,ansi-non-reserved . font-lock-keyword-face)
(,ansi-reserved . font-lock-keyword-face)
- (,ansi-funcs . ,sql-builtin-face)
+ (,ansi-funcs . font-lock-builtin-face)
(,ansi-types . font-lock-type-face)))
"ANSI SQL keywords used by font-lock.
@@ -1230,11 +1200,11 @@ add functions and PL/SQL keywords.")
"\\b.*$"
))))
- `((,sqlplus-commands . ,sql-doc-face)
- (,oracle-functions . ,sql-builtin-face)
+ `((,sqlplus-commands . font-lock-doc-face)
+ (,oracle-functions . font-lock-builtin-face)
(,oracle-keywords . font-lock-keyword-face)
(,oracle-types . font-lock-type-face)
- (,plsql-functions . ,sql-builtin-face)
+ (,plsql-functions . font-lock-builtin-face)
(,plsql-keywords . font-lock-keyword-face)
(,plsql-type . font-lock-type-face)
(,plsql-warning . font-lock-warning-face)))
@@ -1323,7 +1293,7 @@ to add functions and PL/SQL keywords.")
"timestamp" "varchar" "varying" "void" "zone"
)))
- `((,pg-funcs . ,sql-builtin-face)
+ `((,pg-funcs . font-lock-builtin-face)
(,pg-reserved . font-lock-keyword-face)
(,pg-types . font-lock-type-face)))
@@ -1404,7 +1374,7 @@ you define your own sql-mode-postgres-font-lock-keywords.")
`((,linter-keywords . font-lock-keyword-face)
(,linter-reserved . font-lock-keyword-face)
- (,linter-functions . ,sql-builtin-face)
+ (,linter-functions . font-lock-builtin-face)
(,linter-types . font-lock-type-face)))
"Linter SQL keywords used by font-lock.
@@ -1507,9 +1477,9 @@ function `regexp-opt'.")
) t)
"\\)\\)\\|go\\s-*\\|use\\s-+\\|setuser\\s-+\\|dbcc\\s-+\\).*$"))))
- `((,ms-commands . ,sql-doc-face)
+ `((,ms-commands . font-lock-doc-face)
(,ms-reserved . font-lock-keyword-face)
- (,ms-functions . ,sql-builtin-face)
+ (,ms-functions . font-lock-builtin-face)
(,ms-vars . font-lock-variable-name-face)
(,ms-types . font-lock-type-face)))
@@ -1626,7 +1596,7 @@ you define your own sql-mode-solid-font-lock-keywords.")
"zerofill"
)))
- `((,mysql-funcs . ,sql-builtin-face)
+ `((,mysql-funcs . font-lock-builtin-face)
(,mysql-keywords . font-lock-keyword-face)
(,mysql-types . font-lock-type-face)))
@@ -1687,17 +1657,36 @@ the product-specific keywords and syntax-alists defined in
;; Get the product-specific keywords.
(setq sql-mode-font-lock-keywords
(append
- (eval (sql-product-feature :font-lock))
+ (unless (eq sql-product 'ansi)
+ (eval (sql-product-feature :font-lock)))
+ ;; Always highlight ANSI keywords
(eval (sql-product-feature :font-lock 'ansi))
+ ;; Fontify object names in CREATE, DROP and ALTER DDL
+ ;; statements
(list sql-mode-font-lock-object-name)))
- ;; Setup font-lock. (What is the minimum we should have to do
- ;; here?)
- (setq font-lock-set-defaults nil
- font-lock-keywords sql-mode-font-lock-keywords
- font-lock-defaults (list 'sql-mode-font-lock-keywords
+ ;; Setup font-lock. Force re-parsing of `font-lock-defaults'.
+ (set (make-local-variable 'font-lock-set-defaults) nil)
+ (setq font-lock-defaults (list 'sql-mode-font-lock-keywords
keywords-only t syntax-alist))
+ ;; Force font lock to reinitialize if it is already on
+ ;; Otherwise, we can wait until it can be started.
+ (when (and (fboundp 'font-lock-mode)
+ font-lock-mode)
+ (font-lock-mode-internal nil)
+ (font-lock-mode-internal t))
+
+ (add-hook 'font-lock-mode-hook
+ (lambda ()
+ ;; Provide defaults for new font-lock faces.
+ (defvar font-lock-builtin-face
+ (if (boundp 'font-lock-preprocessor-face)
+ font-lock-preprocessor-face
+ font-lock-keyword-face))
+ (defvar font-lock-doc-face font-lock-string-face))
+ nil t)
+
;; Setup imenu; it needs the same syntax-alist.
(when imenu
(setq imenu-syntax-alist syntax-alist))))
@@ -1744,11 +1733,6 @@ selected."
;; Setup font-lock
(sql-product-font-lock nil t)
- ;; Force fontification, if its enabled.
- (if (and (boundp 'font-lock-mode)
- font-lock-mode)
- (font-lock-fontify-buffer))
-
;; Set the mode name to include the product.
(setq mode-name (concat "SQL[" (prin1-to-string sql-product) "]"))))