(command.CommandList
  children: [
    (C {<.>} {<'../string.lib.sh'>})
    (C {<.>} {<'../bool.lib.sh'>})
    (command.ShFunction
      name: test_k_string_contains
      body: 
        (BraceGroup
          children: [
            (C {<assertTrue>} {(DQ <'241345 contains 1'>)} {(DQ <'k_string_contains 1 241345'>)})
            (C {<assertTrue>} {(DQ <'d3dabcd contains a'>)} {(DQ <'k_string_contains a d3dabcd'>)})
            (C {<assertTrue>} {(DQ <'-- contains -'>)} {(DQ <'k_string_contains - --'>)})
            (C {<assertFalse>} {(DQ <'acd does not contain b'>)} {(DQ <'k_string_contains b acd'>)})
          ]
        )
    )
    (command.ShFunction
      name: test_k_string_get_line
      body: 
        (BraceGroup
          children: [
            (C {<local>} {<Id.Lit_VarLike 'line1='> (DQ <'Hello world!'>)})
            (C {<local>} {<Id.Lit_VarLike 'line2='> (DQ <'This is some text'>)})
            (C {<local>} {<Id.Lit_VarLike 'line3='> (DQ <'And this is more'>)})
            (C {<local>} 
              {<Id.Lit_VarLike 'str='> 
                (DQ 
                  (command_sub
                    left_token: <Id.Left_DollarParen '$('>
                    child: 
                      (C {<printf>} 
                        {
                          (DQ <'%s'> <Id.Lit_BadBackslash '\\'> <'n%s'> <Id.Lit_BadBackslash '\\'> 
                            <'n%s'>
                          )
                        } {(DQ (${ Id.VSub_Name line1))} {(DQ (${ Id.VSub_Name line2))} {(DQ (${ Id.VSub_Name line3))}
                      )
                  )
                )
              }
            )
            (C {<assertEquals>} {(DQ (${ Id.VSub_Name line1))} 
              {
                (DQ 
                  (command_sub
                    left_token: <Id.Left_DollarParen '$('>
                    child: (C {<k_string_get_line>} {<1>} {(DQ (${ Id.VSub_Name str))})
                  )
                )
              }
            )
            (C {<assertEquals>} {(DQ (${ Id.VSub_Name line2))} 
              {
                (DQ 
                  (command_sub
                    left_token: <Id.Left_DollarParen '$('>
                    child: (C {<k_string_get_line>} {<2>} {(DQ (${ Id.VSub_Name str))})
                  )
                )
              }
            )
            (C {<assertEquals>} {(DQ (${ Id.VSub_Name line3))} 
              {
                (DQ 
                  (command_sub
                    left_token: <Id.Left_DollarParen '$('>
                    child: (C {<k_string_get_line>} {<3>} {(DQ (${ Id.VSub_Name str))})
                  )
                )
              }
            )
          ]
        )
    )
    (command.ShFunction
      name: test_k_string_ends_with
      body: 
        (BraceGroup
          children: [
            (C {<assertTrue>} {(DQ <'12345 ends with 5'>)} {(DQ <'k_string_ends_with 5 12345'>)})
            (C {<assertFalse>} {(DQ <'12345 does not end with 6'>)} {(DQ <'k_string_ends_with 6 12345'>)})
            (C {<assertTrue>} {(DQ <'abcd ends with d'>)} {(DQ <'k_string_ends_with d abcd'>)})
            (C {<assertTrue>} {(DQ <'-- ends with -'>)} {(DQ <'k_string_ends_with - --'>)})
            (C {<assertFalse>} {(DQ <'- does not end with --'>)} {(DQ <'k_string_ends_with -- -'>)})
            (C {<assertFalse>} {(DQ <'abcd does not end with b'>)} {(DQ <'k_string_ends_with b abcd'>)})
          ]
        )
    )
    (command.ShFunction
      name: test_k_string_starts_with
      body: 
        (BraceGroup
          children: [
            (C {<assertTrue>} {(DQ <'12345 starts with 1'>)} {(DQ <'k_string_starts_with 1 12345'>)})
            (C {<assertTrue>} {(DQ <'abcd starts with a'>)} {(DQ <'k_string_starts_with a abcd'>)})
            (C {<assertTrue>} {(DQ <'-- starts with -'>)} {(DQ <'k_string_starts_with - --'>)})
            (C {<assertFalse>} {(DQ <'- does not start with --'>)} {(DQ <'k_string_starts_with -- -'>)})
            (C {<assertFalse>} {(DQ <'abcd does not start with b'>)} 
              {(DQ <'k_string_starts_with b abcd'>)}
            )
          ]
        )
    )
    (command.ShFunction
      name: test_k_string_lower
      body: 
        (BraceGroup
          children: [
            (C {<assertEquals>} {(DQ <'ABC to lower'>)} {<abc>} 
              {
                (DQ 
                  (command_sub
                    left_token: <Id.Left_DollarParen '$('>
                    child: (C {<k_string_lower>} {<ABC>})
                  )
                )
              }
            )
            (C {<assertEquals>} {(DQ <'Abc to lower'>)} {<abc>} 
              {
                (DQ 
                  (command_sub
                    left_token: <Id.Left_DollarParen '$('>
                    child: (C {<k_string_lower>} {<Abc>})
                  )
                )
              }
            )
            (C {<assertEquals>} {(DQ <'123 to lower'>)} {<123>} 
              {
                (DQ 
                  (command_sub
                    left_token: <Id.Left_DollarParen '$('>
                    child: (C {<k_string_lower>} {<123>})
                  )
                )
              }
            )
            (C {<assertEquals>} {(DQ <'D-e+F to lower'>)} {<d-e> <Id.Lit_Other '+'> <f>} 
              {
                (DQ 
                  (command_sub
                    left_token: <Id.Left_DollarParen '$('>
                    child: (C {<k_string_lower>} {<D-e> <Id.Lit_Other '+'> <F>})
                  )
                )
              }
            )
          ]
        )
    )
    (command.ShFunction
      name: test_k_string_upper
      body: 
        (BraceGroup
          children: [
            (C {<assertEquals>} {(DQ <'abc to upper'>)} {<ABC>} 
              {
                (DQ 
                  (command_sub
                    left_token: <Id.Left_DollarParen '$('>
                    child: (C {<k_string_upper>} {<abc>})
                  )
                )
              }
            )
            (C {<assertEquals>} {(DQ <'Abc to upper'>)} {<ABC>} 
              {
                (DQ 
                  (command_sub
                    left_token: <Id.Left_DollarParen '$('>
                    child: (C {<k_string_upper>} {<Abc>})
                  )
                )
              }
            )
            (C {<assertEquals>} {(DQ <'123 to upper'>)} {<123>} 
              {
                (DQ 
                  (command_sub
                    left_token: <Id.Left_DollarParen '$('>
                    child: (C {<k_string_upper>} {<123>})
                  )
                )
              }
            )
            (C {<assertEquals>} {(DQ <'D-e+F to upper'>)} {<D-E> <Id.Lit_Other '+'> <F>} 
              {
                (DQ 
                  (command_sub
                    left_token: <Id.Left_DollarParen '$('>
                    child: (C {<k_string_upper>} {<D-e> <Id.Lit_Other '+'> <F>})
                  )
                )
              }
            )
          ]
        )
    )
    (command.ShFunction
      name: test_k_string_pad_right
      body: 
        (BraceGroup
          children: [
            (C {<assertEquals>} {(DQ <'Pad to 8 spaces'>)} {(DQ <'foo     '>)} 
              {
                (DQ 
                  (command_sub
                    left_token: <Id.Left_DollarParen '$('>
                    child: (C {<k_string_pad_right>} {<8>} {<foo>})
                  )
                )
              }
            )
          ]
        )
    )
    (command.ShFunction
      name: test_k_string_pad_left
      body: 
        (BraceGroup
          children: [
            (C {<assertEquals>} {(DQ <'Pad to 8 spaces'>)} {(DQ <'     foo'>)} 
              {
                (DQ 
                  (command_sub
                    left_token: <Id.Left_DollarParen '$('>
                    child: (C {<k_string_pad_left>} {<8>} {<foo>})
                  )
                )
              }
            )
          ]
        )
    )
    (command.ShFunction
      name: test_k_string_remove_start
      body: 
        (BraceGroup
          children: [
            (C {<assertEquals>} {(DQ <'abc remove a from start'>)} {<bc>} 
              {
                (DQ 
                  (command_sub
                    left_token: <Id.Left_DollarParen '$('>
                    child: (C {<k_string_remove_start>} {<a>} {<abc>})
                  )
                )
              }
            )
            (C {<assertEquals>} {(DQ <'aabc remove a from start'>)} {<abc>} 
              {
                (DQ 
                  (command_sub
                    left_token: <Id.Left_DollarParen '$('>
                    child: (C {<k_string_remove_start>} {<a>} {<aabc>})
                  )
                )
              }
            )
            (C {<assertEquals>} {(DQ <'abc remove b from start'>)} {<abc>} 
              {
                (DQ 
                  (command_sub
                    left_token: <Id.Left_DollarParen '$('>
                    child: (C {<k_string_remove_start>} {<b>} {<abc>})
                  )
                )
              }
            )
            (C {<assertEquals>} {(DQ <'abc remove c from start'>)} {<abc>} 
              {
                (DQ 
                  (command_sub
                    left_token: <Id.Left_DollarParen '$('>
                    child: (C {<k_string_remove_start>} {<c>} {<abc>})
                  )
                )
              }
            )
            (C {<assertEquals>} {(DQ <'abc remove d from start'>)} {<abc>} 
              {
                (DQ 
                  (command_sub
                    left_token: <Id.Left_DollarParen '$('>
                    child: (C {<k_string_remove_start>} {<d>} {<abc>})
                  )
                )
              }
            )
          ]
        )
    )
    (command.ShFunction
      name: test_k_string_remove_end
      body: 
        (BraceGroup
          children: [
            (C {<assertEquals>} {(DQ <'abc remove a from end'>)} {<abc>} 
              {
                (DQ 
                  (command_sub
                    left_token: <Id.Left_DollarParen '$('>
                    child: (C {<k_string_remove_end>} {<a>} {<abc>})
                  )
                )
              }
            )
            (C {<assertEquals>} {(DQ <'abc remove b from end'>)} {<abc>} 
              {
                (DQ 
                  (command_sub
                    left_token: <Id.Left_DollarParen '$('>
                    child: (C {<k_string_remove_end>} {<b>} {<abc>})
                  )
                )
              }
            )
            (C {<assertEquals>} {(DQ <'abc remove c from end'>)} {<ab>} 
              {
                (DQ 
                  (command_sub
                    left_token: <Id.Left_DollarParen '$('>
                    child: (C {<k_string_remove_end>} {<c>} {<abc>})
                  )
                )
              }
            )
            (C {<assertEquals>} {(DQ <'abc remove d from end'>)} {<abc>} 
              {
                (DQ 
                  (command_sub
                    left_token: <Id.Left_DollarParen '$('>
                    child: (C {<k_string_remove_end>} {<d>} {<abc>})
                  )
                )
              }
            )
          ]
        )
    )
    (command.ShFunction
      name: test_k_string_join
      body: 
        (BraceGroup
          children: [
            (C {<assertEquals>} {(DQ <'a joined by hyphen'>)} {(DQ <a>)} 
              {
                (DQ 
                  (command_sub
                    left_token: <Id.Left_DollarParen '$('>
                    child: (C {<k_string_join>} {(DQ <->)} {<a>})
                  )
                )
              }
            )
            (C {<assertEquals>} {(DQ <'a, b joined by hyphen'>)} {(DQ <a-b>)} 
              {
                (DQ 
                  (command_sub
                    left_token: <Id.Left_DollarParen '$('>
                    child: (C {<k_string_join>} {(DQ <->)} {<a>} {<b>})
                  )
                )
              }
            )
            (C {<assertEquals>} {(DQ <'a, b, c joined by hyphen'>)} {(DQ <a-b-c>)} 
              {
                (DQ 
                  (command_sub
                    left_token: <Id.Left_DollarParen '$('>
                    child: (C {<k_string_join>} {(DQ <->)} {<a>} {<b>} {<c>})
                  )
                )
              }
            )
            (C {<assertEquals>} {(DQ <'a, b, c joined by nothing'>)} {(DQ <abc>)} 
              {
                (DQ 
                  (command_sub
                    left_token: <Id.Left_DollarParen '$('>
                    child: (C {<k_string_join>} {(DQ )} {<a>} {<b>} {<c>})
                  )
                )
              }
            )
          ]
        )
    )
    (command.ShFunction
      name: test_k_string_trim
      body: 
        (BraceGroup
          children: [
            (C {<assertEquals>} {(DQ <'\'   a\' trimmed'>)} {(DQ <a>)} 
              {
                (DQ 
                  (command_sub
                    left_token: <Id.Left_DollarParen '$('>
                    child: (C {<k_string_trim>} {(DQ <'   a'>)})
                  )
                )
              }
            )
            (C {<assertEquals>} {(DQ <'\'a\t\' trimmed'>)} {(DQ <a>)} 
              {
                (DQ 
                  (command_sub
                    left_token: <Id.Left_DollarParen '$('>
                    child: (C {<k_string_trim>} {(DQ <'a\t'>)})
                  )
                )
              }
            )
            (C {<assertEquals>} {(DQ <'\'   a   \' trimmed'>)} {(DQ <a>)} 
              {
                (DQ 
                  (command_sub
                    left_token: <Id.Left_DollarParen '$('>
                    child: (C {<k_string_trim>} {(DQ <'   a   '>)})
                  )
                )
              }
            )
            (C {<assertEquals>} {(DQ <'\'   a b c\t\' trimmed'>)} {(DQ <'a b c'>)} 
              {
                (DQ 
                  (command_sub
                    left_token: <Id.Left_DollarParen '$('>
                    child: (C {<k_string_trim>} {(DQ <'   a b c\t'>)})
                  )
                )
              }
            )
          ]
        )
    )
  ]
)