about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--tvix/eval/src/builtins/mod.rs15
-rw-r--r--tvix/eval/src/value/list.rs4
2 files changed, 18 insertions, 1 deletions
diff --git a/tvix/eval/src/builtins/mod.rs b/tvix/eval/src/builtins/mod.rs
index ce048e22be0d..11e0dc8d9fa7 100644
--- a/tvix/eval/src/builtins/mod.rs
+++ b/tvix/eval/src/builtins/mod.rs
@@ -10,7 +10,7 @@ use std::{
 
 use crate::{
     errors::ErrorKind,
-    value::{Builtin, NixAttrs, NixString, Value},
+    value::{Builtin, NixAttrs, NixList, NixString, Value},
 };
 
 fn pure_builtins() -> Vec<Builtin> {
@@ -20,6 +20,19 @@ fn pure_builtins() -> Vec<Builtin> {
                 ErrorKind::Abort(args.pop().unwrap().to_string()?.as_str().to_owned()).into(),
             );
         }),
+        Builtin::new("catAttrs", 2, |mut args| {
+            let list = args.pop().unwrap().to_list()?;
+            let key = args.pop().unwrap().to_string()?;
+            let mut output = vec![];
+
+            for set in list.into_iter() {
+                if let Some(value) = set.to_attrs()?.select(key.as_str()) {
+                    output.push(value.clone());
+                }
+            }
+
+            Ok(Value::List(NixList::construct(output.len(), output)))
+        }),
         Builtin::new("isAttrs", 1, |args| {
             Ok(Value::Bool(matches!(args[0], Value::Attrs(_))))
         }),
diff --git a/tvix/eval/src/value/list.rs b/tvix/eval/src/value/list.rs
index 31f223fce599..77776c4dce62 100644
--- a/tvix/eval/src/value/list.rs
+++ b/tvix/eval/src/value/list.rs
@@ -38,4 +38,8 @@ impl NixList {
 
         NixList(stack_slice)
     }
+
+    pub fn into_iter(self) -> std::vec::IntoIter<Value> {
+        self.0.into_iter()
+    }
 }