vadd: Allow listing multiple desired values for a field.

This commit is contained in:
Joey Hess 2014-03-02 15:36:45 -04:00
parent c2e8c21ca6
commit 7d9486a709
5 changed files with 36 additions and 28 deletions

View file

@ -90,12 +90,37 @@ data ViewChange = Unchanged | Narrowing | Widening
{- Updates a view, adding new fields to filter on (Narrowing), {- Updates a view, adding new fields to filter on (Narrowing),
- or allowing new values in an existing field (Widening). -} - or allowing new values in an existing field (Widening). -}
refineView :: View -> [(MetaField, ViewFilter)] -> (View, ViewChange) refineView :: View -> [(MetaField, ViewFilter)] -> (View, ViewChange)
refineView = go Unchanged refineView origview = checksize . calc Unchanged origview
where where
go c v [] = (v, c) calc c v [] = (v, c)
go c v ((f, vf):rest) = calc c v ((f, vf):rest) =
let (v', c') = refineView' v f vf let (v', c') = refine v f vf
in go (max c c') v' rest in calc (max c c') v' rest
refine view field vf
| field `elem` map viewField (viewComponents view) =
let (components', viewchanges) = runWriter $
mapM (\c -> updateViewComponent c field vf) (viewComponents view)
viewchange = if field `elem` map viewField (viewComponents origview)
then maximum viewchanges
else Narrowing
in (view { viewComponents = components' }, viewchange)
| otherwise =
let component = mkViewComponent field vf
view' = view { viewComponents = component : viewComponents view }
in (view', Narrowing)
checksize r@(v, _)
| viewTooLarge v = error $ "View is too large (" ++ show (visibleViewSize v) ++ " levels of subdirectories)"
| otherwise = r
updateViewComponent :: ViewComponent -> MetaField -> ViewFilter -> Writer [ViewChange] ViewComponent
updateViewComponent c field vf
| viewField c == field = do
let (newvf, viewchange) = combineViewFilter (viewFilter c) vf
tell [viewchange]
return $ mkViewComponent field newvf
| otherwise = return c
{- Adds an additional filter to a view. This can only result in narrowing {- Adds an additional filter to a view. This can only result in narrowing
- the view. Multivalued filters are added in non-visible form. -} - the view. Multivalued filters are added in non-visible form. -}
@ -106,27 +131,6 @@ filterView v vs = v { viewComponents = viewComponents f' ++ viewComponents v}
f' = f { viewComponents = map toinvisible (viewComponents f) } f' = f { viewComponents = map toinvisible (viewComponents f) }
toinvisible c = c { viewVisible = False } toinvisible c = c { viewVisible = False }
refineView' :: View -> MetaField -> ViewFilter -> (View, ViewChange)
refineView' view field vf
| field `elem` (map viewField components) =
let (components', viewchanges) = runWriter $ mapM updatefield components
in (view { viewComponents = components' }, maximum viewchanges)
| otherwise =
let component = ViewComponent field vf (multiValue vf)
view' = view { viewComponents = component : components }
in if viewTooLarge view'
then error $ "View is too large (" ++ show (visibleViewSize view') ++ " levels of subdirectories)"
else (view', Narrowing)
where
components = viewComponents view
updatefield :: ViewComponent -> Writer [ViewChange] ViewComponent
updatefield v
| viewField v == field = do
let (newvf, viewchange) = combineViewFilter (viewFilter v) vf
tell [viewchange]
return $ v { viewFilter = newvf }
| otherwise = return v
{- Combine old and new ViewFilters, yielding a result that matches {- Combine old and new ViewFilters, yielding a result that matches
- either old+new, or only new. - either old+new, or only new.
- -

View file

@ -36,6 +36,6 @@ start = go =<< currentView
else next $ next $ checkoutViewBranch v' narrowView else next $ next $ checkoutViewBranch v' narrowView
vcycle rest (c:cs) vcycle rest (c:cs)
| multiValue (viewFilter c) = rest ++ cs ++ [c] | viewVisible c = rest ++ cs ++ [c]
| otherwise = vcycle (c:rest) cs | otherwise = vcycle (c:rest) cs
vcycle rest c = rest ++ c vcycle rest c = rest ++ c

View file

@ -50,6 +50,9 @@ instance Arbitrary ViewFilter where
, return (ExcludeValues s) , return (ExcludeValues s)
) )
mkViewComponent :: MetaField -> ViewFilter -> ViewComponent
mkViewComponent f vf = ViewComponent f vf (multiValue vf)
{- Can a ViewFilter match multiple different MetaValues? -} {- Can a ViewFilter match multiple different MetaValues? -}
multiValue :: ViewFilter -> Bool multiValue :: ViewFilter -> Bool
multiValue (FilterValues s) = S.size s > 1 multiValue (FilterValues s) = S.size s > 1

1
debian/changelog vendored
View file

@ -14,6 +14,7 @@ git-annex (5.20140228) UNRELEASED; urgency=medium
git repository; it only makes sense for special remotes. git repository; it only makes sense for special remotes.
* view, vfilter: Add support for filtering tags and values out of a view, * view, vfilter: Add support for filtering tags and values out of a view,
using !tag and field!=value. using !tag and field!=value.
* vadd: Allow listing multiple desired values for a field.
-- Joey Hess <joeyh@debian.org> Fri, 28 Feb 2014 14:52:15 -0400 -- Joey Hess <joeyh@debian.org> Fri, 28 Feb 2014 14:52:15 -0400

View file

@ -759,7 +759,7 @@ subdirectories).
Filters the current view to only the files that have the Filters the current view to only the files that have the
specified field values and tags. specified field values and tags.
* `vadd [field=glob ...]` * `vadd [field=glob ...] [field=value ...]`
Changes the current view, adding an additional level of directories Changes the current view, adding an additional level of directories
to categorize the files. to categorize the files.