diff --git a/lib/default.nix b/lib/default.nix index 4345c48f3bc4c..849d6ce8f9d6a 100644 --- a/lib/default.nix +++ b/lib/default.nix @@ -94,8 +94,9 @@ let inherit (self.lists) singleton forEach map foldr fold foldl foldl' imap0 imap1 filter ifilter0 concatMap flatten remove findSingle findFirst any all count optional optionals toList range replicate partition zipListsWith zipLists - reverseList listDfs toposort sort sortOn naturalSort compareLists take - drop sublist last init crossLists unique allUnique intersectLists + reverseList listDfs toposort sort sortOn naturalSort compareLists + take drop dropEnd sublist last init + crossLists unique allUnique intersectLists subtractLists mutuallyExclusive groupBy groupBy' concatLists genList length head tail elem elemAt isList; inherit (self.strings) concatStrings concatMapStrings concatImapStrings diff --git a/lib/lists.nix b/lib/lists.nix index ca436d7a9c94b..59d47b1eeb9cc 100644 --- a/lib/lists.nix +++ b/lib/lists.nix @@ -6,6 +6,7 @@ let inherit (lib.strings) toInt; inherit (lib.trivial) compare min id warn pipe; inherit (lib.attrsets) mapAttrs; + inherit (lib) max; in rec { @@ -1484,6 +1485,46 @@ rec { count: list: sublist count (length list) list; + /** + Remove the last (at most) N elements of a list. + + + # Inputs + + `count` + + : Number of elements to drop + + `list` + + : Input list + + # Type + + ``` + dropEnd :: Int -> [a] -> [a] + ``` + + # Examples + + :::{.example} + ## `lib.lists.dropEnd` usage example + + ```nix + dropEnd 2 [ "a" "b" "c" "d" ] + => [ "a" "b" ] + dropEnd 2 [ ] + => [ ] + ``` + ::: + + */ + dropEnd = + n: xs: + take + (max 0 (length xs - n)) + xs; + /** Whether the first list is a prefix of the second list. diff --git a/lib/tests/misc.nix b/lib/tests/misc.nix index 330891f312235..7618fd23383d8 100644 --- a/lib/tests/misc.nix +++ b/lib/tests/misc.nix @@ -866,6 +866,18 @@ runTests { (drop 1 [ ] == [ ]) ]; + testDropEnd = let inherit (lib) dropEnd; in testAllTrue [ + (dropEnd 0 [ 1 2 3 ] == [ 1 2 3 ]) + (dropEnd 1 [ 1 2 3 ] == [ 1 2 ]) + (dropEnd 2 [ 1 2 3 ] == [ 1 ]) + (dropEnd 3 [ 1 2 3 ] == [ ]) + (dropEnd 4 [ 1 2 3 ] == [ ]) + (dropEnd 0 [ ] == [ ]) + (dropEnd 1 [ ] == [ ]) + (dropEnd (-1) [ 1 2 3 ] == [ 1 2 3 ]) + (dropEnd (-1) [ ] == [ ]) + ]; + testListHasPrefixExample1 = { expr = lists.hasPrefix [ 1 2 ] [ 1 2 3 4 ]; expected = true;