Skip to content

Commit df9bda0

Browse files
committed
Parse inherit names with quotes
1 parent 7e9e06e commit df9bda0

8 files changed

+63
-24
lines changed

CHANGELOG.md

+3
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@
99

1010
## Unreleased
1111

12+
* Parsing fixes
13+
* Quotes in inherit statements (like `inherit "or";`) are now supported.
14+
1215
## 0.6.0 -- 2023-10-31
1316

1417
* Fix escaping of interpolations after dollar signs.

src/Nixfmt/Parser.hs

+34-10
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ import qualified Text.Megaparsec.Char.Lexer as L (decimal)
2626

2727
import Nixfmt.Lexer (lexeme)
2828
import Nixfmt.Types
29-
(Ann, Binder(..), Expression(..), File(..), Fixity(..), Leaf, Operator(..),
29+
(Ann(..), Binder(..), Expression(..), File(..), Fixity(..), Leaf, Operator(..),
3030
ParamAttr(..), Parameter(..), Parser, Path, Selector(..), SimpleSelector(..),
3131
String, StringPart(..), Term(..), Token(..), operators, tokenText)
3232
import Nixfmt.Parser.Float (floatParse)
@@ -103,6 +103,21 @@ interpolation :: Parser StringPart
103103
interpolation = Interpolation <$>
104104
symbol TInterOpen <*> expression <*> rawSymbol TInterClose
105105

106+
-- Interpolation, but only allowing identifiers and simple strings inside
107+
interpolationRestricted :: Parser StringPart
108+
interpolationRestricted = Interpolation <$>
109+
symbol TInterOpen <*>
110+
-- simple string without dynamic interpolations
111+
(Term <$> String <$> do
112+
str <- string
113+
guard $ not $ containsInterpolation str
114+
return str
115+
) <*>
116+
rawSymbol TInterClose
117+
where
118+
containsInterpolation (Ann str _ _) =
119+
any (\part -> case part of { Interpolation _ _ _ -> True; _ -> False }) $ concat str
120+
106121
simpleStringPart :: Parser StringPart
107122
simpleStringPart = TextPart <$> someText (
108123
chunk "\\n" *> pure "\n" <|>
@@ -214,18 +229,25 @@ parens :: Parser Term
214229
parens = Parenthesized <$>
215230
symbol TParenOpen <*> expression <*> symbol TParenClose
216231

232+
simpleSelector :: Parser StringPart -> Parser SimpleSelector
233+
simpleSelector parseInterpolation =
234+
((IDSelector <$> identifier) <|>
235+
(InterpolSelector <$> lexeme parseInterpolation) <|>
236+
(StringSelector <$> lexeme simpleString))
237+
217238
selector :: Maybe (Parser Leaf) -> Parser Selector
218239
selector parseDot = Selector <$>
219-
sequence parseDot <* notFollowedBy path <*>
220-
((IDSelector <$> identifier) <|>
221-
(InterpolSelector <$> lexeme interpolation) <|>
222-
(StringSelector <$> lexeme simpleString)) <*>
223-
optional (liftM2 (,) (reserved KOr) term)
240+
sequence parseDot <* notFollowedBy path <*> simpleSelector interpolation
224241

225242
selectorPath :: Parser [Selector]
226243
selectorPath = (pure <$> selector Nothing) <>
227244
many (selector $ Just $ symbol TDot)
228245

246+
-- Path with a leading dot
247+
selectorPath' :: Parser [Selector]
248+
selectorPath' = many $ try $ selector $ Just $ symbol TDot
249+
250+
-- Everything but selection
229251
simpleTerm :: Parser Term
230252
simpleTerm = (String <$> string) <|> (Path <$> path) <|>
231253
(Token <$> (envPath <|> float <|> integer <|> identifier)) <|>
@@ -234,9 +256,11 @@ simpleTerm = (String <$> string) <|> (Path <$> path) <|>
234256
term :: Parser Term
235257
term = label "term" $ do
236258
t <- simpleTerm
237-
s <- many $ try $ selector $ Just $ symbol TDot
238-
return $ case s of [] -> t
239-
_ -> Selection t s
259+
sel <- selectorPath'
260+
def <- optional (liftM2 (,) (reserved KOr) term)
261+
return $ case sel of
262+
[] -> t
263+
_ -> Selection t sel def
240264

241265
-- ABSTRACTIONS
242266

@@ -271,7 +295,7 @@ abstraction = try (Abstraction <$>
271295

272296
inherit :: Parser Binder
273297
inherit = Inherit <$> reserved KInherit <*> optional parens <*>
274-
many identifier <*> symbol TSemicolon
298+
many (simpleSelector interpolationRestricted) <*> symbol TSemicolon
275299

276300
assignment :: Parser Binder
277301
assignment = Assignment <$>

src/Nixfmt/Pretty.hs

+9-11
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ module Nixfmt.Pretty where
1111
import Prelude hiding (String)
1212

1313
import Data.Char (isSpace)
14-
import Data.Maybe (fromMaybe)
14+
import Data.Maybe (fromMaybe, isNothing)
1515
import Data.Text (Text, isPrefixOf, isSuffixOf, stripPrefix)
1616
import qualified Data.Text as Text
1717
(dropEnd, empty, init, isInfixOf, last, null, strip, takeWhile)
@@ -62,13 +62,9 @@ instance Pretty SimpleSelector where
6262
= prettySimpleString s <> pretty trailing <> pretty leading
6363

6464
instance Pretty Selector where
65-
pretty (Selector dot sel Nothing)
65+
pretty (Selector dot sel)
6666
= pretty dot <> pretty sel
6767

68-
pretty (Selector dot sel (Just (kw, def)))
69-
= pretty dot <> pretty sel
70-
<> hardspace <> pretty kw <> hardspace <> pretty def
71-
7268
instance Pretty Binder where
7369
pretty (Inherit inherit Nothing ids semicolon)
7470
= base $ group (pretty inherit <> softline
@@ -89,7 +85,9 @@ prettyTerm :: Term -> Doc
8985
prettyTerm (Token t) = pretty t
9086
prettyTerm (String s) = pretty s
9187
prettyTerm (Path p) = pretty p
92-
prettyTerm (Selection term selectors) = pretty term <> hcat selectors
88+
prettyTerm (Selection term selectors Nothing) = pretty term <> hcat selectors
89+
prettyTerm (Selection term selectors (Just (kw, def))) =
90+
pretty term <> hcat selectors <> hardspace <> pretty kw <> hardspace <> pretty def
9391

9492
prettyTerm (List (Ann paropen Nothing []) [] parclose)
9593
= pretty paropen <> hardspace <> pretty parclose
@@ -264,13 +262,13 @@ instance Pretty [Token] where
264262
-- STRINGS
265263

266264
isSimpleSelector :: Selector -> Bool
267-
isSimpleSelector (Selector _ (IDSelector _) Nothing) = True
268-
isSimpleSelector _ = False
265+
isSimpleSelector (Selector _ (IDSelector _)) = True
266+
isSimpleSelector _ = False
269267

270268
isSimple :: Expression -> Bool
271269
isSimple (Term (Token (Ann (Identifier _) Nothing []))) = True
272-
isSimple (Term (Selection t selectors))
273-
= isSimple (Term t) && all isSimpleSelector selectors
270+
isSimple (Term (Selection t selectors def))
271+
= isSimple (Term t) && all isSimpleSelector selectors && isNothing def
274272
isSimple _ = False
275273

276274
hasQuotes :: [StringPart] -> Bool

src/Nixfmt/Types.hs

+4-3
Original file line numberDiff line numberDiff line change
@@ -57,11 +57,12 @@ data SimpleSelector
5757
deriving (Eq, Show)
5858

5959
data Selector
60-
= Selector (Maybe Leaf) SimpleSelector (Maybe (Leaf, Term))
60+
-- `.selector`
61+
= Selector (Maybe Leaf) SimpleSelector
6162
deriving (Eq, Show)
6263

6364
data Binder
64-
= Inherit Leaf (Maybe Term) [Leaf] Leaf
65+
= Inherit Leaf (Maybe Term) [SimpleSelector] Leaf
6566
| Assignment [Selector] Leaf Expression Leaf
6667
deriving (Eq, Show)
6768

@@ -71,7 +72,7 @@ data Term
7172
| Path Path
7273
| List Leaf [Term] Leaf
7374
| Set (Maybe Leaf) Leaf [Binder] Leaf
74-
| Selection Term [Selector]
75+
| Selection Term [Selector] (Maybe (Leaf, Term))
7576
| Parenthesized Leaf Expression Leaf
7677
deriving (Eq, Show)
7778

test/correct/quotes-in-inherit-2.nix

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
let
2+
foo = 1;
3+
"bar" = 2;
4+
${"baz"} = 3;
5+
${"in"} = 4;
6+
7+
in { inherit ${"foo"} bar "baz" "in"; }

test/correct/quotes-in-inherit.nix

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{ inherit ({ "in" = 1; }) "in"; }
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
let
2+
bar = "bar";
3+
4+
in { inherit ${bar}; }
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{ inherit ${"foo" + "bar"}; }

0 commit comments

Comments
 (0)