Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Don't expand final list arguments of functions #254

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
104 changes: 60 additions & 44 deletions src/Nixfmt/Pretty.hs
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,15 @@ prettyTermWide :: Term -> Doc
prettyTermWide (Set krec paropen items parclose) = prettySet True (krec, paropen, items, parclose)
prettyTermWide t = prettyTerm t

prettyList :: Doc -> Leaf -> Items Term -> Leaf -> Doc
prettyList sep paropen@Ann{trailComment = post} items parclose =
pretty paropen{trailComment = Nothing}
<> surroundWith sur (nest $ pretty post <> sepBy sep (unItems items))
<> pretty parclose
where
-- If the brackets are on different lines, keep them like that
sur = if sourceLine paropen /= sourceLine parclose then hardline else line

-- | Pretty print a term without wrapping it in a group.
prettyTerm :: Term -> Doc
prettyTerm (Token t) = pretty t
Expand Down Expand Up @@ -211,14 +220,7 @@ prettyTerm (List paropen@Ann{trailComment = Nothing} (Items []) parclose@Ann{pre
-- If the brackets are on different lines, keep them like that
sep = if sourceLine paropen /= sourceLine parclose then hardline else hardspace
-- General list
-- Always expand if len > 1
prettyTerm (List paropen@Ann{trailComment = post} items parclose) =
pretty (paropen{trailComment = Nothing})
<> surroundWith sur (nest $ pretty post <> prettyItems items)
<> pretty parclose
where
-- If the brackets are on different lines, keep them like that
sur = if sourceLine paropen /= sourceLine parclose then hardline else line
prettyTerm (List paropen items parclose) = prettyList hardline paropen items parclose
prettyTerm (Set krec paropen items parclose) = prettySet False (krec, paropen, items, parclose)
-- Parentheses
prettyTerm (Parenthesized paropen expr parclose@Ann{preTrivia = closePre}) =
Expand Down Expand Up @@ -376,36 +378,44 @@ instance Pretty Parameter where
prettyApp :: Bool -> Doc -> Bool -> Expression -> Expression -> Doc
prettyApp indentFunction pre hasPost f a =
let -- Walk the function call chain
absorbApp :: Expression -> Doc
absorbApp :: Bool -> Expression -> Doc
-- This is very hacky, but selections shouldn't be in a priority group,
-- because if they get expanded before anything else,
-- only the `.`-and-after part gets to a new line, which looks very odd
absorbApp (Application f' a'@(Term Selection{})) = group' Transparent (absorbApp f') <> line <> nest (group' RegularG $ absorbInner a')
absorbApp (Application f' a') = group' Transparent (absorbApp f') <> line <> nest (group' Priority $ absorbInner a')
absorbApp _ (Application f' a'@(Term Selection{})) =
group' Transparent (absorbApp False f') <> line <> nest (group' RegularG $ absorbInner a')
absorbApp nextIsAList (Application f' a'@(Term List{})) =
group' Transparent (absorbApp True f') <> sep <> nest (group' Priority $ absorbInner a')
where
sep = if nextIsAList then hardline else line
-- Problem: The hardline forces multiple lines even when stuff fits on a single one
-- Something like https://github.com/NixOS/nixfmt/pull/256 should work better
absorbApp _ (Application f' a') =
group' Transparent (absorbApp False f') <> line <> nest (group' Priority $ absorbInner a')
-- First argument
absorbApp expr
absorbApp _ expr
| indentFunction && null comment' = nest $ group' RegularG $ line' <> pretty expr
| otherwise = pretty expr

isSimpleItems = all (isSimple . Term)

-- Render the inner arguments of a function call
absorbInner :: Expression -> Doc
-- If lists have only simple items, try to render them single-line instead of expanding
-- This is just a copy of the list rendering code, but with `sepBy line` instead of `sepBy hardline`
absorbInner (Term (List paropen@Ann{trailComment = post'} items parclose))
| length (unItems items) <= 4 && all (isSimple . Term) items =
pretty (paropen{trailComment = Nothing})
<> surroundWith sur (nest $ pretty post' <> sepBy line (unItems items))
<> pretty parclose
where
-- If the brackets are on different lines, keep them like that
sur = if sourceLine paropen /= sourceLine parclose then hardline else line
-- If the list is simple, try to render it single-line instead of expanding
absorbInner (Term (List paropen items parclose))
| isSimpleItems items =
prettyList line paropen items parclose
absorbInner expr = pretty expr

-- Render the last argument of a function call
absorbLast :: Expression -> Doc
absorbLast :: Expression -> (Bool, Doc)
-- If the list is simple, try to render it single-line instead of expanding
absorbLast (Term (List paropen items parclose))
| isSimpleItems items =
(True, group' Priority $ nest $ prettyList line paropen items parclose)
absorbLast (Term t)
| isAbsorbable t =
group' Priority $ nest $ prettyTerm t
(False, group' Priority $ nest $ prettyTerm t)
-- Special case: Absorb parenthesized function declaration with absorbable body
absorbLast
( Term
Expand All @@ -416,14 +426,16 @@ prettyApp indentFunction pre hasPost f a =
)
)
| isAbsorbableTerm body && not (any hasTrivia [open, name, colon]) =
group' Priority $
nest $
pretty open
<> pretty name
<> pretty colon
<> hardspace
<> prettyTermWide body
<> pretty close
( False,
group' Priority $
nest $
pretty open
<> pretty name
<> pretty colon
<> hardspace
<> prettyTermWide body
<> pretty close
)
-- Special case: Absorb parenthesized function application with absorbable body
absorbLast
( Term
Expand All @@ -434,31 +446,35 @@ prettyApp indentFunction pre hasPost f a =
)
)
| isAbsorbableTerm body && not (any hasTrivia [open, ident, close]) =
group' Priority $
nest $
pretty open
<> pretty fn
<> hardspace
<> prettyTermWide body
<> pretty close
( False,
group' Priority $
nest $
pretty open
<> pretty fn
<> hardspace
<> prettyTermWide body
<> pretty close
)
absorbLast (Term (Parenthesized open expr close)) =
absorbParen open expr close
absorbLast arg = group' RegularG $ nest $ pretty arg
(False, absorbParen open expr close)
absorbLast arg = (False, group' RegularG $ nest $ pretty arg)

-- Extract comment before the first function and move it out, to prevent functions being force-expanded
(fWithoutComment, comment') =
mapFirstToken'
((\a'@Ann{preTrivia} -> (a'{preTrivia = []}, preTrivia)) . moveTrailingCommentUp)
f

renderedF = pre <> group' Transparent (absorbApp fWithoutComment)
renderedF = pre <> group' Transparent (absorbApp endsWithAList fWithoutComment)
renderedFUnexpanded = unexpandSpacing' Nothing renderedF

post = if hasPost then line' else mempty

(endsWithAList, lastAbsorbed) = absorbLast a
in pretty comment'
<> ( if isSimple (Application f a) && isJust renderedFUnexpanded
then group' RegularG $ fromJust renderedFUnexpanded <> hardspace <> absorbLast a
else group' RegularG $ renderedF <> line <> absorbLast a <> post
then group' RegularG $ fromJust renderedFUnexpanded <> hardspace <> lastAbsorbed
else group' RegularG $ renderedF <> line <> lastAbsorbed <> post
)
<> (if hasPost && not (null comment') then hardline else mempty)

Expand Down
14 changes: 5 additions & 9 deletions test/diff/apply/out-pure.nix
Original file line number Diff line number Diff line change
Expand Up @@ -155,15 +155,11 @@
utils.lib.eachDefaultSystem (system: { });
}
{
escapeSingleline = libStr.escape [
"\\"
''"''
"\${"
];
escapeMultiline = libStr.replaceStrings [ "\${" "''" ] [
"''\${"
"'''"
];
escapeSingleline = libStr.escape [ "\\" ''"'' "\${" ];
escapeMultiline =
libStr.replaceStrings
[ "\${" "''" ]
[ "''\${" "'''" ];
test =
foo
[
Expand Down
5 changes: 1 addition & 4 deletions test/diff/attr_set/out-pure.nix
Original file line number Diff line number Diff line change
Expand Up @@ -143,10 +143,7 @@
]
++ (if foo then [ bar ] else [ baz ])
++ [ ]
++ (optionals condition [
more
items
]);
++ (optionals condition [ more items ]);
b = with pkgs; [
a
lot
Expand Down
5 changes: 1 addition & 4 deletions test/diff/attr_set/out.nix
Original file line number Diff line number Diff line change
Expand Up @@ -146,10 +146,7 @@
]
++ (if foo then [ bar ] else [ baz ])
++ [ ]
++ (optionals condition [
more
items
]);
++ (optionals condition [ more items ]);
b = with pkgs; [
a
lot
Expand Down
8 changes: 1 addition & 7 deletions test/diff/idioms_lib_2/out-pure.nix
Original file line number Diff line number Diff line change
Expand Up @@ -351,13 +351,7 @@ rec {
Type: string -> a -> a
*/
warn =
if
lib.elem (builtins.getEnv "NIX_ABORT_ON_WARN") [
"1"
"true"
"yes"
]
then
if lib.elem (builtins.getEnv "NIX_ABORT_ON_WARN") [ "1" "true" "yes" ] then
msg:
builtins.trace "warning: ${msg}" (
abort "NIX_ABORT_ON_WARN=true; warnings are treated as unrecoverable errors."
Expand Down
8 changes: 1 addition & 7 deletions test/diff/idioms_lib_2/out.nix
Original file line number Diff line number Diff line change
Expand Up @@ -351,13 +351,7 @@ rec {
Type: string -> a -> a
*/
warn =
if
lib.elem (builtins.getEnv "NIX_ABORT_ON_WARN") [
"1"
"true"
"yes"
]
then
if lib.elem (builtins.getEnv "NIX_ABORT_ON_WARN") [ "1" "true" "yes" ] then
msg:
builtins.trace "warning: ${msg}" (
abort "NIX_ABORT_ON_WARN=true; warnings are treated as unrecoverable errors."
Expand Down
14 changes: 5 additions & 9 deletions test/diff/idioms_lib_3/out-pure.nix
Original file line number Diff line number Diff line change
Expand Up @@ -361,15 +361,11 @@ rec {
else if isString v then
let
lines = filter (v: !isList v) (builtins.split "\n" v);
escapeSingleline = libStr.escape [
"\\"
''"''
"\${"
];
escapeMultiline = libStr.replaceStrings [ "\${" "''" ] [
"''\${"
"'''"
];
escapeSingleline = libStr.escape [ "\\" ''"'' "\${" ];
escapeMultiline =
libStr.replaceStrings
[ "\${" "''" ]
[ "''\${" "'''" ];
singlelineResult =
''"'' + concatStringsSep "\\n" (map escapeSingleline lines) + ''"'';
multilineResult =
Expand Down
14 changes: 5 additions & 9 deletions test/diff/idioms_lib_3/out.nix
Original file line number Diff line number Diff line change
Expand Up @@ -374,15 +374,11 @@ rec {
else if isString v then
let
lines = filter (v: !isList v) (builtins.split "\n" v);
escapeSingleline = libStr.escape [
"\\"
''"''
"\${"
];
escapeMultiline = libStr.replaceStrings [ "\${" "''" ] [
"''\${"
"'''"
];
escapeSingleline = libStr.escape [ "\\" ''"'' "\${" ];
escapeMultiline =
libStr.replaceStrings
[ "\${" "''" ]
[ "''\${" "'''" ];
singlelineResult =
''"'' + concatStringsSep "\\n" (map escapeSingleline lines) + ''"'';
multilineResult =
Expand Down
16 changes: 2 additions & 14 deletions test/diff/idioms_lib_4/out-pure.nix
Original file line number Diff line number Diff line change
Expand Up @@ -771,13 +771,7 @@ rec {
"3" =
# cpu-kernel-environment
if
elemAt l 1 == "linux"
|| elem (elemAt l 2) [
"eabi"
"eabihf"
"elf"
"gnu"
]
elemAt l 1 == "linux" || elem (elemAt l 2) [ "eabi" "eabihf" "elf" "gnu" ]
then
{
cpu = elemAt l 0;
Expand All @@ -788,13 +782,7 @@ rec {
# cpu-vendor-os
else if
elemAt l 1 == "apple"
|| elem (elemAt l 2) [
"wasi"
"redox"
"mmixware"
"ghcjs"
"mingw32"
]
|| elem (elemAt l 2) [ "wasi" "redox" "mmixware" "ghcjs" "mingw32" ]
|| hasPrefix "freebsd" (elemAt l 2)
|| hasPrefix "netbsd" (elemAt l 2)
|| hasPrefix "genode" (elemAt l 2)
Expand Down
16 changes: 2 additions & 14 deletions test/diff/idioms_lib_4/out.nix
Original file line number Diff line number Diff line change
Expand Up @@ -771,13 +771,7 @@ rec {
"3" =
# cpu-kernel-environment
if
elemAt l 1 == "linux"
|| elem (elemAt l 2) [
"eabi"
"eabihf"
"elf"
"gnu"
]
elemAt l 1 == "linux" || elem (elemAt l 2) [ "eabi" "eabihf" "elf" "gnu" ]
then
{
cpu = elemAt l 0;
Expand All @@ -788,13 +782,7 @@ rec {
# cpu-vendor-os
else if
elemAt l 1 == "apple"
|| elem (elemAt l 2) [
"wasi"
"redox"
"mmixware"
"ghcjs"
"mingw32"
]
|| elem (elemAt l 2) [ "wasi" "redox" "mmixware" "ghcjs" "mingw32" ]
|| hasPrefix "freebsd" (elemAt l 2)
|| hasPrefix "netbsd" (elemAt l 2)
|| hasPrefix "genode" (elemAt l 2)
Expand Down
9 changes: 3 additions & 6 deletions test/diff/idioms_nixos_1/out-pure.nix
Original file line number Diff line number Diff line change
Expand Up @@ -290,12 +290,9 @@ in

# Implement consoleLogLevel both in early boot and using sysctl
# (so you don't need to reboot to have changes take effect).
boot.kernelParams =
[ "loglevel=${toString config.boot.consoleLogLevel}" ]
++ optionals config.boot.vesa [
"vga=0x317"
"nomodeset"
];
boot.kernelParams = [
"loglevel=${toString config.boot.consoleLogLevel}"
] ++ optionals config.boot.vesa [ "vga=0x317" "nomodeset" ];

boot.kernel.sysctl."kernel.printk" = mkDefault config.boot.consoleLogLevel;

Expand Down
9 changes: 3 additions & 6 deletions test/diff/idioms_nixos_1/out.nix
Original file line number Diff line number Diff line change
Expand Up @@ -290,12 +290,9 @@ in

# Implement consoleLogLevel both in early boot and using sysctl
# (so you don't need to reboot to have changes take effect).
boot.kernelParams =
[ "loglevel=${toString config.boot.consoleLogLevel}" ]
++ optionals config.boot.vesa [
"vga=0x317"
"nomodeset"
];
boot.kernelParams = [
"loglevel=${toString config.boot.consoleLogLevel}"
] ++ optionals config.boot.vesa [ "vga=0x317" "nomodeset" ];

boot.kernel.sysctl."kernel.printk" = mkDefault config.boot.consoleLogLevel;

Expand Down
Loading