@@ -26,6 +26,8 @@ pub async fn ls(
2626 abs_limit : i32 ,
2727 show_all_hidden : bool ,
2828 node_limit : i32 ,
29+ tags : & [ String ] ,
30+ show_tags : bool ,
2931 output_format : OutputFormat ,
3032 compact : bool ,
3133) -> Result < ( ) > {
@@ -38,9 +40,10 @@ pub async fn ls(
3840 abs_limit,
3941 show_all_hidden,
4042 node_limit,
43+ tags,
4144 )
4245 . await ?;
43- output_filesystem_entries ( & result, output_format, compact, false ) ;
46+ output_filesystem_entries ( & result, output_format, compact, false , show_tags ) ;
4447 Ok ( ( ) )
4548}
4649
@@ -52,6 +55,7 @@ pub async fn tree(
5255 show_all_hidden : bool ,
5356 node_limit : i32 ,
5457 level_limit : i32 ,
58+ tags : & [ String ] ,
5559 output_format : OutputFormat ,
5660 compact : bool ,
5761) -> Result < ( ) > {
@@ -63,9 +67,10 @@ pub async fn tree(
6367 show_all_hidden,
6468 node_limit,
6569 level_limit,
70+ tags,
6671 )
6772 . await ?;
68- output_filesystem_entries ( & result, output_format, compact, true ) ;
73+ output_filesystem_entries ( & result, output_format, compact, true , false ) ;
6974 Ok ( ( ) )
7075}
7176
@@ -74,8 +79,11 @@ fn output_filesystem_entries(
7479 output_format : OutputFormat ,
7580 compact : bool ,
7681 is_tree : bool ,
82+ show_tags : bool ,
7783) {
78- if let Some ( rendered) = render_filesystem_entries_for_table ( result, output_format, is_tree) {
84+ if let Some ( rendered) =
85+ render_filesystem_entries_for_table ( result, output_format, is_tree, show_tags)
86+ {
7987 println ! ( "{rendered}" ) ;
8088 } else {
8189 output_success ( result, output_format, compact) ;
@@ -86,18 +94,24 @@ fn render_filesystem_entries_for_table(
8694 value : & Value ,
8795 output_format : OutputFormat ,
8896 is_tree : bool ,
97+ show_tags : bool ,
8998) -> Option < String > {
9099 if matches ! ( output_format, OutputFormat :: Json ) {
91100 return None ;
92101 }
93102 if is_tree {
94103 render_tree_entries_for_table ( value)
95104 } else {
96- render_ls_entries_for_table ( value)
105+ render_ls_entries_for_table_with_tags ( value, show_tags )
97106 }
98107}
99108
109+ #[ cfg( test) ]
100110fn render_ls_entries_for_table ( value : & Value ) -> Option < String > {
111+ render_ls_entries_for_table_with_tags ( value, false )
112+ }
113+
114+ fn render_ls_entries_for_table_with_tags ( value : & Value , show_tags : bool ) -> Option < String > {
101115 let ( entries, profile) = filesystem_entries ( value) ?;
102116 let mut lines = Vec :: new ( ) ;
103117 let text_width = entry_text_width ( ) ;
@@ -112,7 +126,7 @@ fn render_ls_entries_for_table(value: &Value) -> Option<String> {
112126 if index > 0 {
113127 lines. push ( String :: new ( ) ) ;
114128 }
115- render_ls_entry ( index + 1 , entry, text_width, & mut lines) ;
129+ render_ls_entry ( index + 1 , entry, text_width, show_tags , & mut lines) ;
116130 }
117131
118132 append_profile_lines ( profile, & mut lines) ;
@@ -155,7 +169,13 @@ fn filesystem_entries(value: &Value) -> Option<(Vec<&Value>, Option<&Value>)> {
155169 Some ( ( entries. iter ( ) . collect ( ) , profile) )
156170}
157171
158- fn render_ls_entry ( rank : usize , entry : & Value , text_width : usize , lines : & mut Vec < String > ) {
172+ fn render_ls_entry (
173+ rank : usize ,
174+ entry : & Value ,
175+ text_width : usize ,
176+ show_tags : bool ,
177+ lines : & mut Vec < String > ,
178+ ) {
159179 let object = entry. as_object ( ) ;
160180 let metadata = entry_metadata ( object) ;
161181 lines. push ( format ! (
@@ -171,6 +191,24 @@ fn render_ls_entry(rank: usize, entry: &Value, text_width: usize, lines: &mut Ve
171191 }
172192
173193 append_entry_abstract ( object, ENTRY_INDENT , text_width, lines) ;
194+ if show_tags {
195+ let tags = object
196+ . and_then ( |object| object. get ( "tags" ) )
197+ . and_then ( Value :: as_array)
198+ . map ( |items| {
199+ items
200+ . iter ( )
201+ . filter_map ( Value :: as_str)
202+ . collect :: < Vec < _ > > ( )
203+ . join ( ", " )
204+ } )
205+ . filter ( |tags| !tags. is_empty ( ) )
206+ . unwrap_or_else ( || "-" . to_string ( ) ) ;
207+ lines. push ( format ! (
208+ "{ENTRY_INDENT}{}" ,
209+ theme:: muted( format!( "tags: {tags}" ) )
210+ ) ) ;
211+ }
174212}
175213
176214fn render_tree_entry ( rank : usize , entry : & Value , text_width : usize , lines : & mut Vec < String > ) {
@@ -497,7 +535,7 @@ fn output_message_result(
497535mod tests {
498536 use super :: {
499537 render_filesystem_entries_for_table, render_ls_entries_for_table,
500- render_tree_entries_for_table,
538+ render_ls_entries_for_table_with_tags , render_tree_entries_for_table,
501539 } ;
502540 use crate :: output:: render_profiled_scalar_result;
503541 use serde_json:: json;
@@ -681,11 +719,30 @@ mod tests {
681719 ] ) ;
682720
683721 assert ! (
684- render_filesystem_entries_for_table( & result, crate :: output:: OutputFormat :: Json , false )
685- . is_none( )
722+ render_filesystem_entries_for_table(
723+ & result,
724+ crate :: output:: OutputFormat :: Json ,
725+ false ,
726+ false ,
727+ )
728+ . is_none( )
686729 ) ;
687730 }
688731
732+ #[ test]
733+ fn ls_table_output_shows_requested_tags ( ) {
734+ let result = json ! ( [
735+ { "uri" : "viking://resources/a.md" , "isDir" : false , "tags" : [ "env=prod" , "team=search" ] } ,
736+ { "uri" : "viking://resources/b.md" , "isDir" : false , "tags" : [ ] }
737+ ] ) ;
738+
739+ let rendered =
740+ strip_ansi ( & render_ls_entries_for_table_with_tags ( & result, true ) . expect ( "ls" ) ) ;
741+
742+ assert ! ( rendered. contains( "tags: env=prod, team=search" ) ) ;
743+ assert ! ( rendered. contains( "tags: -" ) ) ;
744+ }
745+
689746 fn strip_ansi ( input : & str ) -> String {
690747 let mut output = String :: with_capacity ( input. len ( ) ) ;
691748 let mut chars = input. chars ( ) . peekable ( ) ;
0 commit comments