diff options
author | pacien | 2020-02-26 22:13:00 +0100 |
---|---|---|
committer | Notkea | 2020-02-27 21:54:32 +0100 |
commit | f09e9d9fa29284bd9ae872efe5ba1d526e349011 (patch) | |
tree | 50d523ffb4f2d6e4b1d09eb2edd9f099c9b20048 /compiler/src | |
parent | c7fa5bd40d0e5c9ea50190a90a0ccfee8ad96c25 (diff) | |
download | ldgallery-f09e9d9fa29284bd9ae872efe5ba1d526e349011.tar.gz |
compiler: add tag inclusion and exclusion globs
GitHub: closes #30
Diffstat (limited to 'compiler/src')
-rw-r--r-- | compiler/src/Compiler.hs | 30 | ||||
-rw-r--r-- | compiler/src/Config.hs | 4 | ||||
-rw-r--r-- | compiler/src/Input.hs | 13 |
3 files changed, 38 insertions, 9 deletions
diff --git a/compiler/src/Compiler.hs b/compiler/src/Compiler.hs index 51f5065..fa405a2 100644 --- a/compiler/src/Compiler.hs +++ b/compiler/src/Compiler.hs | |||
@@ -25,6 +25,7 @@ module Compiler | |||
25 | import GHC.Generics (Generic) | 25 | import GHC.Generics (Generic) |
26 | import Control.Monad (liftM2, when) | 26 | import Control.Monad (liftM2, when) |
27 | import Data.List (any) | 27 | import Data.List (any) |
28 | import Data.Maybe (fromMaybe) | ||
28 | import System.FilePath ((</>)) | 29 | import System.FilePath ((</>)) |
29 | import qualified System.FilePath.Glob as Glob | 30 | import qualified System.FilePath.Glob as Glob |
30 | import System.Directory (canonicalizePath) | 31 | import System.Directory (canonicalizePath) |
@@ -33,7 +34,7 @@ import Data.Aeson (ToJSON) | |||
33 | import qualified Data.Aeson as JSON | 34 | import qualified Data.Aeson as JSON |
34 | 35 | ||
35 | import Config | 36 | import Config |
36 | import Input (readInputTree) | 37 | import Input (InputTree, readInputTree, filterInputTree, sidecar, tags) |
37 | import Resource (GalleryItem, buildGalleryTree, galleryCleanupResourceDir) | 38 | import Resource (GalleryItem, buildGalleryTree, galleryCleanupResourceDir) |
38 | import Files | 39 | import Files |
39 | ( FileName | 40 | ( FileName |
@@ -74,6 +75,15 @@ writeJSON outputPath object = | |||
74 | ensureParentDir JSON.encodeFile outputPath object | 75 | ensureParentDir JSON.encodeFile outputPath object |
75 | 76 | ||
76 | 77 | ||
78 | (&&&) :: (a -> Bool) -> (a -> Bool) -> a -> Bool | ||
79 | (&&&) = liftM2 (&&) | ||
80 | |||
81 | (|||) :: (a -> Bool) -> (a -> Bool) -> a -> Bool | ||
82 | (|||) = liftM2 (||) | ||
83 | |||
84 | anyPattern :: [String] -> String -> Bool | ||
85 | anyPattern patterns string = any (flip Glob.match string) (map Glob.compile patterns) | ||
86 | |||
77 | galleryDirFilter :: GalleryConfig -> [FilePath] -> FSNode -> Bool | 87 | galleryDirFilter :: GalleryConfig -> [FilePath] -> FSNode -> Bool |
78 | galleryDirFilter config excludedCanonicalDirs = | 88 | galleryDirFilter config excludedCanonicalDirs = |
79 | (not . isHidden) | 89 | (not . isHidden) |
@@ -84,9 +94,6 @@ galleryDirFilter config excludedCanonicalDirs = | |||
84 | (matchesFile $ anyPattern $ excludedFiles config))) | 94 | (matchesFile $ anyPattern $ excludedFiles config))) |
85 | 95 | ||
86 | where | 96 | where |
87 | (&&&) = liftM2 (&&) | ||
88 | (|||) = liftM2 (||) | ||
89 | |||
90 | matchesDir :: (FileName -> Bool) -> FSNode -> Bool | 97 | matchesDir :: (FileName -> Bool) -> FSNode -> Bool |
91 | matchesDir cond dir@Dir{} = maybe False cond $ nodeName dir | 98 | matchesDir cond dir@Dir{} = maybe False cond $ nodeName dir |
92 | matchesDir _ File{} = False | 99 | matchesDir _ File{} = False |
@@ -95,13 +102,19 @@ galleryDirFilter config excludedCanonicalDirs = | |||
95 | matchesFile cond file@File{} = maybe False cond $ nodeName file | 102 | matchesFile cond file@File{} = maybe False cond $ nodeName file |
96 | matchesFile _ Dir{} = False | 103 | matchesFile _ Dir{} = False |
97 | 104 | ||
98 | anyPattern :: [String] -> FileName -> Bool | ||
99 | anyPattern patterns filename = any (flip Glob.match filename) (map Glob.compile patterns) | ||
100 | |||
101 | isExcludedDir :: FSNode -> Bool | 105 | isExcludedDir :: FSNode -> Bool |
102 | isExcludedDir Dir{canonicalPath} = any (canonicalPath ==) excludedCanonicalDirs | 106 | isExcludedDir Dir{canonicalPath} = any (canonicalPath ==) excludedCanonicalDirs |
103 | isExcludedDir File{} = False | 107 | isExcludedDir File{} = False |
104 | 108 | ||
109 | inputTreeFilter :: GalleryConfig -> InputTree -> Bool | ||
110 | inputTreeFilter GalleryConfig{includedTags, excludedTags} = | ||
111 | (hasTagMatching $ anyPattern includedTags) | ||
112 | &&& (not . (hasTagMatching $ anyPattern excludedTags)) | ||
113 | |||
114 | where | ||
115 | hasTagMatching :: (String -> Bool) -> InputTree -> Bool | ||
116 | hasTagMatching cond = (any cond) . (fromMaybe [""] . tags) . sidecar | ||
117 | |||
105 | 118 | ||
106 | compileGallery :: FilePath -> FilePath -> FilePath -> FilePath -> [FilePath] -> Bool -> Bool -> IO () | 119 | compileGallery :: FilePath -> FilePath -> FilePath -> FilePath -> [FilePath] -> Bool -> Bool -> IO () |
107 | compileGallery configPath inputDirPath outputDirPath outputIndexPath excludedDirs rebuildAll cleanOutput = | 120 | compileGallery configPath inputDirPath outputDirPath outputIndexPath excludedDirs rebuildAll cleanOutput = |
@@ -113,12 +126,13 @@ compileGallery configPath inputDirPath outputDirPath outputIndexPath excludedDir | |||
113 | let sourceFilter = galleryDirFilter config excludedCanonicalDirs | 126 | let sourceFilter = galleryDirFilter config excludedCanonicalDirs |
114 | let sourceTree = filterDir sourceFilter inputDir | 127 | let sourceTree = filterDir sourceFilter inputDir |
115 | inputTree <- readInputTree sourceTree | 128 | inputTree <- readInputTree sourceTree |
129 | let curatedInputTree = filterInputTree (inputTreeFilter config) inputTree | ||
116 | 130 | ||
117 | let cache = if rebuildAll then skipCached else withCached | 131 | let cache = if rebuildAll then skipCached else withCached |
118 | let itemProc = itemProcessor config cache | 132 | let itemProc = itemProcessor config cache |
119 | let thumbnailProc = thumbnailProcessor config cache | 133 | let thumbnailProc = thumbnailProcessor config cache |
120 | let galleryBuilder = buildGalleryTree itemProc thumbnailProc (tagsFromDirectories config) | 134 | let galleryBuilder = buildGalleryTree itemProc thumbnailProc (tagsFromDirectories config) |
121 | resources <- galleryBuilder inputTree | 135 | resources <- galleryBuilder curatedInputTree |
122 | 136 | ||
123 | when cleanOutput $ galleryCleanupResourceDir resources outputDirPath | 137 | when cleanOutput $ galleryCleanupResourceDir resources outputDirPath |
124 | writeJSON (outputGalleryIndex outputIndexPath) $ GalleryIndex (viewerConfig config) resources | 138 | writeJSON (outputGalleryIndex outputIndexPath) $ GalleryIndex (viewerConfig config) resources |
diff --git a/compiler/src/Config.hs b/compiler/src/Config.hs index 1bdb2b8..8796c3c 100644 --- a/compiler/src/Config.hs +++ b/compiler/src/Config.hs | |||
@@ -55,6 +55,8 @@ data GalleryConfig = GalleryConfig | |||
55 | , excludedDirectories :: [String] | 55 | , excludedDirectories :: [String] |
56 | , includedFiles :: [String] | 56 | , includedFiles :: [String] |
57 | , excludedFiles :: [String] | 57 | , excludedFiles :: [String] |
58 | , includedTags :: [String] | ||
59 | , excludedTags :: [String] | ||
58 | , tagsFromDirectories :: TagsFromDirectoriesConfig | 60 | , tagsFromDirectories :: TagsFromDirectoriesConfig |
59 | , thumbnailMaxResolution :: Resolution | 61 | , thumbnailMaxResolution :: Resolution |
60 | , pictureMaxResolution :: Maybe Resolution | 62 | , pictureMaxResolution :: Maybe Resolution |
@@ -67,6 +69,8 @@ instance FromJSON GalleryConfig where | |||
67 | <*> v .:? "excludedDirectories" .!= [] | 69 | <*> v .:? "excludedDirectories" .!= [] |
68 | <*> v .:? "includedFiles" .!= ["*"] | 70 | <*> v .:? "includedFiles" .!= ["*"] |
69 | <*> v .:? "excludedFiles" .!= [] | 71 | <*> v .:? "excludedFiles" .!= [] |
72 | <*> v .:? "includedTags" .!= ["*"] | ||
73 | <*> v .:? "excludedTags" .!= [] | ||
70 | <*> v .:? "tagsFromDirectories" .!= (TagsFromDirectoriesConfig 0 "") | 74 | <*> v .:? "tagsFromDirectories" .!= (TagsFromDirectoriesConfig 0 "") |
71 | <*> v .:? "thumbnailMaxResolution" .!= (Resolution 400 300) | 75 | <*> v .:? "thumbnailMaxResolution" .!= (Resolution 400 300) |
72 | <*> v .:? "pictureMaxResolution" | 76 | <*> v .:? "pictureMaxResolution" |
diff --git a/compiler/src/Input.hs b/compiler/src/Input.hs index 75d1ed3..6ed7471 100644 --- a/compiler/src/Input.hs +++ b/compiler/src/Input.hs | |||
@@ -19,7 +19,7 @@ | |||
19 | module Input | 19 | module Input |
20 | ( decodeYamlFile | 20 | ( decodeYamlFile |
21 | , Sidecar(..) | 21 | , Sidecar(..) |
22 | , InputTree(..), readInputTree | 22 | , InputTree(..), readInputTree, filterInputTree |
23 | ) where | 23 | ) where |
24 | 24 | ||
25 | 25 | ||
@@ -132,3 +132,14 @@ readInputTree (AnchoredFSNode anchor root@Dir{}) = mkDirNode root | |||
132 | 132 | ||
133 | findThumbnail :: [FSNode] -> Maybe Path | 133 | findThumbnail :: [FSNode] -> Maybe Path |
134 | findThumbnail = (fmap Files.path) . (find isThumbnail) | 134 | findThumbnail = (fmap Files.path) . (find isThumbnail) |
135 | |||
136 | -- | Filters an InputTree. The root is always returned. | ||
137 | filterInputTree :: (InputTree -> Bool) -> InputTree -> InputTree | ||
138 | filterInputTree cond = filterNode | ||
139 | where | ||
140 | filterNode :: InputTree -> InputTree | ||
141 | filterNode inputFile@InputFile{} = inputFile | ||
142 | filterNode inputDir@InputDir{items} = | ||
143 | filter cond items | ||
144 | & map filterNode | ||
145 | & \curatedItems -> inputDir { items = curatedItems } :: InputTree | ||