docs: def _var_strings(self, v_name, v_values, v_idx=None, v_start=None):
          """Convert namelist variable to list of fixed-width strings."""
          if self.uppercase:
              v_name = v_name.upper()
  
          var_strs = []
  
          # Parse a multidimensional array
          if is_nullable_list(v_values, list):
              if not v_idx:
                  v_idx = []
  
              i_s = v_start[::-1][len(v_idx)] if v_start else None
  
              # FIXME: We incorrectly assume 1-based indexing if it is
              # unspecified.  This is necessary because our output method always
              # separates the outer axes to one per line.  But we cannot do this
              # if we don't know the first index (which we are no longer assuming
              # to be 1-based elsewhere).  Unfortunately, the solution needs a
              # rethink of multidimensional output.
  
              # NOTE: Fixing this would also clean up the output of todict(),
              # which is now incorrectly documenting unspecified indices as 1.
  
              # For now, we will assume 1-based indexing here, just to keep
              # things working smoothly.
              if i_s is None:
                  i_s = 1
  
              for idx, val in enumerate(v_values, start=i_s):
                  v_idx_new = v_idx + [idx]
                  v_strs = self._var_strings(v_name, val, v_idx=v_idx_new,
                                             v_start=v_start)
                  var_strs.extend(v_strs)
  
          # Parse derived type contents
          elif isinstance(v_values, Namelist):
              for f_name, f_vals in v_values.items():
                  v_title = '%'.join([v_name, f_name])
  
                  v_start_new = v_values.start_index.get(f_name, None)
  
                  v_strs = self._var_strings(v_title, f_vals,
                                             v_start=v_start_new)
                  var_strs.extend(v_strs)
  
          # Parse an array of derived types
          elif is_nullable_list(v_values, Namelist):
              if not v_idx:
                  v_idx = []
  
              i_s = v_start[::-1][len(v_idx)] if v_start else 1
  
              for idx, val in enumerate(v_values, start=i_s):
  
                  # Skip any empty elements in a list of derived types
                  if val is None:
                      continue
  
                  v_title = v_name + '({0})'.format(idx)
  
                  v_strs = self._var_strings(v_title, val)
                  var_strs.extend(v_strs)
  
          else:
              use_default_start_index = False
              if not isinstance(v_values, list):
                  v_values = [v_values]
                  use_default_start_index = False
              else:
                  use_default_start_index = self.default_start_index is not None
  
              # Print the index range
  
              # TODO: Include a check for len(v_values) to determine if vector
              if v_idx or v_start or use_default_start_index:
                  v_idx_repr = '('
  
                  if v_start or use_default_start_index:
                      if v_start:
                          i_s = v_start[0]
                      else:
                          i_s = self.default_start_index
  
                      if i_s is None:
                          v_idx_repr += ':'
  
                      else:
                          i_e = i_s + len(v_values) - 1
  
                          if i_s == i_e:
                              v_idx_repr += '{0}'.format(i_s)
                          else:
                              v_idx_repr += '{0}:{1}'.format(i_s, i_e)
                  else:
                      v_idx_repr += ':'
  
                  if v_idx:
                      idx_delim = ', ' if self._index_spacing else ','
                      v_idx_repr += idx_delim
                      v_idx_repr += idx_delim.join(str(i) for i in v_idx[::-1])
  
                  v_idx_repr += ')'
  
              else:
                  v_idx_repr = ''
  
              # Split output across multiple lines (if necessary)
  
              val_strs = []
  
              val_line = ''
              for v_val in v_values:
  
                  v_header = v_name + v_idx_repr + ' = '
                  # Increase column width if the header exceeds this value
                  if len(self.indent + v_header) >= self.column_width:
                      column_width = len(self.indent + v_header) + 1
                  else:
                      column_width = self.column_width
  
                  v_width = column_width - len(self.indent + v_header)
  
                  if len(val_line) < v_width:
                      val_line += self._f90repr(v_val) + ', '
  
                  if len(val_line) >= v_width:
                      val_strs.append(val_line.rstrip())
                      val_line = ''
  
              # Append any remaining values
              if val_line:
                  val_strs.append(val_line.rstrip())
  
              if val_strs:
                  if self.end_comma or v_values[-1] is None:
                      pass
                  else:
                      val_strs[-1] = val_strs[-1][:-1]
  
              # Complete the set of values
              if val_strs:
                  var_strs.append('{0}{1} = {2}'
                                  ''.format(v_name, v_idx_repr,
                                            val_strs[0]).strip())
  
                  for v_str in val_strs[1:]:
                      var_strs.append(' ' * len(v_header) + v_str)
  
          return var_strs