1# -*- coding: utf-8 -*-
2"""Test XonshLexer for pygments"""
3
4import os
5import builtins
6
7import pytest
8from pygments.token import (
9    Keyword,
10    Name,
11    String,
12    Error,
13    Number,
14    Operator,
15    Punctuation,
16    Text,
17)
18from tools import skip_if_on_windows
19
20from xonsh.platform import ON_WINDOWS
21from xonsh.built_ins import load_builtins, unload_builtins
22from xonsh.pyghooks import XonshLexer
23
24
25@pytest.yield_fixture(autouse=True)
26def load_command_cache():
27    load_builtins()
28    if ON_WINDOWS:
29        for key in ("cd", "bash"):
30            builtins.aliases[key] = lambda *args, **kwargs: None
31    yield
32    unload_builtins()
33
34
35def check_token(code, tokens):
36    """Make sure that all tokens appears in code in order"""
37    lx = XonshLexer()
38    tks = list(lx.get_tokens(code))
39
40    for tk in tokens:
41        while tks:
42            if tk == tks[0]:
43                break
44            tks = tks[1:]
45        else:
46            msg = "Token {!r} missing: {!r}".format(tk, list(lx.get_tokens(code)))
47            pytest.fail(msg)
48            break
49
50
51@skip_if_on_windows
52def test_ls():
53    check_token("ls -al", [(Name.Builtin, "ls")])
54
55
56@skip_if_on_windows
57def test_bin_ls():
58    check_token("/bin/ls -al", [(Name.Builtin, "/bin/ls")])
59
60
61def test_py_print():
62    check_token('print("hello")', [(Keyword, "print"), (String.Double, "hello")])
63
64
65def test_invalid_cmd():
66    check_token("non-existance-cmd -al", [(Name, "non")])  # parse as python
67    check_token(
68        "![non-existance-cmd -al]", [(Error, "non-existance-cmd")]
69    )  # parse as error
70    check_token("for i in range(10):", [(Keyword, "for")])  # as py keyword
71    check_token("(1, )", [(Punctuation, "("), (Number.Integer, "1")])
72
73
74def test_multi_cmd():
75    check_token(
76        "cd && cd", [(Name.Builtin, "cd"), (Operator, "&&"), (Name.Builtin, "cd")]
77    )
78    check_token(
79        "cd || non-existance-cmd",
80        [(Name.Builtin, "cd"), (Operator, "||"), (Error, "non-existance-cmd")],
81    )
82
83
84def test_nested():
85    check_token(
86        'echo @("hello")',
87        [
88            (Name.Builtin, "echo"),
89            (Keyword, "@"),
90            (Punctuation, "("),
91            (String.Double, "hello"),
92            (Punctuation, ")"),
93        ],
94    )
95    check_token(
96        "print($(cd))",
97        [
98            (Keyword, "print"),
99            (Punctuation, "("),
100            (Keyword, "$"),
101            (Punctuation, "("),
102            (Name.Builtin, "cd"),
103            (Punctuation, ")"),
104            (Punctuation, ")"),
105        ],
106    )
107    check_token(
108        r'print(![echo "])\""])',
109        [
110            (Keyword, "print"),
111            (Keyword, "!"),
112            (Punctuation, "["),
113            (Name.Builtin, "echo"),
114            (String.Double, r'"])\""'),
115            (Punctuation, "]"),
116        ],
117    )
118
119
120def test_path(tmpdir):
121    test_dir = str(tmpdir.mkdir("xonsh-test-highlight-path"))
122    check_token(
123        "cd {}".format(test_dir), [(Name.Builtin, "cd"), (Name.Constant, test_dir)]
124    )
125    check_token(
126        "cd {}-xxx".format(test_dir),
127        [(Name.Builtin, "cd"), (Text, "{}-xxx".format(test_dir))],
128    )
129    check_token("cd X={}".format(test_dir), [(Name.Constant, test_dir)])
130
131    with builtins.__xonsh_env__.swap(AUTO_CD=True):
132        check_token(test_dir, [(Name.Constant, test_dir)])
133
134
135def test_subproc_args():
136    check_token("cd 192.168.0.1", [(Text, "192.168.0.1")])
137
138
139def test_backtick():
140    check_token(
141        r"echo g`.*\w+`",
142        [
143            (String.Affix, "g"),
144            (String.Backtick, "`"),
145            (String.Regex, "."),
146            (String.Regex, "*"),
147            (String.Escape, r"\w"),
148        ],
149    )
150
151
152def test_macro():
153    check_token(
154        r"g!(42, *, 65)",
155        [(Name, "g"), (Keyword, "!"), (Punctuation, "("), (Number.Integer, "42")],
156    )
157    check_token(
158        r"echo! hello world",
159        [(Name.Builtin, "echo"), (Keyword, "!"), (String, "hello world")],
160    )
161    check_token(
162        r"bash -c ! export var=42; echo $var",
163        [
164            (Name.Builtin, "bash"),
165            (Text, "-c"),
166            (Keyword, "!"),
167            (String, "export var=42; echo $var"),
168        ],
169    )
170