From dffb7f65818f94002153f5e46e4bd485681dd390 Mon Sep 17 00:00:00 2001 From: Sridhar Ratnakumar Date: Wed, 6 Mar 2024 16:04:16 -0500 Subject: [PATCH 01/10] wip --- emanote/src/Emanote/CLI.hs | 13 ++++++++----- emanote/src/Emanote/Model/Stork.hs | 2 +- emanote/src/Emanote/Source/Loc.hs | 24 +++++++++++++++--------- emanote/src/Emanote/Source/Patch.hs | 2 ++ flake.lock | 7 ++++--- flake.nix | 3 ++- 6 files changed, 32 insertions(+), 19 deletions(-) diff --git a/emanote/src/Emanote/CLI.hs b/emanote/src/Emanote/CLI.hs index 9eee61c4e..b409c0034 100644 --- a/emanote/src/Emanote/CLI.hs +++ b/emanote/src/Emanote/CLI.hs @@ -17,7 +17,7 @@ import Relude import UnliftIO.Directory (getCurrentDirectory) data Cli = Cli - { layers :: NonEmpty FilePath + { layers :: NonEmpty (FilePath, Maybe FilePath) , allowBrokenLinks :: Bool , cmd :: Cmd } @@ -28,7 +28,7 @@ data Cmd cliParser :: FilePath -> Parser Cli cliParser cwd = do - layers <- pathList (one cwd) + layers <- pathList (one (cwd, Nothing)) allowBrokenLinks <- switch (long "allow-broken-links" <> help "Report but do not fail on broken links") cmd <- fmap Cmd_Ema Ema.CLI.cliParser @@ -44,10 +44,13 @@ cliParser cwd = do , value defaultPath , help "List of (semicolon delimited) notebook folders to 'union mount', with the left-side folders being overlaid on top of the right-side ones. The default layer is implicitly included at the end of this list." ] - pathListReader :: ReadM (NonEmpty FilePath) - pathListReader = + pathListReader :: ReadM (NonEmpty (FilePath, Maybe FilePath)) + pathListReader = do + let partition s = + T.breakOn "@" s + & second (\x -> if T.null s then Nothing else Just $ T.drop 1 x) maybeReader $ \paths -> - nonEmpty $ fmap toString $ T.split (== ';') . toText $ paths + nonEmpty $ fmap (bimap toString (fmap toString) . partition) $ T.split (== ';') . toText $ paths parseCli' :: FilePath -> ParserInfo Cli parseCli' cwd = diff --git a/emanote/src/Emanote/Model/Stork.hs b/emanote/src/Emanote/Model/Stork.hs index 801ad59c4..06b7c5e6f 100644 --- a/emanote/src/Emanote/Model/Stork.hs +++ b/emanote/src/Emanote/Model/Stork.hs @@ -33,7 +33,7 @@ renderStorkIndex model = do storkFiles :: Model -> [File] storkFiles model = flip mapMaybe (Ix.toList (model ^. M.modelNotes)) $ \note -> do - baseDir <- Loc.locPath . fst <$> note ^. N.noteSource + baseDir <- fst . Loc.locPath . fst <$> note ^. N.noteSource let fp = ((baseDir ) $ R.withLmlRoute R.encodeRoute $ note ^. N.noteRoute) ft = case note ^. N.noteRoute of R.LMLRoute_Md _ -> FileType_Markdown diff --git a/emanote/src/Emanote/Source/Loc.hs b/emanote/src/Emanote/Source/Loc.hs index 7e2ac11ca..a5de21088 100644 --- a/emanote/src/Emanote/Source/Loc.hs +++ b/emanote/src/Emanote/Source/Loc.hs @@ -12,6 +12,7 @@ module Emanote.Source.Loc ( -- * Using a `Loc` locResolve, locPath, + locMountPoint, -- * Dealing with layers of locs LocLayers, @@ -28,8 +29,8 @@ import System.FilePath (()) The order here matters. Top = higher precedence. -} data Loc - = -- | The Int argument specifies the precedence (lower value = higher precedence) - LocUser Int FilePath + = -- | The Int argument specifies the precedence (lower value = higher precedence). The last argument is "mount point" + LocUser Int FilePath (Maybe FilePath) | -- | The default location (ie., emanote default layer) LocDefault FilePath deriving stock (Eq, Ord, Show, Generic) @@ -45,7 +46,7 @@ userLayersToSearch :: LocLayers -> [FilePath] userLayersToSearch = mapMaybe ( \case - LocUser _ fp -> Just fp + LocUser _ fp _ -> Just fp LocDefault _ -> Nothing ) . Set.toAscList @@ -53,17 +54,22 @@ userLayersToSearch = defaultLayer :: FilePath -> Loc defaultLayer = LocDefault -userLayers :: NonEmpty FilePath -> Set Loc +userLayers :: NonEmpty (FilePath, Maybe FilePath) -> Set Loc userLayers paths = fromList $ zip [1 ..] (toList paths) - <&> uncurry LocUser + <&> (\(a, (b, c)) -> LocUser a b c) -- | Return the effective path of a file. locResolve :: (Loc, FilePath) -> FilePath -locResolve (loc, fp) = locPath loc fp +locResolve (loc, fp) = fst (locPath loc) fp -locPath :: Loc -> FilePath +locPath :: Loc -> (FilePath, Maybe FilePath) locPath = \case - LocUser _ fp -> fp - LocDefault fp -> fp + LocUser _ fp m -> (fp, m) + LocDefault fp -> (fp, Nothing) + +locMountPoint :: Loc -> Maybe FilePath +locMountPoint = \case + LocUser _ _ mountPoint -> mountPoint + LocDefault _ -> Nothing diff --git a/emanote/src/Emanote/Source/Patch.hs b/emanote/src/Emanote/Source/Patch.hs index 17a6863e9..58c496a1c 100644 --- a/emanote/src/Emanote/Source/Patch.hs +++ b/emanote/src/Emanote/Source/Patch.hs @@ -72,6 +72,7 @@ patchModel' :: UM.FileAction (NonEmpty (Loc, FilePath)) -> m (ModelEma -> ModelEma) patchModel' layers noteF storkIndexTVar scriptingEngine fpType fp action = do + print fp case fpType of R.LMLType lmlType -> do case R.mkLMLRouteFromKnownFilePath lmlType fp of @@ -91,6 +92,7 @@ patchModel' layers noteF storkIndexTVar scriptingEngine fpType fp action = do case action of UM.Refresh refreshAction overlays -> do let fpAbs = head overlays + print fpAbs s <- readRefreshedFile refreshAction $ locResolve fpAbs note <- N.parseNote scriptingEngine (userLayersToSearch layers) r fpAbs (decodeUtf8 s) pure $ M.modelInsertNote $ noteF note diff --git a/flake.lock b/flake.lock index 4b8d838bc..3519e60ca 100644 --- a/flake.lock +++ b/flake.lock @@ -232,15 +232,16 @@ "unionmount": { "flake": false, "locked": { - "lastModified": 1691619410, - "narHash": "sha256-V9/OcGu9cy4kV9jta12A6w5BEj8awSEVYrXPpg8YckQ=", + "lastModified": 1709758996, + "narHash": "sha256-jPiuBY4/k2VVWim9OHgDLf0Dcw2S6JRuSLCCNoclsZw=", "owner": "srid", "repo": "unionmount", - "rev": "ed73b627f88c8f021f41ba4b518ba41beff9df42", + "rev": "6bf00a91402562fcfe5cf49c62b7a4047fb82ff6", "type": "github" }, "original": { "owner": "srid", + "ref": "mount-point", "repo": "unionmount", "type": "github" } diff --git a/flake.nix b/flake.nix index 6a848db91..0aca6d64e 100644 --- a/flake.nix +++ b/flake.nix @@ -23,7 +23,8 @@ heist-extra.url = "github:srid/heist-extra"; heist-extra.flake = false; - unionmount.url = "github:srid/unionmount"; + unionmount.url = "github:srid/unionmount/mount-point"; + # unionmount.url = "path:/Users/srid/code/unionmount"; unionmount.flake = false; commonmark-simple.url = "github:srid/commonmark-simple"; From 6c83f20d87c6e37553fbb06fc978aa83bf5e827a Mon Sep 17 00:00:00 2001 From: Sridhar Ratnakumar Date: Wed, 6 Mar 2024 16:20:52 -0500 Subject: [PATCH 02/10] refacator the flake module --- flake.nix | 3 +-- nix/flake-module.nix | 34 +++++++++++++++++++++------------- 2 files changed, 22 insertions(+), 15 deletions(-) diff --git a/flake.nix b/flake.nix index 0aca6d64e..a7c86ba45 100644 --- a/flake.nix +++ b/flake.nix @@ -177,8 +177,7 @@ package = config.packages.default; sites = { "docs" = { - layers = [ ./docs ]; - layersString = [ "./docs" ]; + layers = [{ path = ./docs; pathString = "./docs"; }]; allowBrokenLinks = true; # A couple, by design, in markdown.md prettyUrls = true; }; diff --git a/nix/flake-module.nix b/nix/flake-module.nix index 54a5d97ea..5bcdfaee6 100644 --- a/nix/flake-module.nix +++ b/nix/flake-module.nix @@ -31,17 +31,25 @@ in description = "Emanote sites"; type = types.attrsOf (types.submodule { options = { - layers = mkOption { - type = types.listOf types.path; - description = ''List of directory paths to run Emanote on''; - }; - # HACK: I can't seem to be able to convert `path` to a - # relative local path; so this is necessary. - # - # cf. https://discourse.nixos.org/t/converting-from-types-path-to-types-str/19405?u=srid - layersString = mkOption { - type = types.listOf types.str; - description = ''Like `layers` but local (not in Nix store)''; + layers = lib.mkOption { + description = "List of layers to use for the site"; + type = types.listOf (types.submodule ({ config, ... }: { + options = { + path = mkOption { + type = types.path; + description = ''Directory path to notes''; + }; + # HACK: I can't seem to be able to convert `path` to a + # relative local path; so this is necessary. + # + # cf. https://discourse.nixos.org/t/converting-from-types-path-to-types-str/19405?u=srid + pathString = mkOption { + type = types.str; + description = ''Like `path` but local (not in Nix store)''; + default = builtins.toString config.path; + }; + }; + })); }; # TODO: Consolidate all these options below with those of home-manager-module.nix port = mkOption { @@ -96,7 +104,7 @@ in runtimeInputs = [ config.emanote.package ]; text = let - layers = lib.concatStringsSep ";" cfg.layersString; + layers = lib.concatStringsSep ";" (builtins.map (x: x.pathString) cfg.layers); in '' set -xe @@ -123,7 +131,7 @@ in mkdir -p $out cp ${configFile} $out/index.yaml ''; - layers = lib.concatStringsSep ";" cfg.layers; + layers = lib.concatStringsSep ";" (builtins.map (x: x.path) cfg.layers); in pkgs.runCommand "emanote-static-website-${name}" { meta.description = "Contents of the statically-generated Emanote website for ${name}"; } From 1801f897a7670ecdbb62a89d37e38b4840903fdd Mon Sep 17 00:00:00 2001 From: Sridhar Ratnakumar Date: Wed, 6 Mar 2024 16:23:51 -0500 Subject: [PATCH 03/10] mp --- nix/flake-module.nix | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/nix/flake-module.nix b/nix/flake-module.nix index 5bcdfaee6..14c30bdc5 100644 --- a/nix/flake-module.nix +++ b/nix/flake-module.nix @@ -48,6 +48,23 @@ in description = ''Like `path` but local (not in Nix store)''; default = builtins.toString config.path; }; + mountPoint = mkOption { + type = types.nullOr types.str; + description = ''Mount point for the layer''; + default = null; + }; + outputs.layer = mkOption { + type = types.str; + description = ''Layer spec''; + readOnly = true; + default = if config.mountPoint == null then "${config.path}" else "${config.path}@${config.mountPoint}"; + }; + outputs.layerString = mkOption { + type = types.str; + description = ''Layer spec''; + readOnly = true; + default = if config.mountPoint == null then config.pathString else "${config.pathString}@${config.mountPoint}"; + }; }; })); }; @@ -104,7 +121,7 @@ in runtimeInputs = [ config.emanote.package ]; text = let - layers = lib.concatStringsSep ";" (builtins.map (x: x.pathString) cfg.layers); + layers = lib.concatStringsSep ";" (builtins.map (x: x.outputs.layerString) cfg.layers); in '' set -xe @@ -131,7 +148,7 @@ in mkdir -p $out cp ${configFile} $out/index.yaml ''; - layers = lib.concatStringsSep ";" (builtins.map (x: x.path) cfg.layers); + layers = lib.concatStringsSep ";" (builtins.map (x: x.outputs.layer) cfg.layers); in pkgs.runCommand "emanote-static-website-${name}" { meta.description = "Contents of the statically-generated Emanote website for ${name}"; } From 7c59a6585b5db501d7c9180a51f58bec9a382604 Mon Sep 17 00:00:00 2001 From: Sridhar Ratnakumar Date: Sat, 9 Mar 2024 13:47:35 -0500 Subject: [PATCH 04/10] Update unionmount --- flake.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/flake.lock b/flake.lock index 3519e60ca..a35a231fb 100644 --- a/flake.lock +++ b/flake.lock @@ -232,11 +232,11 @@ "unionmount": { "flake": false, "locked": { - "lastModified": 1709758996, - "narHash": "sha256-jPiuBY4/k2VVWim9OHgDLf0Dcw2S6JRuSLCCNoclsZw=", + "lastModified": 1710009973, + "narHash": "sha256-hSj8Gx9d9dYabBRAkk0IXgeYWKEyiFxXSbbnQasoNWo=", "owner": "srid", "repo": "unionmount", - "rev": "6bf00a91402562fcfe5cf49c62b7a4047fb82ff6", + "rev": "464c9e89ae1f0163c10dc28431d417952680144b", "type": "github" }, "original": { From c72e9d007d360a36022ce2d5897c4203f71eb3c7 Mon Sep 17 00:00:00 2001 From: Sridhar Ratnakumar Date: Sat, 9 Mar 2024 13:52:40 -0500 Subject: [PATCH 05/10] Update unionmoiunt back to master --- flake.lock | 5 ++--- flake.nix | 3 +-- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/flake.lock b/flake.lock index a35a231fb..b0beb4fd9 100644 --- a/flake.lock +++ b/flake.lock @@ -232,16 +232,15 @@ "unionmount": { "flake": false, "locked": { - "lastModified": 1710009973, + "lastModified": 1710010257, "narHash": "sha256-hSj8Gx9d9dYabBRAkk0IXgeYWKEyiFxXSbbnQasoNWo=", "owner": "srid", "repo": "unionmount", - "rev": "464c9e89ae1f0163c10dc28431d417952680144b", + "rev": "fb401ce6030e0f516ea105e1f5c400260b3ade33", "type": "github" }, "original": { "owner": "srid", - "ref": "mount-point", "repo": "unionmount", "type": "github" } diff --git a/flake.nix b/flake.nix index a7c86ba45..d9eab81f9 100644 --- a/flake.nix +++ b/flake.nix @@ -23,8 +23,7 @@ heist-extra.url = "github:srid/heist-extra"; heist-extra.flake = false; - unionmount.url = "github:srid/unionmount/mount-point"; - # unionmount.url = "path:/Users/srid/code/unionmount"; + unionmount.url = "github:srid/unionmount"; unionmount.flake = false; commonmark-simple.url = "github:srid/commonmark-simple"; From e8abd804f92031a534624e002b5b9035fd8eea09 Mon Sep 17 00:00:00 2001 From: Sridhar Ratnakumar Date: Sun, 10 Mar 2024 10:01:47 -0400 Subject: [PATCH 06/10] up and disbale tst --- flake.lock | 6 +++--- flake.nix | 1 + 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/flake.lock b/flake.lock index b0beb4fd9..4e5bfd545 100644 --- a/flake.lock +++ b/flake.lock @@ -232,11 +232,11 @@ "unionmount": { "flake": false, "locked": { - "lastModified": 1710010257, - "narHash": "sha256-hSj8Gx9d9dYabBRAkk0IXgeYWKEyiFxXSbbnQasoNWo=", + "lastModified": 1710078535, + "narHash": "sha256-gKBgBtuiRTD3/3EeY8aMgFzuaSEffJacBxsCB3ct1eg=", "owner": "srid", "repo": "unionmount", - "rev": "fb401ce6030e0f516ea105e1f5c400260b3ade33", + "rev": "41ae982fa118770bf4d3a3f2d48ac1ffb61c9f09", "type": "github" }, "original": { diff --git a/flake.nix b/flake.nix index 2a7a5c85b..d81450ef4 100644 --- a/flake.nix +++ b/flake.nix @@ -90,6 +90,7 @@ tagtree.jailbreak = true; tailwind.broken = false; tailwind.jailbreak = true; + unionmount.check = !pkgs.stdenv.isDarwin; # garnix: Slow M1 builder emanote = { name, pkgs, self, super, ... }: { check = false; extraBuildDepends = [ pkgs.stork ]; From ceca1b95ff8259895a2cc6e6f166725ae423bf85 Mon Sep 17 00:00:00 2001 From: Sridhar Ratnakumar Date: Sun, 10 Mar 2024 10:35:16 -0400 Subject: [PATCH 07/10] rm print --- emanote/src/Emanote/Source/Patch.hs | 2 -- 1 file changed, 2 deletions(-) diff --git a/emanote/src/Emanote/Source/Patch.hs b/emanote/src/Emanote/Source/Patch.hs index 58c496a1c..17a6863e9 100644 --- a/emanote/src/Emanote/Source/Patch.hs +++ b/emanote/src/Emanote/Source/Patch.hs @@ -72,7 +72,6 @@ patchModel' :: UM.FileAction (NonEmpty (Loc, FilePath)) -> m (ModelEma -> ModelEma) patchModel' layers noteF storkIndexTVar scriptingEngine fpType fp action = do - print fp case fpType of R.LMLType lmlType -> do case R.mkLMLRouteFromKnownFilePath lmlType fp of @@ -92,7 +91,6 @@ patchModel' layers noteF storkIndexTVar scriptingEngine fpType fp action = do case action of UM.Refresh refreshAction overlays -> do let fpAbs = head overlays - print fpAbs s <- readRefreshedFile refreshAction $ locResolve fpAbs note <- N.parseNote scriptingEngine (userLayersToSearch layers) r fpAbs (decodeUtf8 s) pure $ M.modelInsertNote $ noteF note From ada58e9ac2777c320466f0569f36d97e88fbb904 Mon Sep 17 00:00:00 2001 From: Sridhar Ratnakumar Date: Sun, 10 Mar 2024 10:40:40 -0400 Subject: [PATCH 08/10] drop LocLayers alias --- emanote/src/Emanote/Source/Loc.hs | 11 ++++------- emanote/src/Emanote/Source/Patch.hs | 12 ++++++------ 2 files changed, 10 insertions(+), 13 deletions(-) diff --git a/emanote/src/Emanote/Source/Loc.hs b/emanote/src/Emanote/Source/Loc.hs index a5de21088..20243b146 100644 --- a/emanote/src/Emanote/Source/Loc.hs +++ b/emanote/src/Emanote/Source/Loc.hs @@ -15,7 +15,6 @@ module Emanote.Source.Loc ( locMountPoint, -- * Dealing with layers of locs - LocLayers, userLayersToSearch, ) where @@ -36,13 +35,11 @@ data Loc deriving stock (Eq, Ord, Show, Generic) deriving anyclass (Aeson.ToJSON) -type LocLayers = Set Loc - {- | List of user layers, highest precedent being at first. This is useful to delay searching for content in layers. -} -userLayersToSearch :: LocLayers -> [FilePath] +userLayersToSearch :: Set Loc -> [FilePath] userLayersToSearch = mapMaybe ( \case @@ -56,9 +53,9 @@ defaultLayer = LocDefault userLayers :: NonEmpty (FilePath, Maybe FilePath) -> Set Loc userLayers paths = - fromList - $ zip [1 ..] (toList paths) - <&> (\(a, (b, c)) -> LocUser a b c) + fromList $ + zip [1 ..] (toList paths) + <&> (\(a, (b, c)) -> LocUser a b c) -- | Return the effective path of a file. locResolve :: (Loc, FilePath) -> FilePath diff --git a/emanote/src/Emanote/Source/Patch.hs b/emanote/src/Emanote/Source/Patch.hs index 17a6863e9..bbb57bb3e 100644 --- a/emanote/src/Emanote/Source/Patch.hs +++ b/emanote/src/Emanote/Source/Patch.hs @@ -22,7 +22,7 @@ import Emanote.Prelude ( logD, ) import Emanote.Route qualified as R -import Emanote.Source.Loc (Loc, LocLayers, locResolve, userLayersToSearch) +import Emanote.Source.Loc (Loc, locResolve, userLayersToSearch) import Emanote.Source.Pattern (filePatterns, ignorePatterns) import Heist.Extra.TemplateState qualified as T import Optics.Operators ((%~)) @@ -36,7 +36,7 @@ import UnliftIO.Directory (doesDirectoryExist) -- | Map a filesystem change to the corresponding model change. patchModel :: (MonadIO m, MonadLogger m, MonadLoggerIO m) => - LocLayers -> + Set Loc -> (N.Note -> N.Note) -> Stork.IndexVar -> -- | Lua scripting engine @@ -59,7 +59,7 @@ patchModel layers noteF storkIndexTVar scriptingEngine fpType fp action = do -- | Map a filesystem change to the corresponding model change. patchModel' :: (MonadIO m, MonadLogger m) => - LocLayers -> + Set Loc -> (N.Note -> N.Note) -> Stork.IndexVar -> -- | Lua scripting engine @@ -107,9 +107,9 @@ patchModel' layers noteF storkIndexTVar scriptingEngine fpType fp action = do let fpAbs = locResolve overlay traverseToSnd (readRefreshedFile refreshAction) fpAbs sData <- - liftIO - $ either (throwIO . BadInput) pure - $ SD.parseSDataCascading r yamlContents + liftIO $ + either (throwIO . BadInput) pure $ + SD.parseSDataCascading r yamlContents pure $ M.modelInsertData sData UM.Delete -> do log $ "Removing data: " <> toText fp From d6789bc7fe06ca7d27e93a25e129c6a65f91e2d0 Mon Sep 17 00:00:00 2001 From: Sridhar Ratnakumar Date: Sun, 10 Mar 2024 10:46:23 -0400 Subject: [PATCH 09/10] factor out --- emanote/src/Emanote/CLI.hs | 24 +++++++++++++++++------- emanote/src/Emanote/Source/Dynamic.hs | 2 +- emanote/src/Emanote/Source/Loc.hs | 6 +++--- emanote/src/Emanote/Source/Patch.hs | 6 +++--- 4 files changed, 24 insertions(+), 14 deletions(-) diff --git a/emanote/src/Emanote/CLI.hs b/emanote/src/Emanote/CLI.hs index b409c0034..e5fc03c4d 100644 --- a/emanote/src/Emanote/CLI.hs +++ b/emanote/src/Emanote/CLI.hs @@ -3,6 +3,7 @@ module Emanote.CLI ( Cli (..), + Layer (..), Cmd (..), parseCli, cliParser, @@ -17,26 +18,31 @@ import Relude import UnliftIO.Directory (getCurrentDirectory) data Cli = Cli - { layers :: NonEmpty (FilePath, Maybe FilePath) + { layers :: NonEmpty Layer , allowBrokenLinks :: Bool , cmd :: Cmd } +data Layer = Layer + { path :: FilePath + , mountPoint :: Maybe FilePath + } + data Cmd = Cmd_Ema Ema.CLI.Cli | Cmd_Export cliParser :: FilePath -> Parser Cli cliParser cwd = do - layers <- pathList (one (cwd, Nothing)) + layers <- layerList $ one $ Layer cwd Nothing allowBrokenLinks <- switch (long "allow-broken-links" <> help "Report but do not fail on broken links") cmd <- fmap Cmd_Ema Ema.CLI.cliParser <|> subparser (command "export" (info (pure Cmd_Export) (progDesc "Export metadata JSON"))) pure Cli {..} where - pathList defaultPath = do - option pathListReader + layerList defaultPath = do + option layerListReader $ mconcat [ long "layers" , short 'L' @@ -44,13 +50,17 @@ cliParser cwd = do , value defaultPath , help "List of (semicolon delimited) notebook folders to 'union mount', with the left-side folders being overlaid on top of the right-side ones. The default layer is implicitly included at the end of this list." ] - pathListReader :: ReadM (NonEmpty (FilePath, Maybe FilePath)) - pathListReader = do + layerListReader :: ReadM (NonEmpty Layer) + layerListReader = do let partition s = T.breakOn "@" s & second (\x -> if T.null s then Nothing else Just $ T.drop 1 x) maybeReader $ \paths -> - nonEmpty $ fmap (bimap toString (fmap toString) . partition) $ T.split (== ';') . toText $ paths + nonEmpty + $ fmap (uncurry Layer . bimap toString (fmap toString) . partition) + $ T.split (== ';') + . toText + $ paths parseCli' :: FilePath -> ParserInfo Cli parseCli' cwd = diff --git a/emanote/src/Emanote/Source/Dynamic.hs b/emanote/src/Emanote/Source/Dynamic.hs index 187bd9ec6..53c2ffac4 100644 --- a/emanote/src/Emanote/Source/Dynamic.hs +++ b/emanote/src/Emanote/Source/Dynamic.hs @@ -55,7 +55,7 @@ emanoteSiteInput cliAct EmanoteConfig {..} = do defaultLayer <- Loc.defaultLayer <$> liftIO Paths_emanote.getDataDir instanceId <- liftIO UUID.nextRandom storkIndex <- Stork.newIndex - let layers = Loc.userLayers (CLI.layers _emanoteConfigCli) <> one defaultLayer + let layers = Loc.userLayers ((CLI.path &&& CLI.mountPoint) <$> CLI.layers _emanoteConfigCli) <> one defaultLayer initialModel = Model.emptyModel layers cliAct _emanoteConfigPandocRenderers _emanoteCompileTailwind instanceId storkIndex scriptingEngine <- getEngine Dynamic diff --git a/emanote/src/Emanote/Source/Loc.hs b/emanote/src/Emanote/Source/Loc.hs index 20243b146..2eb0677b8 100644 --- a/emanote/src/Emanote/Source/Loc.hs +++ b/emanote/src/Emanote/Source/Loc.hs @@ -53,9 +53,9 @@ defaultLayer = LocDefault userLayers :: NonEmpty (FilePath, Maybe FilePath) -> Set Loc userLayers paths = - fromList $ - zip [1 ..] (toList paths) - <&> (\(a, (b, c)) -> LocUser a b c) + fromList + $ zip [1 ..] (toList paths) + <&> (\(a, (b, c)) -> LocUser a b c) -- | Return the effective path of a file. locResolve :: (Loc, FilePath) -> FilePath diff --git a/emanote/src/Emanote/Source/Patch.hs b/emanote/src/Emanote/Source/Patch.hs index bbb57bb3e..8dcc70e5f 100644 --- a/emanote/src/Emanote/Source/Patch.hs +++ b/emanote/src/Emanote/Source/Patch.hs @@ -107,9 +107,9 @@ patchModel' layers noteF storkIndexTVar scriptingEngine fpType fp action = do let fpAbs = locResolve overlay traverseToSnd (readRefreshedFile refreshAction) fpAbs sData <- - liftIO $ - either (throwIO . BadInput) pure $ - SD.parseSDataCascading r yamlContents + liftIO + $ either (throwIO . BadInput) pure + $ SD.parseSDataCascading r yamlContents pure $ M.modelInsertData sData UM.Delete -> do log $ "Removing data: " <> toText fp From 4c6990e23e352bea76cec449c310b462c2594fa5 Mon Sep 17 00:00:00 2001 From: Sridhar Ratnakumar Date: Sun, 10 Mar 2024 13:45:22 -0400 Subject: [PATCH 10/10] docs --- docs/guide/layer.md | 20 +++++++++++++++++++- emanote/CHANGELOG.md | 1 + emanote/emanote.cabal | 2 +- 3 files changed, 21 insertions(+), 2 deletions(-) diff --git a/docs/guide/layer.md b/docs/guide/layer.md index a84fd4c50..c76cf69f9 100644 --- a/docs/guide/layer.md +++ b/docs/guide/layer.md @@ -1,6 +1,14 @@ # Layer system -Emanote's layer system allows you to "merge" multiple notebooks and treat them as if they were a single notebook. The `-L` option in the command line accepts layers, and you can specify multiple of them with the leftmost taking the most precedence. +Emanote's layer system allows you to "merge" multiple notebook directories and treat them as if they were a single notebook directory. The `-L` option in the command line accepts layers, and you can specify multiple of them with the leftmost taking the most precedence. + +For example, + +```sh +emanote -L ./docs1:./docs2 run +``` + +Internally, Emante merges both `docs1` and `docs2` folders and treats them as a single directory. Thus, both `docs1` and `docs2` can contain the same file, and the one in `docs1` will take precedence. ## "Default" layer @@ -9,3 +17,13 @@ Emanote *implicitly* includes what is known as the "default" layer. Its contents ## Merge semantics The default merge semantic is to replace with the file on the right layer. For some file types, special merge semantic applies. For example, [[yaml-config|YAML files]] are merged by deep merge, not file-level replacement. This is what allows you to create `index.yaml` that overrides only a subset of the default configuration. + +## Mount point + +Layers can be mounted at a specific path. For example, if you want to mount `docs1` at `/D1` and `docs2` at `/D2`, you can do so with: + +```sh +emanote -L /docs1@D1;/docs2@D2 run +``` + +When two layers are mounted at distinct mount points it becomes impossible for there to be overlaps. This is useful to host sub-sites under a single site, such as in [this case](https://github.com/flake-parts/community.flake.parts). \ No newline at end of file diff --git a/emanote/CHANGELOG.md b/emanote/CHANGELOG.md index 40177ba0e..38588efe9 100644 --- a/emanote/CHANGELOG.md +++ b/emanote/CHANGELOG.md @@ -11,6 +11,7 @@ - Resolve ambiguities based on closer common ancestor ([\#498](https://github.com/srid/emanote/pull/498)) - Support for folder "index.md" notes ([\#512](https://github.com/srid/emanote/pull/512)) - Instead of "foo/qux.md", you can now create "foo/qux/index.md" + - Layers can be mounted in sub-directories, enabling composition of distinct notebooks ([\#523](https://github.com/srid/emanote/pull/523)) - **BACKWARDS INCOMPTABILE** changes - `feed.siteUrl` is now `page.siteUrl` - A new HTML template layout "default" (unifies and) replaces both "book" and "note" layout. ([\#483](https://github.com/srid/emanote/pull/483)) diff --git a/emanote/emanote.cabal b/emanote/emanote.cabal index a393ec1e2..7aa22c860 100644 --- a/emanote/emanote.cabal +++ b/emanote/emanote.cabal @@ -1,6 +1,6 @@ cabal-version: 2.4 name: emanote -version: 1.3.14.3 +version: 1.3.15.0 license: AGPL-3.0-only copyright: 2022 Sridhar Ratnakumar maintainer: srid@srid.ca