lexers.py 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657
  1. import os
  2. from .exceptions import ArgcompleteException
  3. from .io import debug
  4. from .packages import _shlex
  5. def split_line(line, point=None):
  6. if point is None:
  7. point = len(line)
  8. line = line[:point]
  9. lexer = _shlex.shlex(line, posix=True)
  10. lexer.whitespace_split = True
  11. lexer.wordbreaks = os.environ.get("_ARGCOMPLETE_COMP_WORDBREAKS", "")
  12. words = []
  13. def split_word(word):
  14. # TODO: make this less ugly
  15. point_in_word = len(word) + point - lexer.instream.tell()
  16. if isinstance(lexer.state, (str, bytes)) and lexer.state in lexer.whitespace:
  17. point_in_word += 1
  18. if point_in_word > len(word):
  19. debug("In trailing whitespace")
  20. words.append(word)
  21. word = ""
  22. prefix, suffix = word[:point_in_word], word[point_in_word:]
  23. prequote = ""
  24. # posix
  25. if lexer.state is not None and lexer.state in lexer.quotes:
  26. prequote = lexer.state
  27. # non-posix
  28. # if len(prefix) > 0 and prefix[0] in lexer.quotes:
  29. # prequote, prefix = prefix[0], prefix[1:]
  30. return prequote, prefix, suffix, words, lexer.last_wordbreak_pos
  31. while True:
  32. try:
  33. word = lexer.get_token()
  34. if word == lexer.eof:
  35. # TODO: check if this is ever unsafe
  36. # raise ArgcompleteException("Unexpected end of input")
  37. return "", "", "", words, None
  38. if lexer.instream.tell() >= point:
  39. debug("word", word, "split, lexer state: '{s}'".format(s=lexer.state))
  40. return split_word(word)
  41. words.append(word)
  42. except ValueError:
  43. debug("word", lexer.token, "split (lexer stopped, state: '{s}')".format(s=lexer.state))
  44. if lexer.instream.tell() >= point:
  45. return split_word(lexer.token)
  46. else:
  47. msg = (
  48. "Unexpected internal state. "
  49. "Please report this bug at https://github.com/kislyuk/argcomplete/issues."
  50. )
  51. raise ArgcompleteException(msg)