有效的Clojure压头

时间:2011-10-18 14:56:28

标签: clojure editor indentation

我正在寻找一个正确的编辑/命令行程序(IMHO)缩进Clojure代码,将第三个和后续元素与第二个元素对齐:

(let [foo (fun arg1
               arg2)

      bar (doto (Baz.)
                (.setProp abc123))

      [v1 v2] (fun2)

      [v3 v4] (fun3)]
  (xyzzy 42))

我已尝试使用“通过第二个元素对齐Clojure表单”(由第二个元素对齐),VimClojure,emacs(混淆了[v3 v4]部分的缩进),然后使用了对于IntelliJ的La Clojure,Enclojure在Netbeans中(不与第二个元素对齐),在Eclipse中逆时针(不与第二个元素对齐)。在每种情况下,我都在使用最新版本的软件。

如果需要,我可以在编辑器外部(在命令行上)运行一个美化器。

以下是Aquamacs的输出。请注意“级联”(make-day-panel)调用:

(defn make-mainframe [build-number project-version]
  "Create the mainframe.
  @param build-number the current build number
  @param project-version the Maven project version
  @returns the reified JFrame"
  (let [[^JToggleButton day-sheets-button
         ^JToggleButton summaries-button]
        (let [day-sheets-button
              (doto (JToggleButton. "Day Sheets")
                (.setToolTipText
                 "Switch to the Day Sheets view"))

              summaries-button
              (doto (JToggleButton. "Summaries")
                (.setToolTipText "Switch to the Summaries view"))]
          (doto (ButtonGroup.)
            (.add day-sheets-button)
            (.add summaries-button))
          (.setSelected day-sheets-button true)
          [day-sheets-button summaries-button])

        [^JPanel monday-panel
         monday-button
         monday-vacation-check
         monday-arrive-text-field
         monday-depart-text-field] (make-day-panel "Monday")

         [^JPanel tuesday-panel
          tuesday-button
          tuesday-vacation-check
          tuesday-arrive-text-field
          tuesday-depart-text-field] (make-day-panel "Tuesday")

          [^JPanel wednesday-panel
           wednesday-button
           wednesday-vacation-check
           wednesday-arrive-text-field
           wednesday-depart-text-field] (make-day-panel "Wednesday")

           [^JPanel thursday-panel
            thursday-button
            thursday-vacation-check
            thursday-arrive-text-field
            thursday-depart-text-field] (make-day-panel "Thursday")

            [^JPanel friday-panel
             friday-button
             friday-vacation-check
             friday-arrive-text-field
             friday-depart-text-field] (make-day-panel "Friday")

             [^JPanel saturday-panel
              saturday-button
              saturday-vacation-check
              saturday-arrive-text-field
              saturday-depart-text-field] (make-day-panel "Saturday")

              [^JPanel sunday-panel
               sunday-button
               sunday-vacation-check
               sunday-arrive-text-field
               sunday-depart-text-field] (make-day-panel "Sunday")

        #_ [week-selector-panel week-selector-combobox week-selector-today-button]
        #_ (make-week-selector)

        north-panel
        (let [^JPanel panel (JPanel.)]
          (doto panel
            (.setLayout (BoxLayout. panel BoxLayout/X_AXIS))
            (.add day-sheets-button)
            (.add (Box/createHorizontalStrut 5))
            (.add summaries-button)
            (.add (Box/createHorizontalGlue))
            #_ (.add week-selector-panel)))

        ^JToggleButton mail-button
        (make-button "Mail Report"
                     (make-icon "email-32x32-plain.png")
                     "Generate and send a weekly report for the currently selected week")

        ^JToggleButton report-button
        (make-button "Report"
                     (make-icon "history2-32x32-plain.png")
                     "Generate a weekly report for the currently selected week")

        day-sheet-panel
        (let [panel (JPanel. (BorderLayout.))

              north-panel (grid-bag-container (JPanel. (GridBagLayout.))
                                              {:insets (Insets. 2 2 2 2)}
                                              [[(doto (JPanel. (GridLayout. 1 0))
                                                  (.add report-button)
                                                  (.add mail-button))]
                                               [(Box/createHorizontalGlue)
                                                :weightx 1.0 :fill :HORIZONTAL ]
                                               [(doto (JPanel. (GridLayout. 1 0))
                                                  (.add monday-panel)
                                                  (.add tuesday-panel)
                                                  (.add wednesday-panel)
                                                  (.add thursday-panel)
                                                  (.add friday-panel)
                                                  (.add saturday-panel)
                                                  (.add sunday-panel))]])]
          (doto panel
            (.add north-panel BorderLayout/NORTH)
            (.setBorder (BorderFactory/createRaisedBevelBorder))))

        summaries-panel (let [panel (JPanel.)]
                          (doto panel))

        card-panel (let [panel (JPanel. (CardLayout.))]
                     (doto panel
                       (.add day-sheet-panel day-sheet-panel-key)
                       (.add summaries-panel summaries-panel-key)))

        main-panel (doto (JPanel. (BorderLayout.))
                     (.setBorder
                      (BorderFactory/createEmptyBorder default-border default-border
                                                       default-border default-border))
                     (.add north-panel BorderLayout/NORTH)
                     (.add card-panel))

        frame (doto (JFrame. (str "SpareTime (version " project-version ", build "
                                  build-number ")"))
                (.setDefaultCloseOperation JFrame/EXIT_ON_CLOSE)
                (.add main-panel))]
    (reify mainview-methods
      (frame-add-component-listener [_ listener] (.addComponentListener frame listener))
      (frame-center [_] (.setLocationRelativeTo frame nil))
      (frame-get-location [_] (.getLocation frame))
      (frame-get-size [_] (.getSize frame))
      (frame-set-location [_ x y] (.setLocation frame x y))
      (frame-set-size [_ width height] (.setSize frame (Dimension. width height)))
      (frame-set-visible [_ visible] (.setVisible frame visible)))))

4 个答案:

答案 0 :(得分:2)

据我所知,当前的clojure-mode缩进就像你想要的那样,只是它把doto处理为特殊的(也就是说,它从第三个​​表单开始缩进以制作“目标”的立场更多)。

使用来自橘子酱的clojure-mode在我的emacs 24上输出indent-sexp

(let [foo (fun arg1
               arg2)

      bar (doto (Baz.)
            (.setProp abc123))

      [v1 v2] (fun2)

      [v3 v4] (fun3)]
  (xyzzy 42))

我认为你要么破坏了clojure模式,要么aquamacs又变得困难了。我真的建议在OSX上使用标准的Gnu emacs - 只要你将meta映射到命令以外的东西,你就可以在标准的emacs中使用大多数简单的标准osx密钥组合(command-c,command-v,command-s等)

附录:该大型代码块的输出(请注意make-day-panel调用的正确位置):

(defn make-mainframe [build-number project-version]
  "Create the mainframe.
  @param build-number the current build number
  @param project-version the Maven project version
  @returns the reified JFrame"
  (let [[^JToggleButton day-sheets-button
         ^JToggleButton summaries-button]
        (let [day-sheets-button
              (doto (JToggleButton. "Day Sheets")
                (.setToolTipText
                 "Switch to the Day Sheets view"))

              summaries-button
              (doto (JToggleButton. "Summaries")
                (.setToolTipText "Switch to the Summaries view"))]
          (doto (ButtonGroup.)
            (.add day-sheets-button)
            (.add summaries-button))
          (.setSelected day-sheets-button true)
          [day-sheets-button summaries-button])

        [^JPanel monday-panel
         monday-button
         monday-vacation-check
         monday-arrive-text-field
         monday-depart-text-field] (make-day-panel "Monday")

        [^JPanel tuesday-panel
         tuesday-button
         tuesday-vacation-check
         tuesday-arrive-text-field
         tuesday-depart-text-field] (make-day-panel "Tuesday")

        [^JPanel wednesday-panel
         wednesday-button
         wednesday-vacation-check
         wednesday-arrive-text-field
         wednesday-depart-text-field] (make-day-panel "Wednesday")

        [^JPanel thursday-panel
         thursday-button
         thursday-vacation-check
         thursday-arrive-text-field
         thursday-depart-text-field] (make-day-panel "Thursday")

        [^JPanel friday-panel
         friday-button
         friday-vacation-check
         friday-arrive-text-field
         friday-depart-text-field] (make-day-panel "Friday")

        [^JPanel saturday-panel
         saturday-button
         saturday-vacation-check
         saturday-arrive-text-field
         saturday-depart-text-field] (make-day-panel "Saturday")

        [^JPanel sunday-panel
         sunday-button
         sunday-vacation-check
         sunday-arrive-text-field
         sunday-depart-text-field] (make-day-panel "Sunday")

        #_ [week-selector-panel week-selector-combobox week-selector-today-button]
        #_ (make-week-selector)

        north-panel
        (let [^JPanel panel (JPanel.)]
          (doto panel
            (.setLayout (BoxLayout. panel BoxLayout/X_AXIS))
            (.add day-sheets-button)
            (.add (Box/createHorizontalStrut 5))
            (.add summaries-button)
            (.add (Box/createHorizontalGlue))
            #_ (.add week-selector-panel)))

        ^JToggleButton mail-button
        (make-button "Mail Report"
                     (make-icon "email-32x32-plain.png")
                     "Generate and send a weekly report for the currently selected week")

        ^JToggleButton report-button
        (make-button "Report"
                     (make-icon "history2-32x32-plain.png")
                     "Generate a weekly report for the currently selected week")

        day-sheet-panel
        (let [panel (JPanel. (BorderLayout.))

              north-panel (grid-bag-container (JPanel. (GridBagLayout.))
                                              {:insets (Insets. 2 2 2 2)}
                                              [[(doto (JPanel. (GridLayout. 1 0))
                                                  (.add report-button)
                                                  (.add mail-button))]
                                               [(Box/createHorizontalGlue)
                                                :weightx 1.0 :fill :HORIZONTAL ]
                                               [(doto (JPanel. (GridLayout. 1 0))
                                                  (.add monday-panel)
                                                  (.add tuesday-panel)
                                                  (.add wednesday-panel)
                                                  (.add thursday-panel)
                                                  (.add friday-panel)
                                                  (.add saturday-panel)
                                                  (.add sunday-panel))]])]
          (doto panel
            (.add north-panel BorderLayout/NORTH)
            (.setBorder (BorderFactory/createRaisedBevelBorder))))

        summaries-panel (let [panel (JPanel.)]
                          (doto panel))

        card-panel (let [panel (JPanel. (CardLayout.))]
                     (doto panel
                       (.add day-sheet-panel day-sheet-panel-key)
                       (.add summaries-panel summaries-panel-key)))

        main-panel (doto (JPanel. (BorderLayout.))
                     (.setBorder
                      (BorderFactory/createEmptyBorder default-border default-border
                                                       default-border default-border))
                     (.add north-panel BorderLayout/NORTH)
                     (.add card-panel))

        frame (doto (JFrame. (str "SpareTime (version " project-version ", build "
                                  build-number ")"))
                (.setDefaultCloseOperation JFrame/EXIT_ON_CLOSE)
                (.add main-panel))]
    (reify mainview-methods
      (frame-add-component-listener [_ listener] (.addComponentListener frame listener))
      (frame-center [_] (.setLocationRelativeTo frame nil))
      (frame-get-location [_] (.getLocation frame))
      (frame-get-size [_] (.getSize frame))
      (frame-set-location [_ x y] (.setLocation frame x y))
      (frame-set-size [_ width height] (.setSize frame (Dimension. width height)))
      (frame-set-visible [_ visible] (.setVisible frame visible)))))

答案 1 :(得分:1)

据我所知,如果你在同一行开始一个全新的性别与缩进的延续,Emacs压头不明白发生了什么,这就是你let以上所做的事情。你看到了与

类似的问题
(if (< 1 (- 3
            1) 3
            4))

当然,开头写的不是很好的风格,所以也许E​​macs可以原谅。正如你所指出的那样,这样形状的代码更有可能出现在Clojure的letcond中,并且风格也不错 - 但是Emacs压头是为其他lisps设计的,这需要每对都是用括号括起来:

(let [([x
        y
        z] (foo))
      ([a
        b
        c] (bar))]
  ...)

正如你所看到的那样,缩进很好。因此,我认为在某些时候有人必须弄清楚如何更新Emacs压头以适应这种情况,并且这比让其他编辑器达到Emacs的水平更容易。也许那个人应该是你,如果它困扰你 - 我想是开源的魔力和负担。

答案 2 :(得分:1)

当您从doto移除lispwords时,VimClojure将缩进您想要的方式(如果我理解您的示例正确)。

setlocal lispwords-=doto

答案 3 :(得分:0)

LightTable在Joost的帖子中以与Emacs相同的方式缩进它:

(let [foo (fun arg1
               arg2)

      bar (doto (Baz.)
            (.setProp abc123))

      [v1 v2] (fun2)

      [v3 v4] (fun3)]
  (xyzzy 42))

如果你问我,那就太好了。根据我的经验,它比IDEA,Sublime Text或Netbeans更好。如果你不是Vim / Emacs用户,值得一试。它仍然处于早期阶段,但显示出很多希望。它的设计考虑了Clojure。