;; Allows white space before and after point.
(defun jde-line-end-at-open-brace ()
(and (looking-back "{\\s-*" (line-beginning-position)) (looking-at "}?\\s-$")))


;; Discovering the function parse-partial-sexp has simplified the mismatched brace detecting code considerably.
;; Now we just check if the number of unmatched open braces from the beginning of the buffer to point
;; is greater than the number of unmatched close braces in the region from point to the end of the buffer.
;; If so we add a close brace. This handles all the problems that have come up so far.


(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))))


;; allows you to customize the indentation function
(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)))
 )

(defun jde-newline ()
 "This command invokes the function defined by `jde-newline-function'."
 (interactive)
 (call-interactively (car jde-newline-function)))


;; And here's the rest of the code Paul, so you don't have to grab it from multiple posts.
(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 () {
} ^


It does this by checking if the line containing the matching
close brace is already correctly indented. If it is not then this
close brace probably does not match the open brace at point and
so a new close brace is inserted."
 :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-has-incomplete-string ()
"Returns true if point is at the end of the line and the
current line has a mismatched double quote 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)))))


(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)
))))




Reply via email to