📄 perl-mode.el
字号:
(setq lsexp (point)) (setq bof (perl-beginning-of-function)) (goto-char oldpnt) (setq delta (perl-indent-line "\f\\|;?#" bof)) (and perl-tab-to-comment (= oldpnt (point)) ; done if point moved (if (listp delta) ; if line starts in a quoted string (setq lsexp (or (nth 2 delta) bof)) (= delta 0)) ; done if indenting occurred (let (eol state) (end-of-line) (setq eol (point)) (if (= (char-after bof) ?=) (if (= oldpnt eol) (message "In a format statement")) (setq state (parse-partial-sexp lsexp eol)) (if (nth 3 state) (if (= oldpnt eol) ; already at eol in a string (message "In a string which starts with a %c." (nth 3 state))) (if (not (nth 4 state)) (if (= oldpnt eol) ; no comment, create one? (indent-for-comment)) (beginning-of-line) (if (re-search-forward comment-start-skip eol 'move) (if (eolp) (progn ; kill existing comment (goto-char (match-beginning 0)) (skip-chars-backward " \t") (kill-region (point) eol)) (if (or (< oldpnt (point)) (= oldpnt eol)) (indent-for-comment) ; indent existing comment (end-of-line))) (if (/= oldpnt eol) (end-of-line) (message "Use backslash to quote # characters.") (ding t))))))))))))(defun perl-indent-line (&optional nochange parse-start) "Indent current line as Perl code. Return the amount the indentation changed by, or (parse-state) if line starts in a quoted string." (let ((case-fold-search nil) (pos (- (point-max) (point))) (bof (or parse-start (save-excursion (perl-beginning-of-function)))) beg indent shift-amt) (beginning-of-line) (setq beg (point)) (setq shift-amt (cond ((= (char-after bof) ?=) 0) ((listp (setq indent (calculate-perl-indent bof))) indent) ((looking-at (or nochange perl-nochange)) 0) (t (skip-chars-forward " \t\f") (cond ((looking-at "\\(\\w\\|\\s_\\)+:") (setq indent (max 1 (+ indent perl-label-offset)))) ((= (following-char) ?}) (setq indent (- indent perl-indent-level))) ((= (following-char) ?{) (setq indent (+ indent perl-brace-offset)))) (- indent (current-column))))) (skip-chars-forward " \t\f") (if (and (numberp shift-amt) (/= 0 shift-amt)) (progn (delete-region beg (point)) (indent-to indent))) ;; If initial point was within line's indentation, ;; position after the indentation. Else stay at same point in text. (if (> (- (point-max) pos) (point)) (goto-char (- (point-max) pos))) shift-amt))(defun calculate-perl-indent (&optional parse-start) "Return appropriate indentation for current line as Perl code.In usual case returns an integer: the column to indent to.Returns (parse-state) if line starts inside a string." (save-excursion (beginning-of-line) (let ((indent-point (point)) (case-fold-search nil) (colon-line-end 0) state containing-sexp) (if parse-start ;used to avoid searching (goto-char parse-start) (perl-beginning-of-function)) (while (< (point) indent-point) ;repeat until right sexp (setq parse-start (point)) (setq state (parse-partial-sexp (point) indent-point 0)); state = (depth_in_parens innermost_containing_list last_complete_sexp; string_terminator_or_nil inside_commentp following_quotep; minimum_paren-depth_this_scan); Parsing stops if depth in parentheses becomes equal to third arg. (setq containing-sexp (nth 1 state))) (cond ((nth 3 state) state) ; In a quoted string? ((null containing-sexp) ; Line is at top level. (skip-chars-forward " \t\f") (if (= (following-char) ?{) 0 ; move to beginning of line if it starts a function body ;; indent a little if this is a continuation line (perl-backward-to-noncomment) (if (or (bobp) (memq (preceding-char) '(?\; ?\}))) 0 perl-continued-statement-offset))) ((/= (char-after containing-sexp) ?{) ;; line is expression, not statement: ;; indent to just after the surrounding open. (goto-char (1+ containing-sexp)) (current-column)) (t ;; Statement level. Is it a continuation or a new statement? ;; Find previous non-comment character. (perl-backward-to-noncomment) ;; Back up over label lines, since they don't ;; affect whether our line is a continuation. (while (or (eq (preceding-char) ?\,) (and (eq (preceding-char) ?:) (memq (char-syntax (char-after (- (point) 2))) '(?w ?_)))) (if (eq (preceding-char) ?\,) (perl-backward-to-start-of-continued-exp containing-sexp)) (beginning-of-line) (perl-backward-to-noncomment)) ;; Now we get the answer. (if (not (memq (preceding-char) '(?\; ?\} ?\{))) ;; This line is continuation of preceding line's statement; ;; indent perl-continued-statement-offset more than the ;; previous line of the statement. (progn (perl-backward-to-start-of-continued-exp containing-sexp) (+ perl-continued-statement-offset (current-column) (if (save-excursion (goto-char indent-point) (looking-at "[ \t]*{")) perl-continued-brace-offset 0))) ;; This line starts a new statement. ;; Position at last unclosed open. (goto-char containing-sexp) (or ;; If open paren is in col 0, close brace is special (and (bolp) (save-excursion (goto-char indent-point) (looking-at "[ \t]*}")) perl-indent-level) ;; Is line first statement after an open-brace? ;; If no, find that first statement and indent like it. (save-excursion (forward-char 1) ;; Skip over comments and labels following openbrace. (while (progn (skip-chars-forward " \t\f\n") (cond ((looking-at ";?#") (forward-line 1) t) ((looking-at "\\(\\w\\|\\s_\\)+:") (save-excursion (end-of-line) (setq colon-line-end (point))) (search-forward ":"))))) ;; The first following code counts ;; if it is before the line we want to indent. (and (< (point) indent-point) (if (> colon-line-end (point)) (- (current-indentation) perl-label-offset) (current-column)))) ;; If no previous statement, ;; indent it relative to line brace is on. ;; For open paren in column zero, don't let statement ;; start there too. If perl-indent-level is zero, ;; use perl-brace-offset + perl-continued-statement-offset ;; For open-braces not the first thing in a line, ;; add in perl-brace-imaginary-offset. (+ (if (and (bolp) (zerop perl-indent-level)) (+ perl-brace-offset perl-continued-statement-offset) perl-indent-level) ;; Move back over whitespace before the openbrace. ;; If openbrace is not first nonwhite thing on the line, ;; add the perl-brace-imaginary-offset. (progn (skip-chars-backward " \t") (if (bolp) 0 perl-brace-imaginary-offset)) ;; If the openbrace is preceded by a parenthesized exp, ;; move to the beginning of that; ;; possibly a different line (progn (if (eq (preceding-char) ?\)) (forward-sexp -1)) ;; Get initial indentation of the line we are on. (current-indentation))))))))))(defun perl-backward-to-noncomment () "Move point backward to after the first non-white-space, skipping comments." (interactive) (let (opoint stop) (while (not stop) (setq opoint (point)) (beginning-of-line) (if (re-search-forward comment-start-skip opoint 'move 1) (progn (goto-char (match-end 1)) (skip-chars-forward ";"))) (skip-chars-backward " \t\f") (setq stop (or (bobp) (not (bolp)) (forward-char -1))))))(defun perl-backward-to-start-of-continued-exp (lim) (if (= (preceding-char) ?\)) (forward-sexp -1)) (beginning-of-line) (if (<= (point) lim) (goto-char (1+ lim))) (skip-chars-forward " \t\f"));; note: this may be slower than the c-mode version, but I can understand it.(defun indent-perl-exp () "Indent each line of the Perl grouping following point." (interactive) (let* ((case-fold-search nil) (oldpnt (point-marker)) (bof-mark (save-excursion (end-of-line 2) (perl-beginning-of-function) (point-marker))) eol last-mark lsexp-mark delta) (if (= (char-after (marker-position bof-mark)) ?=) (message "Can't indent a format statement") (message "Indenting Perl expression...") (save-excursion (end-of-line) (setq eol (point))) (save-excursion ; locate matching close paren (while (and (not (eobp)) (<= (point) eol)) (parse-partial-sexp (point) (point-max) 0)) (setq last-mark (point-marker))) (setq lsexp-mark bof-mark) (beginning-of-line) (while (< (point) (marker-position last-mark)) (setq delta (perl-indent-line nil (marker-position bof-mark))) (if (numberp delta) ; unquoted start-of-line? (progn (if (eolp) (delete-horizontal-space)) (setq lsexp-mark (point-marker)))) (end-of-line) (setq eol (point)) (if (nth 4 (parse-partial-sexp (marker-position lsexp-mark) eol)) (progn ; line ends in a comment (beginning-of-line) (if (or (not (looking-at "\\s-*;?#")) (listp delta) (and (/= 0 delta) (= (- (current-indentation) delta) comment-column))) (if (re-search-forward comment-start-skip eol t) (indent-for-comment))))) ; indent existing comment (forward-line 1)) (goto-char (marker-position oldpnt)) (message "Indenting Perl expression...done"))))(defun perl-beginning-of-function (&optional arg) "Move backward to next beginning-of-function, or as far as possible.With argument, repeat that many times; negative args move forward.Returns new value of point in all cases." (interactive "p") (or arg (setq arg 1)) (if (< arg 0) (forward-char 1)) (and (/= arg 0) (re-search-backward "^\\s(\\|^\\s-*sub\\b[^{]+{\\|^\\s-*format\\b[^=]*=\\|^\\." nil 'move arg) (goto-char (1- (match-end 0)))) (point));; note: this routine is adapted directly from emacs lisp.el, end-of-defun;;; no bugs have been removed :-)(defun perl-end-of-function (&optional arg) "Move forward to next end-of-function.The end of a function is found by moving forward from the beginning of one.With argument, repeat that many times; negative args move backward." (interactive "p") (or arg (setq arg 1)) (let ((first t)) (while (and (> arg 0) (< (point) (point-max))) (let ((pos (point)) npos) (while (progn (if (and first (progn (forward-char 1) (perl-beginning-of-function 1) (not (bobp)))) nil (or (bobp) (forward-char -1)) (perl-beginning-of-function -1)) (setq first nil) (forward-list 1) (skip-chars-forward " \t") (if (looking-at "[#\n]") (forward-line 1)) (<= (point) pos)))) (setq arg (1- arg))) (while (< arg 0) (let ((pos (point))) (perl-beginning-of-function 1) (forward-sexp 1) (forward-line 1) (if (>= (point) pos) (if (progn (perl-beginning-of-function 2) (not (bobp))) (progn (forward-list 1) (skip-chars-forward " \t") (if (looking-at "[#\n]") (forward-line 1))) (goto-char (point-min))))) (setq arg (1+ arg)))))(defun mark-perl-function () "Put mark at end of Perl function, point at beginning." (interactive) (push-mark (point)) (perl-end-of-function) (push-mark (point)) (perl-beginning-of-function) (backward-paragraph));;;;;;;; That's all, folks! ;;;;;;;;;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -