juvix icon indicating copy to clipboard operation
juvix copied to clipboard

Properly newline expressions in the pretty printer

Open mariari opened this issue 2 years ago • 1 comments

I was looking at Juvix examples today, and many examples are quite hard to read


  --- Given a player attempted move, updates the state accordingly.
  playMove : Maybe Nat → GameState → GameState;
  playMove nothing (state b p _) := state b p (continue "\nInvalid number, try again\n");
  playMove (just k) (state (board s) player e) := if (not (elem (==) k (possibleMoves (flatten s)))) (state (board s) player (continue "\nThe square is already occupied, try again\n")) (checkState (state (board (map (map (replace player k)) s)) (switch player) noError));

Namely the text goes off the screen since it is over 270 characters long. Would be good to have a mechanism that can newline at 80 or 90 characters long automatically in the pretty printed. Should be easy to implement and would improve readability quite a bit.

mariari avatar Oct 05 '22 03:10 mariari

It seems the changes make it harder to read, let me explain

  playMove : Maybe Nat → GameState → GameState;
  playMove nothing (state b p _) := state b p (continue
    "\nInvalid number, try again\n");
  playMove (just k) (state (board s) player e) := if (not (elem (==) k
    (possibleMoves (flatten s)))) (state (board s) player (continue
    "\nThe square is already occupied, try again\n")) (checkState (state (board
    (map (map (replace player k)) s)) (switch player) noError));

the ( after the if is more forward than the line after it, making watching a sense of nesting hard. This gets worse in player (continue as the same indentation level stays the same, meaning it's impossible to see where expressions end. is (checkState ...) apart of continue? I can't tell!

A plan

I think there still is an easy way to fix this, the library seems heavily inspired from what I currently use in projects

Make an block (group in the library terms), where you align each argument of a function together, that way they either all newline or don't. Probably best to indent things like

 if (won (state b p e))
     (state b p (terminate ("Player " ++str (showSymbol (switch p)) ++str " wins!")))
     (if (draw (state b p e))
         (state b p (terminate "It's a draw!"))
         (state b p e));

Where the alignment starts after the function word (if in this case).

Thankfully It seems the library has done most of the work already with encloseSep, and you can likely just invoke it as follows

"app" <+> align (encloseSep lparen rparen space (map pretty [1,20,300,4000]))

Infix functions will take more effort as you'll want to decide on infix on the next line or end of the line, which affects how you ought to format.

mariari avatar Oct 06 '22 02:10 mariari

#1581 closes this

janmasrovira avatar Oct 20 '22 14:10 janmasrovira