@@ -30,6 +30,7 @@ use harp::utils::pairlist_size;
3030use harp:: utils:: r_altrep_class;
3131use harp:: utils:: r_assert_type;
3232use harp:: utils:: r_classes;
33+ use harp:: utils:: r_format_s4;
3334use harp:: utils:: r_inherits;
3435use harp:: utils:: r_is_altrep;
3536use harp:: utils:: r_is_data_frame;
@@ -100,6 +101,7 @@ impl WorkspaceVariableDisplayValue {
100101 LANGSXP => Self :: from_language ( value) ,
101102 _ if r_is_matrix ( value) => Self :: from_matrix ( value) ?,
102103 RAWSXP | LGLSXP | INTSXP | REALSXP | STRSXP | CPLXSXP => Self :: from_default ( value) ?,
104+ _ if r_is_s4 ( value) => Self :: from_s4 ( value) ?,
103105 _ => Self :: from_error ( Error :: Anyhow ( anyhow ! (
104106 "Unexpected type {}" ,
105107 r_type2char( r_typeof( value) )
@@ -336,6 +338,20 @@ impl WorkspaceVariableDisplayValue {
336338 Ok ( Self :: new ( display_value, false ) )
337339 }
338340
341+ fn from_s4 ( value : SEXP ) -> anyhow:: Result < Self > {
342+ let result: Vec < String > = RObject :: from ( r_format_s4 ( value) ?) . try_into ( ) ?;
343+ let mut display_value = String :: from ( "" ) ;
344+ for val in result. iter ( ) {
345+ for char in val. chars ( ) {
346+ if display_value. len ( ) >= MAX_DISPLAY_VALUE_LENGTH {
347+ return Ok ( Self :: new ( display_value, true ) ) ;
348+ }
349+ display_value. push ( char) ;
350+ }
351+ }
352+ Ok ( Self :: new ( display_value, false ) )
353+ }
354+
339355 fn from_default ( value : SEXP ) -> anyhow:: Result < Self > {
340356 let formatted = FormattedVector :: new ( RObject :: from ( value) ) ?;
341357
@@ -1886,6 +1902,16 @@ mod tests {
18861902 )
18871903 . unwrap ( ) ;
18881904
1905+ let path = vec ! [ ] ;
1906+ let vars = PositronVariable :: inspect ( env. clone ( ) , & path) . unwrap ( ) ;
1907+
1908+ assert_eq ! ( vars. len( ) , 1 ) ;
1909+ // Matching equality is not nice because the default `format` method for S4 objects
1910+ // uses different quoting characters on Windows vs Unix.
1911+ // Unix: <S4 class ‘ddiMatrix’ [package “Matrix”] with 4 slots>
1912+ // Windows: <S4 class 'ddiMatrix' [package "Matrix"] with 4 slots>
1913+ assert ! ( vars[ 0 ] . display_value. starts_with( "<S4 class" ) ) ;
1914+
18891915 // Inspect the S4 object
18901916 let path = vec ! [ String :: from( "x" ) ] ;
18911917 let fields = PositronVariable :: inspect ( env. clone ( ) , & path) . unwrap ( ) ;
@@ -2032,4 +2058,20 @@ mod tests {
20322058 assert_eq ! ( vars[ 0 ] . display_value, "[]" ) ;
20332059 } ) ;
20342060 }
2061+
2062+ #[ test]
2063+ fn test_s4_with_different_length ( ) {
2064+ r_task ( || {
2065+ let env = Environment :: new_empty ( ) . unwrap ( ) ;
2066+ // Matrix::Matrix objects have length != 1, but their format() method returns a length 1 character
2067+ // describing their class.
2068+ let value = harp:: parse_eval_base ( "Matrix::Matrix(0, nrow= 10, ncol = 10)" ) . unwrap ( ) ;
2069+ env. bind ( "x" . into ( ) , & value) ;
2070+
2071+ let path = vec ! [ ] ;
2072+ let vars = PositronVariable :: inspect ( env. into ( ) , & path) . unwrap ( ) ;
2073+ assert_eq ! ( vars. len( ) , 1 ) ;
2074+ assert ! ( vars[ 0 ] . display_value. starts_with( "<S4 class" ) , ) ;
2075+ } )
2076+ }
20352077}
0 commit comments