1. Meikel Brandmeyer
  2. vimclojure
  3. Issues
Issue #22 resolved

Indentation

brandonw
created an issue

When writing code such as: {{{ (ns reader.tasklist (:import [java.io File] [org.xml.sax InputSource] [org.xml.sax.helpers DefaultHandler] [javax.xml.parsers SAXParserFactory])) }}}

The indentation does not line up package names to import as I expected. It also occurs with let bindings not being indented the same amount as the expressions, even though they are both arguments to let.

Am I misunderstanding how pretty-printing works, or is the way it works in vimclojure better on conserving width in the file, at the cost of making more lines?

{{{ (ns reader.tasklist (:import [java.io File] }}} vs {{{ (ns reader.tasklist (:import [java.io File] }}}

I only bring this up because I noticed when going through Programming Clojure by Stuart Halloway and saw that the code in the book was indented differently than it was when I typed it in vimclojure.

Comments (18)

  1. Meikel Brandmeyer repo owner
    • changed status to open
    • marked as bug

    First of all: VimClojure does not do pretty printing! It just re-indents the given source. It does not insert newlines or such.

    I'm not sure I understand the problem with let. Do you have an example?

    The two examples you showed are up to your personal liking. VimClojure indentation does not impose any restrictions on how you layout your source code. However it follows the Vim lisp mode as close as possible. I don't know whether this is totally compliant with all edge cases of the very widespread lisp and scheme indentation standard. It comes close enough that the incentive to fix the small dark corners was not very high up to now.

    Your issue however is really a bug.

  2. brandonw reporter

    Sorry, I was thinking of pretty-printing in terms of the SICP book; I didn't realize there was a pretty-print package for clojure that deals with the REPL output.

    I don't know that let bindings are specifically different than any other formatted code I've seen; I only saw that it had a similar indentation as the namespace indentation.

    As for the namespace (which I think was the primary question I had)- that was pretty much why I put it on proposal instead of bug-- because I wasn't sure if it was a stylistic interpretation per user, or if it was a standard indentation rule that was missed.

    My only comparison was the book I had mentioned, and how the source in the book (and in the code sample files) were indented differently. Anything after that is up to you; I just wanted to bring it to your attention in case it was an edge case.

    Regards, Brandon

  3. brandonw reporter

    I was mistaken on the let example, it definitely works as expected.

    I think the issue is with a series of arguments that are not enclosed by delimiting characters ( (,[,{ ) by themselves. the ns function is one example: you have a keyword, and then an arbitrary number of packages after that, instead of a keyword, and then a sequence of packages to import

    I think anything with the form:

    (ns reader.tasklist
      (:import [java.io File]
        [org.xml.sax InputSource]
        [org.xml.sax.helpers DefaultHandler]
        [javax.xml.parsers SAXParserFactory]))
    
    

    will indent as shown (with the packages to import not being indented consistently) as opposed to:

    (ns reader.tasklist
      (:import ([java.io File]
                [org.xml.sax InputSource]
                [org.xml.sax.helpers DefaultHandler]
                [javax.xml.parsers SAXParserFactory])))
    
    

    ...which will indent correctly (albeit with incorrect syntax).

    So basically anything that takes in an arbitrary number of args that are not formed as a sequence would indent differently than expected.

  4. brandonw reporter

    I found another example of unexpected indentation format, the cond macro.

    It is normally written something like:

    (cond test expr
          test expr
          test expr) 
    

    However, vimclojure indents as such:

    (cond test expr
      test expr
      test expr)
    
  5. brandonw reporter

    Awesome!

    About the ns indentation: if you modify GetClojureIndent() so that instead of just white space that is checked immediately after the paren, you also check for a colon, that fixes the issue.

    If you don't check for a colon too, then when normal! w is executed towards the end, instead of going to the next word, it just moves the cursor to the right one character to the word beginning after the colon.

    It seems that a keyword immediately following an open paren in the scope of a function call is idiomatic clojure for allowing a macro to embed multiple function calls (in the ns example-- embedding use/require/import/etc.), but I do not yet have enough experience to back that up.

    The only other time you would use a keyword immediately after a paren is using the keyword as a function into an ad-hoc defined collection, in which case the '(, [, or { that defines the collection would take precedence in defining the indentation. At least it looked okay in the gorilla repl I tried for a few minutes.

    I've attached a patch in case you agree and want to update. If it isn't a standard thing that can be assumed, then it would probably be better off as is.

  6. brandonw reporter

    Realized after my previous post that I didn't take into account the case where there is a space after the paren, and a colon before the first word.

    I have uploaded a new patch to reflect those considerations. I think this patch should be good to go.

  7. Meikel Brandmeyer repo owner

    (Reply via m...@kotka.de):

    I'm not sure I understand what you mean. The clauses are now indented like this:

      (ns name.space
        (:require lib1
                  lib2
                  lib3))
    

    This is the "right" way. Is this not what you expect?

    Besides ns I'm not aware of a macro, which translates keywords to function calls.

  8. brandonw reporter

    With the latest .vim/indent/clojure.vim file from your repo, my indentation works as described in my original report. In your example, lib2 is indented two spaces to the right of the (:require lib1 line:

    (ns name.space
      (:require lib1
        lib2
        lib3))
    

    It didn't indent correctly until I changed the .vim/indent/clojure.vim as described in my patch above. Do you think something is is causing my indentation to be wrong on my side? It works correctly (as you typed it) for you, with the current version of .vim/indent/clojure.vim? Are there any other requirements for the vimclojure plugin to work?

  9. Meikel Brandmeyer repo owner

    The fix was actually not done in indent/clojure.vim, but ftplugin/clojure.vim: The : was missing from the iskeyword option. Please use always the whole set of plugin files from a changeset. There might be interdependencies between them!

    See 4eee9c98da7c .

  10. Anonymous

    Oh, I'm sorry. I didn't realize you had confirmed the colon keyword indentation issue, so I hadn't updated since right before you fixed the cond indentation.

    Works now, thanks for the update! This really is one of the best coding file-type plugins I've ever used. Thanks for all the hard work :)

  11. Log in to comment