Commit f12b30ad authored by Ivan Andrus's avatar Ivan Andrus

Added cython-beginning-of-defun and cython-end-of-defun

parent 5b6ec593
......@@ -76,6 +76,153 @@ It will be passed to `format' with `buffer-file-name' as the only other argument
:group 'cython
:type 'string)
;; Some functions defined differently in the different python modes
(defun cython-comment-line-p ()
"Return non-nil if current line is a comment."
(save-excursion
(back-to-indentation)
(eq ?# (char-after (point)))))
(defun cython-in-string/comment ()
"Return non-nil if point is in a comment or string."
(nth 8 (syntax-ppss)))
(defalias 'cython-beginning-of-statement
(cond
;; python-mode.el
((fboundp 'py-beginning-of-statement)
'py-beginning-of-statement)
;; old python.el
((fboundp 'python-beginning-of-statement)
'python-beginning-of-statement)
;; new python.el
((fboundp 'python-nav-beginning-of-statement)
'python-nav-beginning-of-statement)
(t (error "Couldn't find implementation for `cython-beginning-of-statement'"))))
(defalias 'cython-beginning-of-block
(cond
;; python-mode.el
((fboundp 'py-beginning-of-block)
'py-beginning-of-block)
;; old python.el
((fboundp 'python-beginning-of-block)
'python-beginning-of-block)
;; new python.el
((fboundp 'python-nav-beginning-of-block)
'python-nav-beginning-of-block)
(t (error "Couldn't find implementation for `cython-beginning-of-block'"))))
(defalias 'cython-end-of-statement
(cond
;; python-mode.el
((fboundp 'py-end-of-statement)
'py-end-of-statement)
;; old python.el
((fboundp 'python-end-of-statement)
'python-end-of-statement)
;; new python.el
((fboundp 'python-nav-end-of-statement)
'python-nav-end-of-statement)
(t (error "Couldn't find implementation for `cython-end-of-statement'"))))
(defun cython-open-block-statement-p (&optional bos)
"Return non-nil if statement at point opens a Cython block.
BOS non-nil means point is known to be at beginning of statement."
(save-excursion
(unless bos (cython-beginning-of-statement))
(looking-at (rx (and (or "if" "else" "elif" "while" "for" "def" "cdef" "cpdef"
"class" "try" "except" "finally" "with"
"EXAMPLES:" "TESTS:" "INPUT:" "OUTPUT:")
symbol-end)))))
(defun cython-beginning-of-defun ()
"`beginning-of-defun-function' for Cython.
Finds beginning of innermost nested class or method definition.
Returns the name of the definition found at the end, or nil if
reached start of buffer."
(let ((ci (current-indentation))
(def-re (rx line-start (0+ space) (or "def" "cdef" "cpdef" "class") (1+ space)
(group (1+ (or word (syntax symbol))))))
found lep) ;; def-line
(if (cython-comment-line-p)
(setq ci most-positive-fixnum))
(while (and (not (bobp)) (not found))
;; Treat bol at beginning of function as outside function so
;; that successive C-M-a makes progress backwards.
;;(setq def-line (looking-at def-re))
(unless (bolp) (end-of-line))
(setq lep (line-end-position))
(if (and (re-search-backward def-re nil 'move)
;; Must be less indented or matching top level, or
;; equally indented if we started on a definition line.
(let ((in (current-indentation)))
(or (and (zerop ci) (zerop in))
(= lep (line-end-position)) ; on initial line
;; Not sure why it was like this -- fails in case of
;; last internal function followed by first
;; non-def statement of the main body.
;;(and def-line (= in ci))
(= in ci)
(< in ci)))
(not (cython-in-string/comment)))
(setq found t)))))
(defun cython-end-of-defun ()
"`end-of-defun-function' for Cython.
Finds end of innermost nested class or method definition."
(let ((orig (point))
(pattern (rx line-start (0+ space) (or "def" "cdef" "cpdef" "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.
(when (cython-comment-line-p)
(end-of-line)
(forward-comment most-positive-fixnum))
(when (not (cython-open-block-statement-p))
(cython-beginning-of-block))
(if (zerop (current-indentation))
(unless (cython-open-block-statement-p)
(while (and (re-search-forward pattern nil 'move)
(cython-in-string/comment))) ; just loop
(unless (eobp)
(beginning-of-line)))
;; Don't move before top-level statement that would end defun.
(end-of-line)
(beginning-of-defun))
;; If we got to the start of buffer, look forward for
;; definition statement.
(when (and (bobp) (not (looking-at (rx (or "def" "cdef" "cpdef" "class")))))
(while (and (not (eobp))
(re-search-forward pattern nil 'move)
(cython-in-string/comment)))) ; just loop
;; We're at a definition statement (or end-of-buffer).
;; This is where we should have started when called from end-of-defun
(unless (eobp)
(let ((block-indentation (current-indentation)))
(python-nav-end-of-statement)
(while (and (forward-line 1)
(not (eobp))
(or (and (> (current-indentation) block-indentation)
(or (cython-end-of-statement) t))
;; comment or empty line
(looking-at (rx (0+ space) (or eol "#"))))))
(forward-comment -1))
;; Count trailing space in defun (but not trailing comments).
(skip-syntax-forward " >")
(unless (eobp) ; e.g. missing final newline
(beginning-of-line)))
;; Catch pathological cases like this, where the beginning-of-defun
;; skips to a definition we're not in:
;; if ...:
;; ...
;; else:
;; ... # point here
;; ...
;; def ...
(if (< (point) orig)
(goto-char (point-max)))))
;;;###autoload
(define-derived-mode cython-mode python-mode "Cython"
"Major mode for Cython development, derived from Python mode.
......@@ -87,6 +234,10 @@ It will be passed to `format' with `buffer-file-name' as the only other argument
(rx (* space) (or "class" "def" "cdef" "cpdef" "elif" "else" "except" "finally"
"for" "if" "try" "while" "with")
symbol-end))
(set (make-local-variable 'beginning-of-defun-function)
#'cython-beginning-of-defun)
(set (make-local-variable 'end-of-defun-function)
#'cython-end-of-defun)
(set (make-local-variable 'compile-command)
(format cython-default-compile-format (shell-quote-argument buffer-file-name)))
(add-to-list (make-local-variable 'compilation-finish-functions)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment