Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Fix undesirable EMACS tabbing behavior in ESS/Stata

ESS/Stata mode in emacs incorrectly indents lines that follow lines ending in operators. It seems to incorrectly interpret these lines as multiline commands.

For example:

gen foo = 1

/* generate another variable */
  gen bar = 1

The line "gen bar = 1" should not be indented. It looks like EMACS interprets the trailing slash in the comment as an operator, and thinks this line of code spans two lines.

In fact, multiline commands in stata have 3 trailing slashes, and newlines without 3 trailing slashes indicate the end of a statement. e.g. the following indentation would be correct:

gen bar = 1
gen ///
  foo = 1

Is there something I can put in my .emacs to correct this behavior? I don't want to give up automatic tabbing completely - it works very well for everything except comments that /* look like this */.

Thanks,

Pnj

like image 272
pnj Avatar asked Nov 09 '11 17:11

pnj


1 Answers

You're right, ESS interprets the trailing / as an indication of line continuation. This is hard-coded into the function ess-continued-statement-p, so to modify the behaviour you have to rewrite the code. The following code (in your .emacs) works for your examples.

(eval-after-load 'ess-mode
  '(defun ess-continued-statement-p ()
   "this is modified code"
     (let ((eol (point)))
       (save-excursion
         (cond ((memq (preceding-char) '(nil ?\, ?\; ?\} ?\{ ?\]))
                nil)
               ;; ((bolp))
               ((= (preceding-char) ?\))
                (forward-sexp -2)
                (looking-at "if\\b[ \t]*(\\|function\\b[ \t]*(\\|for\\b[ \t]*(\\|while\\b[ \t]*("))
               ((progn (forward-sexp -1)
                       (and (looking-at "else\\b\\|repeat\\b")
                            (not (looking-at "else\\s_\\|repeat\\s_"))))
                (skip-chars-backward " \t")
                (or (bolp)
                    (= (preceding-char) ?\;)))
               (t
                (progn (goto-char eol)
                       (skip-chars-backward " \t")
                       (or (and (> (current-column) 1)
                                (save-excursion (backward-char 1)

        ;;;; Modified code starts here: ;;;;
                                                (or (looking-at "[-:+*><=]")
                                                    (and (looking-at "/")
                                                         (save-excursion (backward-char 1)
                                                                         (not (looking-at "*")))))))
        ;;;; End of modified code ;;;;

                           (and (> (current-column) 3)
                                (progn (backward-char 3)
                                       (looking-at "%[^ \t]%")))))))))))
like image 75
Tyler Avatar answered Oct 17 '22 01:10

Tyler