Skip to content

Commit c9a3f8d

Browse files
committed
Always read shipped config file (#133)
Upon installation a configuration file will always be created if missing. But if a user already installed jbeam-edit, a configuration was created, then the user updates to a new version, then the new installation would use older configuration which was in AppData. This patch will load the shipped configuration file and the AppData version if it exists, preferring the the AppData settings if availabale. Since jbeam-edit now both loads a config file in AppData as well as the shipped minimal configuration, I added a test which proves that combining the configurations at runtime works. I also improved logging in the test suite to be able debug issues easier.
1 parent 5132e4a commit c9a3f8d

File tree

11 files changed

+93
-52
lines changed

11 files changed

+93
-52
lines changed

.github/workflows/build-and-release.yaml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,8 +73,11 @@ jobs:
7373
- name: Build dependencies, good to do separate for caching
7474
run: cabal build --project-file cabal.project.release --only-dependencies
7575
- name: Build LSP executable
76+
shell: bash
7677
run: |
7778
cabal build exe:jbeam-lsp-server --project-file cabal.project.release || true
79+
LSP_FOLDER=$(find dist-newstyle -path '*/build/jbeam-lsp-server')
80+
cp -r examples $LSP_FOLDER/
7881
- name: Build main executable
7982
run: cabal build exe:jbeam-edit --project-file cabal.project.release
8083
- name: Run tests (GHC ${{ matrix.ghc }})

cabal.project

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
packages: .
22
optimization: False
3+
test-options: --diff-context=0 --color
34

45
package *
56
tests: False

src/JbeamEdit/Formatting.hs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ module JbeamEdit.Formatting (
22
formatNode,
33
formatWithCursor,
44
formatScalarNode,
5-
newRuleSet,
65
RuleSet (..),
76
) where
87

@@ -30,7 +29,6 @@ import JbeamEdit.Formatting.Rules (
3029
findPropertiesForCursor,
3130
forceComplexNewLine,
3231
lookupIndentProperty,
33-
newRuleSet,
3432
noComplexNewLine,
3533
)
3634

src/JbeamEdit/Formatting/Config.hs

Lines changed: 22 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
module JbeamEdit.Formatting.Config (localRuleFile, readFormattingConfig, copyToConfigDir, ConfigType (..)) where
44

5+
import Data.Foldable (traverse_)
6+
import Data.Text qualified as T
57
import GHC.IO.Exception (IOErrorType (NoSuchThing))
68
import JbeamEdit.Formatting.Rules
79
import JbeamEdit.IOUtils
@@ -59,8 +61,12 @@ copyConfigFile :: OsPath -> ConfigType -> IO ()
5961
copyConfigFile dest configType = do
6062
createDirectoryIfMissing True (takeDirectory dest)
6163
source <- getJbflSourcePath configType
62-
destPath <- decodeUtf dest
63-
putStrLn ("installing " ++ show configType ++ " config file to " ++ destPath)
64+
putErrorLine
65+
( "installing "
66+
<> T.pack (show configType)
67+
<> " config file to "
68+
<> T.pack (show dest)
69+
)
6470
copyFile source dest
6571

6672
copyToConfigDir :: ConfigType -> IO ()
@@ -76,14 +82,18 @@ createRuleFileIfDoesNotExist configPath =
7682
readFormattingConfig :: Maybe OsPath -> IO RuleSet
7783
readFormattingConfig maybeJbflPath = do
7884
configDir <- getConfigDir
79-
case maybeJbflPath of
80-
Just jbfl ->
81-
decodeUtf jbfl
82-
>>= (\a -> putErrorStringLn $ "Loading jbfl: " ++ a)
83-
Nothing ->
84-
createRuleFileIfDoesNotExist (configDir </> userRuleFile)
85+
traverse_
86+
(\jbfl -> putErrorLine $ "Loading jbfl: " <> T.pack (show jbfl))
87+
maybeJbflPath
88+
createRuleFileIfDoesNotExist (configDir </> userRuleFile)
8589
configPath <- getConfigPath maybeJbflPath configDir
86-
contents <- tryReadFile [NoSuchThing] configPath
87-
case contents >>= parseDSL of
88-
Right rs -> pure rs
89-
Left err -> putErrorLine err $> newRuleSet
90+
userCfg <- tryReadFile [NoSuchThing] configPath
91+
defaultRulesetPath <- getJbflSourcePath MinimalConfig
92+
defaultCfg <- tryReadFile [] defaultRulesetPath
93+
case (userCfg >>= parseDSL, defaultCfg >>= parseDSL) of
94+
(Right rs, Right defaultRs) -> pure (rs <> defaultRs)
95+
(Left err, Right defaultRs) -> putErrorLine err $> defaultRs
96+
(_, Left err) ->
97+
let err' =
98+
"Failed to parse default ruleset. Please consider making bugreport. \n" <> err
99+
in putErrorLine err' >> mempty

src/JbeamEdit/Formatting/Rules.hs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@ module JbeamEdit.Formatting.Rules (
1919
noComplexNewLine,
2020
forceComplexNewLine,
2121
lookupIndentProperty,
22-
newRuleSet,
2322
findPropertiesForCursor,
2423
) where
2524

@@ -57,6 +56,12 @@ newtype NodePattern
5756
= NodePattern (Seq NodePatternSelector)
5857
deriving stock (Eq, Read, Show)
5958

59+
instance Monoid RuleSet where
60+
mempty = RuleSet M.empty
61+
62+
instance Semigroup RuleSet where
63+
(RuleSet rs1) <> (RuleSet rs2) = RuleSet (M.unionWith M.union rs1 rs2)
64+
6065
instance Ord NodePattern where
6166
compare (NodePattern a) (NodePattern b) =
6267
case on compare (Down . Seq.length) a b of
@@ -161,9 +166,6 @@ newtype RuleSet
161166
= RuleSet (Map NodePattern Rule)
162167
deriving stock (Eq, Read, Show)
163168

164-
newRuleSet :: RuleSet
165-
newRuleSet = RuleSet M.empty
166-
167169
lookupProp :: (Eq a, Read a, Show a) => PropertyKey a -> Rule -> Maybe a
168170
lookupProp targetKey m =
169171
case M.lookup (SomeKey targetKey) m of

src/JbeamEdit/IOUtils.hs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import Data.Text (Text)
99
import Data.Text qualified as T (append, pack, unpack)
1010
import GHC.IO.Exception (IOErrorType, IOException (IOError))
1111
import JbeamEdit.Core.Node (Node)
12-
import JbeamEdit.Formatting (formatNode, newRuleSet)
12+
import JbeamEdit.Formatting (formatNode)
1313
import System.File.OsPath qualified as OS
1414
import System.IO (hPutStrLn, stderr)
1515
import System.OsPath
@@ -24,7 +24,7 @@ reportInvalidNodes :: Text -> [Node] -> IO ()
2424
reportInvalidNodes msg nodes =
2525
unless (null nodes) $ do
2626
putErrorLine msg
27-
mapM_ (putErrorLine . formatNode newRuleSet) nodes
27+
mapM_ (putErrorLine . formatNode mempty) nodes
2828

2929
ioErrorMsg
3030
:: [IOErrorType]

src/JbeamEdit/Parsing/DSL.hs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,7 @@ ruleSetParser = RuleSet . M.fromListWith M.union . separateRulesets <$> MP.some
142142

143143
parseDSL :: LBS.ByteString -> Either Text RuleSet
144144
parseDSL input
145-
| LBS.null input = pure newRuleSet
145+
| LBS.null input = pure mempty
146146
| otherwise =
147147
first formatErrors . MP.parse (ruleSetParser <* MP.eof) "<input>" $
148148
input

test-extra/language-server/WorkspaceLspSpec.hs

Lines changed: 36 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -4,35 +4,21 @@ import Control.Monad.IO.Class (liftIO)
44
import Data.Text qualified as T (pack)
55
import Language.LSP.Protocol.Types as LSP
66
import Language.LSP.Test
7-
import System.Directory (getCurrentDirectory)
87
import System.FilePath ((</>))
98
import System.IO qualified as IO (readFile)
109
import Test.Hspec
1110

12-
exampleJbflFilepath :: FilePath -> FilePath
13-
exampleJbflFilepath cwd =
14-
cwd
15-
</> "examples"
16-
</> "jbfl"
17-
</> "minimal.jbfl"
18-
19-
spec :: Spec
20-
spec = do
21-
cwd <- runIO getCurrentDirectory
22-
workspaceSpec cwd
23-
2411
runJbeamSession :: FilePath -> Session a -> IO a
25-
runJbeamSession cwd =
26-
runSession
27-
("jbeam-lsp-server -c " <> exampleJbflFilepath cwd)
28-
fullLatestClientCaps
29-
"examples"
30-
31-
formatVerify :: Session ()
32-
formatVerify = do
33-
let jbeamFile = "jbeam" </> "fender.jbeam"
34-
expectedFile = "examples" </> "formatted_jbeam" </> "fender-minimal-jbfl.jbeam"
35-
12+
runJbeamSession jbflFile = runSessionWithConfig cfg cmd fullLatestClientCaps "examples"
13+
where
14+
cmd = "jbeam-lsp-server -c " <> jbflFile
15+
cfg =
16+
defaultConfig
17+
{ logStdErr = True
18+
}
19+
20+
formatVerify :: FilePath -> FilePath -> Session ()
21+
formatVerify jbeamFile expectedFile = do
3622
doc <- openDoc jbeamFile "jbeam"
3723

3824
formatDoc doc (LSP.FormattingOptions 0 False Nothing Nothing Nothing)
@@ -42,9 +28,29 @@ formatVerify = do
4228

4329
liftIO $ formatted `shouldBe` expected
4430

45-
workspaceSpec :: FilePath -> Spec
46-
workspaceSpec cwd =
47-
let label =
48-
describe "JBeam LSP Formatter"
49-
. it "formats a single JBeam file with a single JBFL rule correctly"
50-
in label . runJbeamSession cwd $ formatVerify
31+
jbflTests :: [(FilePath, FilePath, FilePath)]
32+
jbflTests =
33+
[
34+
( "jbeam" </> "fender.jbeam"
35+
, "examples" </> "formatted_jbeam" </> "fender-minimal-jbfl.jbeam"
36+
, "examples" </> "jbfl" </> "minimal.jbfl"
37+
)
38+
,
39+
( "jbeam" </> "fender.jbeam"
40+
, "test-extra/language-server/data/fender-custom-minimal-jbfl.jbeam"
41+
, "test-extra/language-server/data/custom-minimal.jbfl"
42+
)
43+
]
44+
45+
workspaceSpec :: Spec
46+
workspaceSpec =
47+
describe "JBeam LSP Formatter" $
48+
mapM_
49+
( \(jbeam, expected, jbfl) ->
50+
it ("formats " <> jbeam <> " correctly") $
51+
runJbeamSession jbfl (formatVerify jbeam expected)
52+
)
53+
jbflTests
54+
55+
spec :: Spec
56+
spec = workspaceSpec
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
.*.nodes[*][*] {
2+
PadAmount: 8;
3+
}

test/FormattingSpec.hs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ spec = do
8787
applySpecOnInput
8888
descFun
8989
shouldBe
90-
(formatWithCursor newRuleSet newCursor node)
90+
(formatWithCursor mempty newCursor node)
9191
(T.pack jbeam)
9292
descFun jbeam node = "should format " ++ show node ++ " as " ++ jbeam
9393
specs =

0 commit comments

Comments
 (0)