are now allowed after the brace and around point.
As suggested by Jens I also added a defcustom for jde-newline which lets you select what indentation
function you want. The default value is ('newline) or no indentation. Control-j is bound to the same function
as return but will always indent the new line.
(defcustom jde-newline-function '(newline)
"Indent command that the enter key calls."
:group 'jde
:type '(list
(radio-button-choice
:format "%t \n%v"
:tag "Function: "
:entry-format " %b %v"
(const newline)
(const newline-and-indent)
(const align-newline-and-indent)
(function my-custom-newline-function)))
)(defcustom jde-gen-embrace t "Typing enter after a close brace at the end of a line will insert a matching closing brace (if required) and put point on a empty line between the braces and indent the new lines.
So if before you had:
pubic void function () {
^
You now have:pubic void function () {
} ^
Point must be at the end of the line, or at a } character followed by the end of the line.
If it thinks a matching close brace already exists a new one is not inserted.
Before:
pubic void function () {
} ^
After:
pubic void function () {
} ^
"
:type 'boolean
)
(defcustom jde-gen-complete-multi-line-string t
"Typing enter at the end of a line with an unterminated string
constant will result in the generation of the required string by
adding a \\n character to the end of the line, closing the string,
adding the string append operator (+) and starting a new string
on the next line. Before:
String a = \"This is a multi-line string
^
After:
String a = \"This is a multi-line string\\n\" +
\"
^"
:type 'boolean
)
(defun jde-line-end-at-open-brace ()
(and (looking-back "{\\s-*" (line-beginning-position)) (looking-at "}?\\s-*$")))
(defun jde-gen-embrace () "Adds a new line and inserts a matching close brace if required. See variable 'jde-gen-embrace.
Assumes that 'jde-line-end-at-open-brace has been called and it
returned true."
(interactive)
(let ((open-indent (current-indentation)))
(when (looking-at "}")
;; if there is a } after point, put it on a new line and come back
(jde-newline)
(end-of-line 0) ;; move to end of previous line
)
;; make a blank line
(jde-newline)
(when (save-excursion
(>
(car (parse-partial-sexp (point-min) (point))) ;; parenthesis depth at point
(- (car (parse-partial-sexp (point) (point-max))))) ;; number of unmatched open parenthesis staring from point
)
;; add the } on a new indented line
(insert "}")
(indent-according-to-mode)
(end-of-line 0) ;; move to end of previous line
(jde-newline))))
(defun jde-line-has-incomplete-string ()
"Returns true if point is at the end of the line and the
current line has a mismatched doublequote character."
(let* ((end (point))
(beg (save-excursion (beginning-of-line) (point)))
(count 0))
(save-excursion
(while (search-backward "\"" beg t)
(unless (or (= (preceding-char) ?\\) (and (= (preceding-char) ?') (looking-at "\"'")))
(incf count)
)
))
(= (mod count 2) 1)
))
(defun jde-multi-line-string-enter ()
"Ends an unterminated string constant and continues it on the
next line. See variable 'jde-gen-complete-multi-line-string.
Assumes that 'jde-line-has-incomplete-string was called and it returned true. "
(interactive)
(insert "\\n\" +")
(jde-newline)
(insert "\"")
)
(defun jde-mode-return ()
"Check if variables 'jde-gen-embrace or
'jde-gen-complete-multi-line-string are set and handle them
appropriately. Automatically indents the new line if jde-auto-indent is true or if invoked by C-j"
(interactive)
(let ((jde-newline-function (if (equal last-command-char 10)
'(newline-and-indent)
jde-newline-function)))
(cond
((and jde-gen-complete-multi-line-string (jde-line-has-incomplete-string))
(jde-multi-line-string-enter))
((and jde-gen-embrace (jde-line-end-at-open-brace))
(jde-gen-embrace))
(t (jde-newline)))))
(defun jde-newline () "This command invokes the function defined by `jde-newline-function'." (interactive) (call-interactively (car jde-newline-function)))
(define-key jde-mode-map [return] 'jde-mode-return) (define-key jde-mode-map [(control j)] 'jde-mode-return)
;; Do an indent after a yank. (defadvice yank (after jde-indent-and-fix-strings-after-yank activate) (jde-indent-and-fix-strings-after-yank))
(defadvice yank-pop (after jde-indent-and-fix-strings-after-yank activate) (jde-indent-and-fix-strings-after-yank))
(lexical-let ((unescaped-quote (if (string-match "XEmacs" (version)) ;; no sregex in XEmacs
"\\(?:[^\\]\\|^\\)\""
(require 'sregex)
(sregexq (or
;; the " char should either have
;; something that's not a \ before it
(not-char ?\\)
;; or should be at the beginning of the line
bol)
"\""))))
(defun jde-indent-and-fix-strings-after-yank ()
"Do an indent and also check if adding a multiline string after a yank"
(when (equal "JDE" mode-name)
(let ((transient-mark-mode nil) (zmacs-regions nil))
;; check for incomplete string
(save-excursion
(exchange-point-and-mark)
(when (and jde-gen-complete-multi-line-string (jde-line-has-incomplete-string))
(save-restriction
(narrow-to-region (region-beginning) (region-end))
;; escape open quotes
(while (re-search-forward unescaped-quote nil t)
(backward-char)
(insert "\\"))
(goto-char (point-min))
;; for each line added terminate the string on the
;; previous line and open a new string
(while (progn (end-of-line) (not (= (point) (point-max))))
(insert "\\n\" +")
(forward-char)
(insert "\"")
)
)
(indent-according-to-mode)
))
(indent-region (region-beginning) (region-end) nil)
(end-of-line)
))))
;; to remove the above advice
;; (ad-remove-advice 'yank 'after 'jde-indent-and-fix-strings-after-yank)
;; (ad-remove-advice 'yank-pop 'after 'jde-indent-and-fix-strings-after-yank)
