text: # -*- coding: utf-8 -*-
  
  """
  clint.arguments
  ~~~~~~~~~~~~~~~
  
  This module provides the CLI argument interface.
  
  """
  
  
  from __future__ import absolute_import
  
  import os
  from sys import argv
  from glob import glob
  
  from .packages.ordereddict import OrderedDict
  from .utils import is_collection
  
  
  
  __all__ = ('Args', )
  
  
  
  def _expand_path(path):
      """Expands directories and globs in given path."""
  
      paths = []
  
      if os.path.isdir(path):
  
          for (dir, dirs, files) in os.walk(path):
              for file in files:
                  paths.append(os.path.join(dir, file))
      else:
          paths.extend(glob(path))
  
      return paths
  
  
  class Args(object):
      """CLI Argument management."""
  
      def __init__(self, args=None, no_argv=False):
          if not args:
              if not no_argv:
                  self._args = argv[1:]
              else:
                  self._args = []
          else:
              self._args = args
  
  
      def __len__(self):
          return len(self._args)
  
  
      def __repr__(self):
          return '<args %s>' % (repr(self._args))
  
  
      def __getitem__(self, i):
          try:
              return self.all[i]
          except IndexError:
              return None
  
  
      def __contains__(self, x):
          return self.first(x) is not None
  
  
      def get(self, x):
          """Returns argument at given index, else none."""
          try:
              return self.all[x]
          except IndexError:
              return None
  
  
      def get_with(self, x):
          """Returns first argument that contains given string."""
          return self.all[self.first_with(x)]
  
  
      def remove(self, x):
          """Removes given arg (or list thereof) from Args object."""
  
          def _remove(x):
              found = self.first(x)
              if found is not None:
                  self._args.pop(found)
  
          if is_collection(x):
              for item in x:
                  _remove(x)
          else:
              _remove(x)
  
  
      def pop(self, x):
          """Removes and Returns value at given index, else none."""
          try:
              return self._args.pop(x)
          except IndexError:
              return None
  
  
      def any_contain(self, x):
          """Tests if given string is contained in any stored argument."""
          
          return bool(self.first_with(x))
  
  
      def contains(self, x):
          """Tests if given object is in arguments list. 
             Accepts strings and lists of strings."""
          
          return self.__contains__(x)
  
  
      def first(self, x):
          """Returns first found index of given value (or list of values)"""
          
          def _find( x):
              try:
                  return self.all.index(str(x))
              except ValueError:
                  return None
  
          if is_collection(x):
              for item in x:
                  found = _find(item)
                  if found is not None:
                      return found
              return None
          else:
              return _find(x)
  
  
      def first_with(self, x):
          """Returns first found index containing value (or list of values)"""
  
          def _find(x):
              try:
                  for arg in self.all:
                      if x in arg:
                          return self.all.index(arg)
              except ValueError:
                  return None
  
          if is_collection(x):
              for item in x:
                  found = _find(item)
                  if found:
                      return found
              return None
          else:
              return _find(x)
  
  
      def first_without(self, x):
          """Returns first found index not containing value (or list of values)"""
  
          def _find(x):
              try:
                  for arg in self.all:
                      if x not in arg:
                          return self.all.index(arg)
              except ValueError:
                  return None
  
          if is_collection(x):
              for item in x:
                  found = _find(item)
                  if found:
                      return found
              return None
          else:
              return _find(x)
  
  
      def start_with(self, x):
             """Returns all arguments beginning with given string (or list thereof)"""
  
             _args = []
  
             for arg in self.all:
                 if is_collection(x):
                     for _x in x:
                         if arg.startswith(x):
                             _args.append(arg)
                             break
                 else:
                     if arg.startswith(x):
                         _args.append(arg)
  
             return Args(_args, no_argv=True)
  
  
      def contains_at(self, x, index):
          """Tests if given [list of] string is at given index."""
  
          try:
              if is_collection(x):
                  for _x in x:
                      if (_x in self.all[index]) or (_x == self.all[index]):
                          return True
                      else:
                          return False
              else:
                  return (x in self.all[index])
          
          except IndexError:
              return False
  
  
      def has(self, x):
          """Returns true if argument exists at given index.
             Accepts: integer.
          """
          
          try:
              self.all[x]
              return True
          except IndexError:
              return False
  
  
      def value_after(self, x):
          """Returns value of argument after given found argument (or list thereof)."""
          
          try:
              try:
                  i = self.all.index(x)
              except ValueError:
                  return None
                  
              return self.all[i + 1]
              
          except IndexError:
              return None
  
  
      @property
      def grouped(self):
          """Extracts --flag groups from argument list.
             Returns {format: Args, ...}
          """
  
          collection = OrderedDict(_=Args(no_argv=True))
  
          _current_group = None
  
          for arg in self.all:
              if arg.startswith('-'):
                  _current_group = arg
                  collection[arg] = Args(no_argv=True)
              else:
                  if _current_group:
                      collection[_current_group]._args.append(arg)
                  else:
                      collection['_']._args.append(arg)
  
          return collection
  
      
      @property
      def last(self):
          """Returns last argument."""
          
          try:
              return self.all[-1]
          except IndexError:
              return None
  
      
      @property
      def all(self):
          """Returns all arguments."""
          
          return self._args
  
  
      def all_with(self, x):
          """Returns all arguments containing given string (or list thereof)"""
  
          _args = []
          
          for arg in self.all:
              if is_collection(x):
                  for _x in x:
                      if _x in arg:
                          _args.append(arg)
                          break
              else:
                  if x in arg:
                      _args.append(arg)
  
          return Args(_args, no_argv=True)
  
  
      def all_without(self, x):
          """Returns all arguments not containing given string (or list thereof)"""
  
          _args = []
  
          for arg in self.all:
              if is_collection(x):
                  for _x in x:
                      if _x not in arg:
                          _args.append(arg)
                          break
              else:
                  if x not in arg:
                      _args.append(arg)
  
          return Args(_args, no_argv=True)
  
  
      @property
      def flags(self):
          """Returns Arg object including only flagged arguments."""
  
          return self.start_with('-')
  
  
      @property    
      def not_flags(self):
          """Returns Arg object excluding flagged arguments."""
  
          return self.all_without('-')
  
  
      @property
      def files(self, absolute=False):
          """Returns an expanded list of all valid paths that were passed in."""
  
          _paths = []
  
          for arg in self.all:
              for path in _expand_path(arg):
                  if os.path.exists(path):
                      if absolute:
                          _paths.append(os.path.abspath(path))
                      else:
                          _paths.append(path)
  
          return _paths
  
  
      @property
      def not_files(self):
          """Returns a list of all arguments that aren't files/globs."""
  
          _args = []
  
          for arg in self.all:
              if not len(_expand_path(arg)):
                  if not os.path.exists(arg):
                      _args.append(arg)
  
          return Args(_args, no_argv=True)
  
      @property
      def copy(self):
          """Returns a copy of Args object for temporary manipulation."""
  
          return Args(self.all)
  
  