6

I'm not a lisp programmer. But I'm an emacs user, so I use elisp from times to times to do simple scripting. I'm not familiar with lisp style and I'm quite incompatible with it. Default indents quickly become over 80 whitespaces long making the program unreadable. Lisp style implies writing all braces in the single line and that makes me crazy. I'm much more comfortable with the K-R notation:

def doSomething() {
  ...
}

That style may be easily adopted to lisp code:

(defun doSomething ()
   ...
)

So I'm using it for my code, see example. But accidental calls to the indent function ruins line. That is not a big deal, undo function works well. But that still bothers me.

So I'd like to change indent function for lisp mode in either way:

  • work like for java mode (preferred)
  • do nothing (not make things worse at least)
ayvango
  • 575
  • 4
  • 6
  • 3
    As far as I know, there is no existing solution for this. However, you can define your own indentation function and bind it to `indent-line-function'. I don't have the time to implement it for you, but if someone else like to, feel free to post this as an answer. – Lindydancer Oct 21 '15 at 06:08
  • 4
    Just a tiny question, what if, from time to time, you want to share your code, or one of your friend want to share his code with you? – Nsukami _ Oct 21 '15 at 12:32
  • 3
    Note that this is a really bad idea. The notation you have may look nice for C++ or Java, but this will look terribly ugly for anyone fluent enoguh in Lisp to read your code. You'd better use paredit/smartparens - you will forget about parenthesis in an instant. Remember, that you will probably need to ask a few questions once in a while - and every time someone will be disgusted by the indentation. The tradeoff is non-existent, and the current style holds because it turns out it's more readable this way. – MatthewRock Oct 23 '15 at 14:01
  • I'm afraid C++ and Java programmers has a bigger share of emacs users than pure lisp programmers. The current style is not more readable it is more used. It was at the same point of time, but IT progressed and suggested more readable styles. How can I detect where does statement end, when its closed bracket does not match open? – ayvango Oct 24 '15 at 05:32

1 Answers1

3

If you really do want to change it, it's Emacs, of course you can.

Brutality

In the extreme, one can always use M-x fundamental-mode to “turn off” all of the mode-specific goodies, but that's probably overkill here.

Conformity

The only thing in your code that seems to be particularly injured by indentation was the use of (if … (progn)) forms.

(if … (progn)) is usually considered bad form; one uses one of when, unless, or cond for such cases more often. Switching these to when or cond forms yields what you might have wanted/expected:

Your example code with standard indentation and dangling )s:

(defun my:push-whitespace (&rest skip)
  (if (my:prev-whitespace-pushed) (progn
                                     (setq my:prev-whitespace-mode whitespace-mode)
                                     (setq my:prev-whitespace-pushed t)
                                     (my:force-modes nil 'whitespace-mode)
                                     ))
  )

(defun my:push-whitespace (&rest skip)
  (when (my:prev-whitespace-pushed) 
    (setq my:prev-whitespace-mode whitespace-mode)
    (setq my:prev-whitespace-pushed t)
    (my:force-modes nil 'whitespace-mode)
    )
  )

or

(defun my:push-whitespace (&rest skip)
  (cond ((my:prev-whitespace-pushed) 
         (setq my:prev-whitespace-mode whitespace-mode)
         (setq my:prev-whitespace-pushed t)
         (my:force-modes nil 'whitespace-mode))
        )
  )

Customization

The indentation patterns for various special forms are defined by lisp-indent-function properties on their symbols.

This will change the progn special form to indent from the prior (containing) form's start point, rather than its own:

(defun progn-java-indent (path state indent-point sexp-column normal-indent)
  (declare (ignored path state sexp-column normal-indent))
  ;; Find the point at the start of the containing sexp
  (let ((containing-point (condition-case
                           nil
                           (save-excursion
                            ;; Start at the current line
                            (goto-char indent-point)
                            ;; Up once to `|(progn` and again to its parent
                            (up-list -2)
                            ;; Take that column
                            (current-column))
                           ;; If there isn't a containing list, use the
                           ;; left margin, instead.
                           (scan-error 0))))
    ;; Increase by standard indentation, or 2, by default.
    (+ containing-point (or lisp-indent-offset
                            2))))

The scan-error condition is signaled by up-list when progn appears as a top-level form.

You could put that into your init.el and associate it with

 (put 'progn 'lisp-indent-function 'progn-java-indent)

With your sample code, I get:

(defun my:push-whitespace (&rest skip)
  (if my:prev-whitespace-pushed () (progn
    (setq my:prev-whitespace-mode whitespace-mode)
    (setq my:prev-whitespace-pushed t)
    (my:force-modes nil 'whitespace-mode)
    ))
  )

QED, I think.

BRPocock
  • 131
  • 3