nodes: 0, module; 1, function_definition; 2, function_name:list_str; 3, parameters; 4, block; 5, identifier:list_; 6, dictionary_splat_pattern; 7, expression_statement; 8, import_statement; 9, expression_statement; 10, expression_statement; 11, expression_statement; 12, expression_statement; 13, expression_statement; 14, expression_statement; 15, expression_statement; 16, expression_statement; 17, comment:# Doesn't actually put in trailing comma if on same line; 18, expression_statement; 19, expression_statement; 20, expression_statement; 21, expression_statement; 22, expression_statement; 23, expression_statement; 24, if_statement; 25, if_statement; 26, if_statement; 27, comment:# TODO: rectify with dict_truncate; 28, expression_statement; 29, if_statement; 30, return_statement; 31, identifier:listkw; 32, comment:r"""
      Makes a pretty list string
  
      Args:
          list_ (list): input list
          **listkw: nl, newlines, packed, truncate, nobr, nobraces, itemsep,
                    trailing_sep, truncatekw, strvals, recursive,
                    indent_, precision, use_numpy, with_dtype, force_dtype,
                    stritems, strkeys, align, explicit, sorted_, key_order,
                    key_order_metric, maxlen
  
      Returns:
          str: retstr
  
      CommandLine:
          python -m utool.util_str --test-list_str
          python -m utool.util_str --exec-list_str --truncate=True
          python -m utool.util_str --exec-list_str --truncate=0
  
  
      Example:
          >>> # ENABLE_DOCTEST
          >>> from utool.util_str import *  # NOQA
          >>> import utool as ut
          >>> list_ = [[(('--verbose-qt', '--verbqt'), 1, False, ''),
          >>>           (('--verbose-qt', '--verbqt'), 1, False, ''),
          >>>           (('--verbose-qt', '--verbqt'), 1, False, ''),
          >>>           (('--verbose-qt', '--verbqt'), 1, False, '')],
          >>>          [(['--nodyn'], 1, False, ''), (['--nodyn'], 1, False, '')]]
          >>> listkw = {'nl':  2}
          >>> result = list_str(list_, **listkw)
          >>> print(result)
          [
              [
                  (('--verbose-qt', '--verbqt'), 1, False, ''),
                  (('--verbose-qt', '--verbqt'), 1, False, ''),
                  (('--verbose-qt', '--verbqt'), 1, False, ''),
                  (('--verbose-qt', '--verbqt'), 1, False, ''),
              ],
              [
                  (['--nodyn'], 1, False, ''),
                  (['--nodyn'], 1, False, ''),
              ],
          ]
      """; 33, aliased_import; 34, assignment; 35, assignment; 36, assignment; 37, assignment; 38, assignment; 39, assignment; 40, assignment; 41, assignment; 42, assignment; 43, assignment; 44, assignment; 45, assignment; 46, assignment; 47, assignment; 48, identifier:nobraces; 49, block; 50, elif_clause; 51, elif_clause; 52, else_clause; 53, comparison_operator:len(itemstr_list) == 0; 54, block; 55, boolean_operator; 56, block; 57, else_clause; 58, assignment; 59, identifier:do_truncate; 60, block; 61, identifier:retstr; 62, dotted_name; 63, identifier:ut; 64, identifier:newlines; 65, call; 66, identifier:packed; 67, call; 68, identifier:truncate; 69, call; 70, subscript; 71, call; 72, subscript; 73, call; 74, subscript; 75, call; 76, identifier:nobraces; 77, call; 78, identifier:itemsep; 79, call; 80, identifier:trailing_sep; 81, call; 82, identifier:with_comma; 83, True; 84, identifier:itemstr_list; 85, call; 86, identifier:is_tuple; 87, call; 88, identifier:is_set; 89, call; 90, identifier:is_onetup; 91, boolean_operator; 92, expression_statement; 93, identifier:is_tuple; 94, block; 95, identifier:is_set; 96, block; 97, block; 98, call; 99, integer:0; 100, expression_statement; 101, comparison_operator:newlines is not False; 102, parenthesized_expression; 103, expression_statement; 104, if_statement; 105, block; 106, identifier:do_truncate; 107, boolean_operator; 108, expression_statement; 109, expression_statement; 110, identifier:utool; 111, attribute; 112, argument_list; 113, attribute; 114, argument_list; 115, attribute; 116, argument_list; 117, identifier:listkw; 118, string; 119, identifier:_rectify_countdown_or_bool; 120, argument_list; 121, identifier:listkw; 122, string; 123, identifier:_rectify_countdown_or_bool; 124, argument_list; 125, identifier:listkw; 126, string; 127, identifier:_rectify_countdown_or_bool; 128, argument_list; 129, attribute; 130, argument_list; 131, attribute; 132, argument_list; 133, attribute; 134, argument_list; 135, identifier:get_itemstr_list; 136, argument_list; 137, identifier:isinstance; 138, argument_list; 139, identifier:isinstance; 140, argument_list; 141, call; 142, comparison_operator:len(list_) <= 1; 143, assignment; 144, expression_statement; 145, expression_statement; 146, expression_statement; 147, identifier:len; 148, argument_list; 149, assignment; 150, identifier:newlines; 151, False; 152, boolean_operator; 153, assignment; 154, identifier:nobraces; 155, block; 156, else_clause; 157, expression_statement; 158, expression_statement; 159, if_statement; 160, expression_statement; 161, comparison_operator:truncate is not False; 162, parenthesized_expression; 163, assignment; 164, assignment; 165, identifier:listkw; 166, identifier:pop; 167, string; 168, call; 169, identifier:listkw; 170, identifier:pop; 171, string; 172, False; 173, identifier:listkw; 174, identifier:pop; 175, string; 176, False; 177, string_content:nl; 178, identifier:newlines; 179, string_content:truncate; 180, identifier:truncate; 181, string_content:packed; 182, identifier:packed; 183, identifier:listkw; 184, identifier:pop; 185, string; 186, call; 187, identifier:listkw; 188, identifier:get; 189, string; 190, string; 191, identifier:listkw; 192, identifier:get; 193, string; 194, True; 195, identifier:list_; 196, dictionary_splat; 197, identifier:list_; 198, identifier:tuple; 199, identifier:list_; 200, tuple; 201, identifier:isinstance; 202, argument_list; 203, call; 204, integer:1; 205, pattern_list; 206, expression_list; 207, assignment; 208, assignment; 209, assignment; 210, identifier:itemstr_list; 211, identifier:newlines; 212, False; 213, comparison_operator:newlines is True; 214, comparison_operator:newlines > 0; 215, identifier:sep; 216, conditional_expression:',\n' if with_comma else '\n'; 217, expression_statement; 218, if_statement; 219, expression_statement; 220, block; 221, assignment; 222, assignment; 223, identifier:is_onetup; 224, block; 225, assignment; 226, identifier:truncate; 227, False; 228, boolean_operator; 229, identifier:truncatekw; 230, call; 231, identifier:retstr; 232, call; 233, string_content:nl; 234, attribute; 235, argument_list; 236, string_content:packed; 237, string_content:truncate; 238, string_content:nobr; 239, attribute; 240, argument_list; 241, string_content:itemsep; 242, string_content:; 243, string_content:trailing_sep; 244, identifier:listkw; 245, identifier:set; 246, identifier:frozenset; 247, attribute; 248, identifier:list_; 249, parenthesized_expression; 250, identifier:len; 251, argument_list; 252, identifier:lbr; 253, identifier:rbr; 254, string; 255, string; 256, pattern_list; 257, expression_list; 258, pattern_list; 259, expression_list; 260, pattern_list; 261, expression_list; 262, identifier:newlines; 263, True; 264, identifier:newlines; 265, integer:0; 266, string; 267, identifier:with_comma; 268, string; 269, assignment; 270, identifier:trailing_sep; 271, block; 272, assignment; 273, if_statement; 274, expression_statement; 275, identifier:sep; 276, conditional_expression:',' + itemsep if with_comma else itemsep; 277, identifier:body_str; 278, call; 279, expression_statement; 280, identifier:retstr; 281, parenthesized_expression; 282, comparison_operator:truncate is True; 283, comparison_operator:truncate == 0; 284, attribute; 285, argument_list; 286, identifier:truncate_str; 287, argument_list; 288, identifier:listkw; 289, identifier:pop; 290, string; 291, integer:1; 292, identifier:listkw; 293, identifier:pop; 294, string; 295, False; 296, identifier:ut; 297, identifier:oset; 298, identifier:tuple; 299, identifier:list_; 300, identifier:lbr; 301, identifier:rbr; 302, string; 303, string; 304, identifier:lbr; 305, identifier:rbr; 306, string; 307, string; 308, identifier:lbr; 309, identifier:rbr; 310, string; 311, string; 312, string_content; 313, string_content; 314, identifier:body_str; 315, call; 316, expression_statement; 317, identifier:retstr; 318, identifier:body_str; 319, identifier:packed; 320, comment:# DEPRICATE?; 321, block; 322, else_clause; 323, assignment; 324, binary_operator:',' + itemsep; 325, identifier:with_comma; 326, identifier:itemsep; 327, attribute; 328, argument_list; 329, augmented_assignment; 330, binary_operator:lbr + body_str +  rbr; 331, identifier:truncate; 332, True; 333, identifier:truncate; 334, integer:0; 335, identifier:listkw; 336, identifier:get; 337, string; 338, dictionary; 339, identifier:retstr; 340, dictionary_splat; 341, string_content:newlines; 342, string_content:nobraces; 343, string_content:(; 344, string_content:); 345, string_content:{; 346, string_content:}; 347, string_content:[; 348, string_content:]; 349, escape_sequence:\n; 350, escape_sequence:\n; 351, attribute; 352, argument_list; 353, augmented_assignment; 354, expression_statement; 355, expression_statement; 356, if_statement; 357, expression_statement; 358, block; 359, identifier:retstr; 360, identifier:braced_body_str; 361, string; 362, identifier:itemsep; 363, identifier:sep; 364, identifier:join; 365, identifier:itemstr_list; 366, identifier:body_str; 367, string; 368, binary_operator:lbr + body_str; 369, identifier:rbr; 370, string_content:truncatekw; 371, identifier:truncatekw; 372, identifier:sep; 373, identifier:join; 374, identifier:itemstr_list; 375, identifier:body_str; 376, string; 377, assignment; 378, assignment; 379, identifier:trailing_sep; 380, block; 381, assignment; 382, expression_statement; 383, if_statement; 384, expression_statement; 385, string_content:,; 386, string_content:,; 387, identifier:lbr; 388, identifier:body_str; 389, string_content:,; 390, identifier:joinstr; 391, binary_operator:sep + itemsep * len(lbr); 392, identifier:body_str; 393, call; 394, expression_statement; 395, identifier:braced_body_str; 396, parenthesized_expression; 397, assignment; 398, identifier:trailing_sep; 399, block; 400, assignment; 401, identifier:sep; 402, binary_operator:itemsep * len(lbr); 403, attribute; 404, argument_list; 405, augmented_assignment; 406, binary_operator:lbr + '' + body_str + '' + rbr; 407, identifier:body_str; 408, call; 409, expression_statement; 410, identifier:braced_body_str; 411, parenthesized_expression; 412, identifier:itemsep; 413, call; 414, identifier:joinstr; 415, identifier:join; 416, list_comprehension; 417, identifier:body_str; 418, string; 419, binary_operator:lbr + '' + body_str + ''; 420, identifier:rbr; 421, attribute; 422, argument_list; 423, augmented_assignment; 424, binary_operator:lbr + '\n' + body_str + '\n' + rbr; 425, identifier:len; 426, argument_list; 427, identifier:itemstr; 428, for_in_clause; 429, string_content:,; 430, binary_operator:lbr + '' + body_str; 431, string; 432, identifier:sep; 433, identifier:join; 434, list_comprehension; 435, identifier:body_str; 436, string; 437, binary_operator:lbr + '\n' + body_str + '\n'; 438, identifier:rbr; 439, identifier:lbr; 440, identifier:itemstr; 441, identifier:itemstr_list; 442, binary_operator:lbr + ''; 443, identifier:body_str; 444, call; 445, for_in_clause; 446, string_content:,; 447, binary_operator:lbr + '\n' + body_str; 448, string; 449, identifier:lbr; 450, string; 451, attribute; 452, argument_list; 453, identifier:itemstr; 454, identifier:itemstr_list; 455, binary_operator:lbr + '\n'; 456, identifier:body_str; 457, string_content; 458, identifier:ut; 459, identifier:indent; 460, identifier:itemstr; 461, identifier:lbr; 462, string; 463, escape_sequence:\n; 464, string_content; 465, escape_sequence:\n
code: def list_str(list_, **listkw):
      r"""
      Makes a pretty list string
  
      Args:
          list_ (list): input list
          **listkw: nl, newlines, packed, truncate, nobr, nobraces, itemsep,
                    trailing_sep, truncatekw, strvals, recursive,
                    indent_, precision, use_numpy, with_dtype, force_dtype,
                    stritems, strkeys, align, explicit, sorted_, key_order,
                    key_order_metric, maxlen
  
      Returns:
          str: retstr
  
      CommandLine:
          python -m utool.util_str --test-list_str
          python -m utool.util_str --exec-list_str --truncate=True
          python -m utool.util_str --exec-list_str --truncate=0
  
  
      Example:
          >>> # ENABLE_DOCTEST
          >>> from utool.util_str import *  # NOQA
          >>> import utool as ut
          >>> list_ = [[(('--verbose-qt', '--verbqt'), 1, False, ''),
          >>>           (('--verbose-qt', '--verbqt'), 1, False, ''),
          >>>           (('--verbose-qt', '--verbqt'), 1, False, ''),
          >>>           (('--verbose-qt', '--verbqt'), 1, False, '')],
          >>>          [(['--nodyn'], 1, False, ''), (['--nodyn'], 1, False, '')]]
          >>> listkw = {'nl':  2}
          >>> result = list_str(list_, **listkw)
          >>> print(result)
          [
              [
                  (('--verbose-qt', '--verbqt'), 1, False, ''),
                  (('--verbose-qt', '--verbqt'), 1, False, ''),
                  (('--verbose-qt', '--verbqt'), 1, False, ''),
                  (('--verbose-qt', '--verbqt'), 1, False, ''),
              ],
              [
                  (['--nodyn'], 1, False, ''),
                  (['--nodyn'], 1, False, ''),
              ],
          ]
      """
      import utool as ut
  
      newlines = listkw.pop('nl', listkw.pop('newlines', 1))
      packed = listkw.pop('packed', False)
      truncate = listkw.pop('truncate', False)
      listkw['nl'] = _rectify_countdown_or_bool(newlines)
      listkw['truncate'] = _rectify_countdown_or_bool(truncate)
      listkw['packed'] = _rectify_countdown_or_bool(packed)
  
      nobraces = listkw.pop('nobr', listkw.pop('nobraces', False))
  
      itemsep = listkw.get('itemsep', ' ')
      # Doesn't actually put in trailing comma if on same line
      trailing_sep = listkw.get('trailing_sep', True)
      with_comma = True
  
      itemstr_list = get_itemstr_list(list_, **listkw)
      is_tuple = isinstance(list_, tuple)
      is_set = isinstance(list_, (set, frozenset, ut.oset))
      is_onetup = isinstance(list_, (tuple)) and len(list_) <= 1
      if nobraces:
          lbr, rbr = '', ''
      elif is_tuple:
          lbr, rbr  = '(', ')'
      elif is_set:
          lbr, rbr  = '{', '}'
      else:
          lbr, rbr  = '[', ']'
  
      if len(itemstr_list) == 0:
          newlines = False
  
      if newlines is not False and (newlines is True or newlines > 0):
          sep = ',\n' if with_comma else '\n'
          if nobraces:
              body_str = sep.join(itemstr_list)
              if trailing_sep:
                  body_str += ','
              retstr = body_str
          else:
              if packed:
                  # DEPRICATE?
                  joinstr = sep + itemsep * len(lbr)
                  body_str = joinstr.join([itemstr for itemstr in itemstr_list])
                  if trailing_sep:
                      body_str += ','
                  braced_body_str = (lbr + '' + body_str + '' + rbr)
              else:
                  body_str = sep.join([
                      ut.indent(itemstr) for itemstr in itemstr_list])
                  if trailing_sep:
                      body_str += ','
                  braced_body_str = (lbr + '\n' + body_str + '\n' + rbr)
              retstr = braced_body_str
      else:
          sep = ',' + itemsep if with_comma else itemsep
          body_str = sep.join(itemstr_list)
          if is_onetup:
              body_str += ','
          retstr  = (lbr + body_str +  rbr)
  
      # TODO: rectify with dict_truncate
      do_truncate = truncate is not False and (truncate is True or truncate == 0)
      if do_truncate:
          truncatekw = listkw.get('truncatekw', {})
          retstr = truncate_str(retstr, **truncatekw)
      return retstr