ormolu icon indicating copy to clipboard operation
ormolu copied to clipboard

Allow the programmer to suggest alignment

Open lukaszlew opened this issue 4 years ago • 5 comments

It would be super hard for Ormulu to figure how to preserve alignment: (sorry, scrambled after the diff):

-igLkcrdYnsh s l = ntfa
-        [ "Ig"                  % K . iyfo Q . mlug (pucqQrbD.otfnc rpyopo)
-        , "mGTJIr"              % pure (ofeOIAPxD.iuevf bsxscd)
-        , "xCSNXpf"             % pure (iiwYQPXemB.jmlii geccnk)
-        , "sRxxfruPgeWasigi"    % pure (borlwfKscWrsfxfQ.kekqwd)
-        , "fTlkhrlXuiDliwvqw"   % aujb (cbbxuoBcaGwapmruR.aeojec)
-        , "jHuoovqKnsyDfyvlxoi" % sqnd (jteuiiGgydLufxqgfxX.bfoqwj)
-        , "xE"                  % K . vggs (phcWepgawQ.vatXcxff.dhinf iqdmnj)
-        , "vW"                  % K . omwl (xpqBrpfdyF.phnYxcki.dvqse phulxc)
-        , "vH"                  % K . udxo (rxfCuovowE.qltTvye.xovea glfuck)
-        , "iD"                  % A . nydq (ewoDxcaemB.fvxAakt.dotfb nsicgx)
-        , "bMG"                 % wjox (forIxjolYpQ.kqmyoc)
-        , "dw"                  % B . _fjqbLqyspm
-        ]
+dcMigcfIemk o f =
+  livn
+    [ "Rn" % R . vfxo V . kwjr (jkdbSgpE . mmsdo yspudw)
+    , "dNFXNy" % clan (afqRDLFlM . rowfh rcwngo)
+    , "kCUFUvu" % xhnf (fyuPQSUlyF . potot ihpfgl)
+    , "pIxcqupCkqAcgbpi" % qbxe (tenjiwBexSeedtwR . mugogf)
+    , "qQbjuljXwiLigmewh" % mxfy (mxkfyeTadXvcyaabV . ctcoyo)
+    , "yRcjsfgSvjiNqemmqqt" % sbgo (qwgesmGwspRpucaqiaN . rdwtpl)
+    , "iI" % N . ocon (qdrYjylrdF . crtCqecc . wnhsa aubmjb)
+    , "wW" % H . ibqy (httEbitkmH . wlsSdhuc . napgm ajtums)
+    , "tU" % R . xbyf (hluGpmohsP . soeHwld . hcijt ujrmds)
+    , "eW" % E . ulxi (pknXuqysiX . wnxCvhl . tycba slrqxt)
+    , "cQO" % mveb (ellIarccVtM . tbiqqk)
+    , "ns" % I . _ydshFfkrqw
+    ]

second example:

-  -- QVA hnahv 
-  , _fqQaalBjw         :: !(THnkePxmbg 8 QnhVIKnnHldvfyb DyySxf)
-  , _pgTrwroXyf        :: !(XFuwlPbjko 6 PmiXFGkmFipvjvd CfjYwy)
-  , _qtIjbiGjs         :: !(KWxqsTrkox 4 PbjNFMjeRtfsvuq OpsCas)
-  , _jtXreriNiu        :: !(EUwhiDgpvw 2 WmaIQVkbExuieiv XulRlv)
-  , _xqFwbd            :: !(SRolpTtvsk 8 MvtKVHtnjDrkyovs PergWer)
-  , _ktQgacllu         :: !(IWqdxScdls 2 LxgSWRwsveudCjeldvo XyluamwQke)
-  , _xuRsucVvwdVviiq   :: !UucpSkriTgdyeRwutr
-  , _kkBxobmSgpxOwmom  :: !NobiQokhDpxkjNfuaa
+  , -- JDV ftpcv
+    _fvGsaiWnx :: !(JRicrKokqp 3 WnvRYSrsJpmutab UpyLel)
+  , _xiObwntFks :: !(RMkweNugao 6 OyqPUAgrOdeslah FqfPsn)
+  , _tsXgxnNmj :: !(IBtnmHeqaj 4 FhhPMIjkEncaquc WctEty)
+  , _ouErcweJrq :: !(SPuhmXrxca 2 BsbHQIwfJteaabj BmfAti)
+  , _qiLmpp :: !(ETcfcGayko 5 WanJLCklkKqorhxq LeymPqt)
+  , _rjFcotplm :: !(LLpatVjsxy 5 JjlJKXmyiidaMmuwagi IpijnvlEpf)
+  , _ccRbsmXnixEolnn :: !WosyJcmcHxkrxNmkvc
+  , _clSloldXsqxPwyto :: !UkaxBublGwvwkVqrml

What about if instead of using ORMOLU_DISABLE we give the programmer power to teach:

-igLkcrdYnsh s l = ntfa -- ORMOLU align "%"
-        [ "Ig"                  % K . iyfo Q . mlug (pucqQrbD.otfnc rpyopo)
-        , "mGTJIr"              % pure (ofeOIAPxD.iuevf bsxscd)
-        , "xCSNXpf"             % pure (iiwYQPXemB.jmlii geccnk)
-        , "sRxxfruPgeWasigi"    % pure (borlwfKscWrsfxfQ.kekqwd)
-        , "fTlkhrlXuiDliwvqw"   % aujb (cbbxuoBcaGwapmruR.aeojec)
-        , "jHuoovqKnsyDfyvlxoi" % sqnd (jteuiiGgydLufxqgfxX.bfoqwj)
-        , "xE"                  % K . vggs (phcWepgawQ.vatXcxff.dhinf iqdmnj)
-        , "vW"                  % K . omwl (xpqBrpfdyF.phnYxcki.dvqse phulxc)
-        , "vH"                  % K . udxo (rxfCuovowE.qltTvye.xovea glfuck)
-        , "iD"                  % A . nydq (ewoDxcaemB.fvxAakt.dotfb nsicgx)
-        , "bMG"                 % wjox (forIxjolYpQ.kqmyoc)
-        , "dw"                  % B . _fjqbLqyspm
-        ]

second example:

-  -- QVA hnahv -- ORMOLU align "::"
-  , _fqQaalBjw         :: !(THnkePxmbg 8 QnhVIKnnHldvfyb DyySxf)
-  , _pgTrwroXyf        :: !(XFuwlPbjko 6 PmiXFGkmFipvjvd CfjYwy)
-  , _qtIjbiGjs         :: !(KWxqsTrkox 4 PbjNFMjeRtfsvuq OpsCas)
-  , _jtXreriNiu        :: !(EUwhiDgpvw 2 WmaIQVkbExuieiv XulRlv)
-  , _xqFwbd            :: !(SRolpTtvsk 8 MvtKVHtnjDrkyovs PergWer)
-  , _ktQgacllu         :: !(IWqdxScdls 2 LxgSWRwsveudCjeldvo XyluamwQke)
-  , _xuRsucVvwdVviiq   :: !UucpSkriTgdyeRwutr
-  , _kkBxobmSgpxOwmom  :: !NobiQokhDpxkjNfuaa

lukaszlew avatar Jun 12 '20 14:06 lukaszlew

I like that adding -- ORMOLU align "::" everywhere is painful enough that people will (hopefully!) only use it when necessary.

I don't like that this feature has approximately 0% discoverability, which might make it not worth the effort.

neongreen avatar Jun 15 '20 12:06 neongreen

Value of this feature is less about converging the world on a single style and more on encouraging people are strongly affected (e.g. Google Haskellers) to use Ormolu at all.

lukaszlew avatar Jun 16 '20 21:06 lukaszlew

I will never want to live without ormolu again, but I also really want this! :)

fisx avatar Feb 20 '21 11:02 fisx

Perhaps a stop gap solution would just be to detect and maintain existing alignment. I'm thinking the user can indicate that they want things to be aligned by introducing multiple sequential spaces. Specifically, we can identify an "alignment column" which is a single column over a range of rows. Intuitively, a column an alignment column if all the following hold:

  1. If it is composed only of spaces and spans more than 1 row
  2. Each row has a non-space character directly to the right of the column
  3. There is at least one extra space directly to the left of the column (on ANY row) as long as there is some non-space character further left in the same row

From the above example:

igLkcrdYnsh s l = ntfa
----------------------------- v This column has spaces (Rule 1)
       [ "Ig"                  % K . iyfo Q . mlug (pucqQrbD.otfnc rpyopo)
       , "mGTJIr"              % pure (ofeOIAPxD.iuevf bsxscd)
       , "xCSNXpf"             % pure (iiwYQPXemB.jmlii geccnk)
       , "sRxxfruPgeWasigi"    % pure (borlwfKscWrsfxfQ.kekqwd)
       , "fTlkhrlXuiDliwvqw"   % aujb (cbbxuoBcaGwapmruR.aeojec)
       , "jHuoovqKnsyDfyvlxoi" % sqnd (jteuiiGgydLufxqgfxX.bfoqwj)              -- (*)
       , "xE"                  % K . vggs (phcWepgawQ.vatXcxff.dhinf iqdmnj)
       , "vW"                  % K . omwl (xpqBrpfdyF.phnYxcki.dvqse phulxc)
       , "vH"                  % K . udxo (rxfCuovowE.qltTvye.xovea glfuck)
       , "iD"                  % A . nydq (ewoDxcaemB.fvxAakt.dotfb nsicgx)
       , "bMG"                 % wjox (forIxjolYpQ.kqmyoc)
       , "dw"                  % B . _fjqbLqyspm
----------------------------- ^ This column has spaces (Rule 1)
       ]

Rule 2: all rows have a % directly to the right of the column (the fact that they are the same character is not important, it's only important that they are non-space). The line marked with (*) does NOT have a space to the left of the column, but that's fine, we only require at least 1 of the rows to have a space to the right (rule 3). So in this case we should maintain alignment (everything to the right of the column should stay aligned.

This solution won't do the aligning for you, but will maintain it and doesn't require an extra pragma like -- ORMOLU align. Rule 3 is key to providing a way for programmers to "request" alignment without resorting to : they just align things (which requires using extra spaces) and ormolu will adhere to that.

DavidEichmann avatar May 13 '21 12:05 DavidEichmann

I'll chime in too :) , even though ORMOLU_DISABLE/ENABLE is enough already, in my own experience.

If we were to use explicit comments to label the region for ormolu, then I think it'd be reasonable for those comments to include a specification of the alignment columns. The programmer is already manually aligning things, so having them also manually align a specification header row ought to be no problem.

Each "alignment column marker" would simply be anything except a space, so eg an emacs user could continue to use their align-via-regexp command when they've already got one that works for their actual code lines. I'd suggest that the cells in the header row should be empty; no names etc. That way the rule is simple: if it's not a space, it marks an alignment column.

igLkcrdYnsh s l = ntfa
{- ORMOLU_BEGIN_ALIGN
                               % -}
       [ "Ig"                  % K . iyfo Q . mlug (pucqQrbD.otfnc rpyopo)
       , "mGTJIr"              % pure (ofeOIAPxD.iuevf bsxscd)
       , "xCSNXpf"             % pure (iiwYQPXemB.jmlii geccnk)
       , "sRxxfruPgeWasigi"    % pure (borlwfKscWrsfxfQ.kekqwd)
       , "fTlkhrlXuiDliwvqw"   % aujb (cbbxuoBcaGwapmruR.aeojec)
       , "jHuoovqKnsyDfyvlxoi" % sqnd (jteuiiGgydLufxqgfxX.bfoqwj)
       , "xE"                  % K . vggs (phcWepgawQ.vatXcxff.dhinf iqdmnj)
       , "vW"                  % K . omwl (xpqBrpfdyF.phnYxcki.dvqse phulxc)
       , "vH"                  % K . udxo (rxfCuovowE.qltTvye.xovea glfuck)
       , "iD"                  % A . nydq (ewoDxcaemB.fvxAakt.dotfb nsicgx)
       , "bMG"                 % wjox (forIxjolYpQ.kqmyoc)
       , "dw"                  % B . _fjqbLqyspm
{- ORMOLU_END_ALIGN -}
       ]

nfrisby avatar May 13 '21 16:05 nfrisby