diff options
-rwxr-xr-x | bin/qmk | 62 | ||||
-rw-r--r-- | docs/cli.md | 250 | ||||
-rw-r--r-- | docs/cli_development.md | 2 | ||||
-rwxr-xr-x | lib/python/qmk/cli/hello.py | 2 | ||||
-rwxr-xr-x | lib/python/qmk/cli/pyformat.py | 2 | ||||
-rw-r--r-- | lib/python/qmk/cli/pytest.py | 2 | ||||
-rw-r--r-- | requirements-dev.txt | 4 | ||||
-rw-r--r-- | requirements.txt | 3 |
8 files changed, 302 insertions, 25 deletions
@@ -4,34 +4,58 @@ | |||
4 | import os | 4 | import os |
5 | import sys | 5 | import sys |
6 | from importlib.util import find_spec | 6 | from importlib.util import find_spec |
7 | from time import strftime | ||
8 | from pathlib import Path | ||
7 | 9 | ||
8 | # Add the QMK python libs to our path | 10 | # Add the QMK python libs to our path |
9 | script_dir = os.path.dirname(os.path.realpath(__file__)) | 11 | script_dir = Path(os.path.realpath(__file__)).parent |
10 | qmk_dir = os.path.abspath(os.path.join(script_dir, '..')) | 12 | qmk_dir = script_dir.parent |
11 | python_lib_dir = os.path.abspath(os.path.join(qmk_dir, 'lib', 'python')) | 13 | python_lib_dir = Path(qmk_dir / 'lib' / 'python').resolve() |
12 | sys.path.append(python_lib_dir) | 14 | sys.path.append(str(python_lib_dir)) |
15 | |||
16 | # QMK CLI user config file | ||
17 | config_file = Path(Path.home() / '.config/qmk/qmk.ini') | ||
13 | 18 | ||
14 | # Make sure our modules have been setup | ||
15 | with open(os.path.join(qmk_dir, 'requirements.txt'), 'r') as fd: | ||
16 | for line in fd.readlines(): | ||
17 | line = line.strip().replace('<', '=').replace('>', '=') | ||
18 | 19 | ||
19 | if line[0] == '#': | 20 | def _check_modules(requirements): |
20 | continue | 21 | """ Check if the modules in the given requirements.txt are available. |
22 | """ | ||
23 | with Path(qmk_dir / requirements).open() as fd: | ||
24 | for line in fd.readlines(): | ||
25 | line = line.strip().replace('<', '=').replace('>', '=') | ||
21 | 26 | ||
22 | if '#' in line: | 27 | if line[0] == '#': |
23 | line = line.split('#')[0] | 28 | continue |
24 | 29 | ||
25 | module = line.split('=')[0] if '=' in line else line | 30 | if '#' in line: |
31 | line = line.split('#')[0] | ||
32 | |||
33 | module = dict() | ||
34 | module['name'] = module['import'] = line.split('=')[0] if '=' in line else line | ||
26 | 35 | ||
27 | if module in ['pep8-naming']: | ||
28 | # Not every module is importable by its own name. | 36 | # Not every module is importable by its own name. |
29 | continue | 37 | if module['name'] == "pep8-naming": |
38 | module['import'] = "pep8ext_naming" | ||
30 | 39 | ||
31 | if not find_spec(module): | 40 | if not find_spec(module['import']): |
32 | print('Could not find module %s!' % module) | 41 | print('Could not find module %s!' % module['name']) |
33 | print('Please run `pip3 install -r requirements.txt` to install the python dependencies.') | 42 | if developer: |
34 | exit(255) | 43 | print('Please run `pip3 install -r requirements-dev.txt` to install the python development dependencies or turn off developer mode with `qmk config user.developer=None`.') |
44 | print() | ||
45 | else: | ||
46 | print('Please run `pip3 install -r requirements.txt` to install the python dependencies.') | ||
47 | print() | ||
48 | exit(255) | ||
49 | |||
50 | |||
51 | developer = False | ||
52 | # Make sure our modules have been setup | ||
53 | _check_modules('requirements.txt') | ||
54 | |||
55 | # For developers additional modules are needed | ||
56 | if config_file.exists() and 'developer = True' in config_file.read_text(): | ||
57 | developer = True | ||
58 | _check_modules('requirements-dev.txt') | ||
35 | 59 | ||
36 | # Setup the CLI | 60 | # Setup the CLI |
37 | import milc # noqa | 61 | import milc # noqa |
diff --git a/docs/cli.md b/docs/cli.md index 760fe1cdb..625ac4fb7 100644 --- a/docs/cli.md +++ b/docs/cli.md | |||
@@ -37,3 +37,253 @@ We are looking for people to create and maintain a `qmk` package for more operat | |||
37 | * Document why in a comment when you do deviate | 37 | * Document why in a comment when you do deviate |
38 | * Install using a virtualenv | 38 | * Install using a virtualenv |
39 | * Instruct the user to set the environment variable `QMK_HOME` to have the firmware source checked out somewhere other than `~/qmk_firmware`. | 39 | * Instruct the user to set the environment variable `QMK_HOME` to have the firmware source checked out somewhere other than `~/qmk_firmware`. |
40 | |||
41 | # Local CLI | ||
42 | |||
43 | If you do not want to use the global CLI there is a local CLI bundled with `qmk_firmware`. You can find it in `qmk_firmware/bin/qmk`. You can run the `qmk` command from any directory and it will always operate on that copy of `qmk_firmware`. | ||
44 | |||
45 | **Example**: | ||
46 | |||
47 | ``` | ||
48 | $ ~/qmk_firmware/bin/qmk hello | ||
49 | Ψ Hello, World! | ||
50 | ``` | ||
51 | |||
52 | ## Local CLI Limitations | ||
53 | |||
54 | There are some limitations to the local CLI compared to the global CLI: | ||
55 | |||
56 | * The local CLI does not support `qmk setup` or `qmk clone` | ||
57 | * The local CLI always operates on the same `qmk_firmware` tree, even if you have multiple repositories cloned. | ||
58 | * The local CLI does not run in a virtualenv, so it's possible that dependencies will conflict | ||
59 | |||
60 | # CLI Commands | ||
61 | |||
62 | ## `qmk cformat` | ||
63 | |||
64 | *dev mode* | ||
65 | |||
66 | This command formats C code using clang-format. Run it with no arguments to format all core code, or pass filenames on the command line to run it on specific files. | ||
67 | |||
68 | **Usage**: | ||
69 | |||
70 | ``` | ||
71 | qmk cformat [file1] [file2] [...] [fileN] | ||
72 | ``` | ||
73 | |||
74 | ## `qmk compile` | ||
75 | |||
76 | This command allows you to compile firmware from any directory. You can compile JSON exports from <https://config.qmk.fm>, compile keymaps in the repo, or compile the keyboard in the current working directory. | ||
77 | |||
78 | **Usage for Configurator Exports**: | ||
79 | |||
80 | ``` | ||
81 | qmk compile <configuratorExport.json> | ||
82 | ``` | ||
83 | |||
84 | **Usage for Keymaps**: | ||
85 | |||
86 | ``` | ||
87 | qmk compile -kb <keyboard_name> -km <keymap_name> | ||
88 | ``` | ||
89 | |||
90 | **Usage in Keyboard Directory**: | ||
91 | |||
92 | Must be in keyboard directory with a default keymap, or in keymap directory for keyboard, or supply one with `--keymap <keymap_name>` | ||
93 | ``` | ||
94 | qmk compile | ||
95 | ``` | ||
96 | |||
97 | **Example**: | ||
98 | ``` | ||
99 | $ qmk config compile.keymap=default | ||
100 | $ cd ~/qmk_firmware/keyboards/planck/rev6 | ||
101 | $ qmk compile | ||
102 | Ψ Compiling keymap with make planck/rev6:default | ||
103 | ... | ||
104 | ``` | ||
105 | or with optional keymap argument | ||
106 | |||
107 | ``` | ||
108 | $ cd ~/qmk_firmware/keyboards/clueboard/66/rev4 | ||
109 | $ qmk compile -km 66_iso | ||
110 | Ψ Compiling keymap with make clueboard/66/rev4:66_iso | ||
111 | ... | ||
112 | ``` | ||
113 | or in keymap directory | ||
114 | |||
115 | ``` | ||
116 | $ cd ~/qmk_firmware/keyboards/gh60/satan/keymaps/colemak | ||
117 | $ qmk compile | ||
118 | Ψ Compiling keymap with make make gh60/satan:colemak | ||
119 | ... | ||
120 | ``` | ||
121 | |||
122 | **Usage in Layout Directory**: | ||
123 | |||
124 | Must be under `qmk_firmware/layouts/`, and in a keymap folder. | ||
125 | ``` | ||
126 | qmk compile -kb <keyboard_name> | ||
127 | ``` | ||
128 | |||
129 | **Example**: | ||
130 | ``` | ||
131 | $ cd ~/qmk_firmware/layouts/community/60_ansi/mechmerlin-ansi | ||
132 | $ qmk compile -kb dz60 | ||
133 | Ψ Compiling keymap with make dz60:mechmerlin-ansi | ||
134 | ... | ||
135 | ``` | ||
136 | |||
137 | ## `qmk flash` | ||
138 | |||
139 | This command is similar to `qmk compile`, but can also target a bootloader. The bootloader is optional, and is set to `:flash` by default. | ||
140 | To specify a different bootloader, use `-bl <bootloader>`. Visit <https://docs.qmk.fm/#/flashing> | ||
141 | for more details of the available bootloaders. | ||
142 | |||
143 | **Usage for Configurator Exports**: | ||
144 | |||
145 | ``` | ||
146 | qmk flash <configuratorExport.json> -bl <bootloader> | ||
147 | ``` | ||
148 | |||
149 | **Usage for Keymaps**: | ||
150 | |||
151 | ``` | ||
152 | qmk flash -kb <keyboard_name> -km <keymap_name> -bl <bootloader> | ||
153 | ``` | ||
154 | |||
155 | **Listing the Bootloaders** | ||
156 | |||
157 | ``` | ||
158 | qmk flash -b | ||
159 | ``` | ||
160 | |||
161 | ## `qmk config` | ||
162 | |||
163 | This command lets you configure the behavior of QMK. For the full `qmk config` documentation see [CLI Configuration](cli_configuration.md). | ||
164 | |||
165 | **Usage**: | ||
166 | |||
167 | ``` | ||
168 | qmk config [-ro] [config_token1] [config_token2] [...] [config_tokenN] | ||
169 | ``` | ||
170 | |||
171 | ## `qmk docs` | ||
172 | |||
173 | This command starts a local HTTP server which you can use for browsing or improving the docs. Default port is 8936. | ||
174 | |||
175 | **Usage**: | ||
176 | |||
177 | ``` | ||
178 | qmk docs [-p PORT] | ||
179 | ``` | ||
180 | |||
181 | ## `qmk doctor` | ||
182 | |||
183 | This command examines your environment and alerts you to potential build or flash problems. It can fix many of them if you want it to. | ||
184 | |||
185 | **Usage**: | ||
186 | |||
187 | ``` | ||
188 | qmk doctor [-y] [-n] | ||
189 | ``` | ||
190 | |||
191 | **Examples**: | ||
192 | |||
193 | Check your environment for problems and prompt to fix them: | ||
194 | |||
195 | qmk doctor | ||
196 | |||
197 | Check your environment and automatically fix any problems found: | ||
198 | |||
199 | qmk doctor -y | ||
200 | |||
201 | Check your environment and report problems only: | ||
202 | |||
203 | qmk doctor -n | ||
204 | |||
205 | ## `qmk json-keymap` | ||
206 | |||
207 | Creates a keymap.c from a QMK Configurator export. | ||
208 | |||
209 | **Usage**: | ||
210 | |||
211 | ``` | ||
212 | qmk json-keymap [-o OUTPUT] filename | ||
213 | ``` | ||
214 | |||
215 | ## `qmk kle2json` | ||
216 | |||
217 | This command allows you to convert from raw KLE data to QMK Configurator JSON. It accepts either an absolute file path, or a file name in the current directory. By default it will not overwrite `info.json` if it is already present. Use the `-f` or `--force` flag to overwrite. | ||
218 | |||
219 | **Usage**: | ||
220 | |||
221 | ``` | ||
222 | qmk kle2json [-f] <filename> | ||
223 | ``` | ||
224 | |||
225 | **Examples**: | ||
226 | |||
227 | ``` | ||
228 | $ qmk kle2json kle.txt | ||
229 | ☒ File info.json already exists, use -f or --force to overwrite. | ||
230 | ``` | ||
231 | |||
232 | ``` | ||
233 | $ qmk kle2json -f kle.txt -f | ||
234 | Ψ Wrote out to info.json | ||
235 | ``` | ||
236 | |||
237 | ## `qmk list-keyboards` | ||
238 | |||
239 | This command lists all the keyboards currently defined in `qmk_firmware` | ||
240 | |||
241 | **Usage**: | ||
242 | |||
243 | ``` | ||
244 | qmk list-keyboards | ||
245 | ``` | ||
246 | |||
247 | ## `qmk list-keymaps` | ||
248 | |||
249 | This command lists all the keymaps for a specified keyboard (and revision). | ||
250 | |||
251 | **Usage**: | ||
252 | |||
253 | ``` | ||
254 | qmk list-keymaps -kb planck/ez | ||
255 | ``` | ||
256 | |||
257 | ## `qmk new-keymap` | ||
258 | |||
259 | This command creates a new keymap based on a keyboard's existing default keymap. | ||
260 | |||
261 | **Usage**: | ||
262 | |||
263 | ``` | ||
264 | qmk new-keymap [-kb KEYBOARD] [-km KEYMAP] | ||
265 | ``` | ||
266 | |||
267 | ## `qmk pyformat` | ||
268 | |||
269 | *dev mode* | ||
270 | |||
271 | This command formats python code in `qmk_firmware`. | ||
272 | |||
273 | **Usage**: | ||
274 | |||
275 | ``` | ||
276 | qmk pyformat | ||
277 | ``` | ||
278 | |||
279 | ## `qmk pytest` | ||
280 | |||
281 | *dev mode* | ||
282 | |||
283 | This command runs the python test suite. If you make changes to python code you should ensure this runs successfully. | ||
284 | |||
285 | **Usage**: | ||
286 | |||
287 | ``` | ||
288 | qmk pytest | ||
289 | ``` | ||
diff --git a/docs/cli_development.md b/docs/cli_development.md index cc8c59d06..e41afc42f 100644 --- a/docs/cli_development.md +++ b/docs/cli_development.md | |||
@@ -6,6 +6,8 @@ This document has useful information for developers wishing to write new `qmk` s | |||
6 | 6 | ||
7 | The QMK CLI operates using the subcommand pattern made famous by git. The main `qmk` script is simply there to setup the environment and pick the correct entrypoint to run. Each subcommand is a self-contained module with an entrypoint (decorated by `@cli.subcommand()`) that performs some action and returns a shell returncode, or None. | 7 | The QMK CLI operates using the subcommand pattern made famous by git. The main `qmk` script is simply there to setup the environment and pick the correct entrypoint to run. Each subcommand is a self-contained module with an entrypoint (decorated by `@cli.subcommand()`) that performs some action and returns a shell returncode, or None. |
8 | 8 | ||
9 | *Tip*: Enable dev mode by `qmk config user.developer=True` | ||
10 | |||
9 | # Subcommands | 11 | # Subcommands |
10 | 12 | ||
11 | [MILC](https://github.com/clueboard/milc) is the CLI framework `qmk` uses to handle argument parsing, configuration, logging, and many other features. It lets you focus on writing your tool without wasting your time writing glue code. | 13 | [MILC](https://github.com/clueboard/milc) is the CLI framework `qmk` uses to handle argument parsing, configuration, logging, and many other features. It lets you focus on writing your tool without wasting your time writing glue code. |
diff --git a/lib/python/qmk/cli/hello.py b/lib/python/qmk/cli/hello.py index bee28c301..5119188a0 100755 --- a/lib/python/qmk/cli/hello.py +++ b/lib/python/qmk/cli/hello.py | |||
@@ -6,7 +6,7 @@ from milc import cli | |||
6 | 6 | ||
7 | 7 | ||
8 | @cli.argument('-n', '--name', default='World', help='Name to greet.') | 8 | @cli.argument('-n', '--name', default='World', help='Name to greet.') |
9 | @cli.subcommand('QMK Hello World.') | 9 | @cli.subcommand('QMK Hello World.', hidden=False if cli.config.user.developer else True) |
10 | def hello(cli): | 10 | def hello(cli): |
11 | """Log a friendly greeting. | 11 | """Log a friendly greeting. |
12 | """ | 12 | """ |
diff --git a/lib/python/qmk/cli/pyformat.py b/lib/python/qmk/cli/pyformat.py index a53ba40c0..146444380 100755 --- a/lib/python/qmk/cli/pyformat.py +++ b/lib/python/qmk/cli/pyformat.py | |||
@@ -5,7 +5,7 @@ from milc import cli | |||
5 | import subprocess | 5 | import subprocess |
6 | 6 | ||
7 | 7 | ||
8 | @cli.subcommand("Format python code according to QMK's style.") | 8 | @cli.subcommand("Format python code according to QMK's style.", hidden=False if cli.config.user.developer else True) |
9 | def pyformat(cli): | 9 | def pyformat(cli): |
10 | """Format python code according to QMK's style. | 10 | """Format python code according to QMK's style. |
11 | """ | 11 | """ |
diff --git a/lib/python/qmk/cli/pytest.py b/lib/python/qmk/cli/pytest.py index 09611d750..5417a9cb3 100644 --- a/lib/python/qmk/cli/pytest.py +++ b/lib/python/qmk/cli/pytest.py | |||
@@ -7,7 +7,7 @@ import subprocess | |||
7 | from milc import cli | 7 | from milc import cli |
8 | 8 | ||
9 | 9 | ||
10 | @cli.subcommand('QMK Python Unit Tests') | 10 | @cli.subcommand('QMK Python Unit Tests', hidden=False if cli.config.user.developer else True) |
11 | def pytest(cli): | 11 | def pytest(cli): |
12 | """Run several linting/testing commands. | 12 | """Run several linting/testing commands. |
13 | """ | 13 | """ |
diff --git a/requirements-dev.txt b/requirements-dev.txt new file mode 100644 index 000000000..deab419cb --- /dev/null +++ b/requirements-dev.txt | |||
@@ -0,0 +1,4 @@ | |||
1 | # Python development requirements | ||
2 | nose2 | ||
3 | flake8 | ||
4 | pep8-naming | ||
diff --git a/requirements.txt b/requirements.txt index 074b11a8c..aa6ee1ba3 100644 --- a/requirements.txt +++ b/requirements.txt | |||
@@ -4,6 +4,3 @@ appdirs | |||
4 | argcomplete | 4 | argcomplete |
5 | colorama | 5 | colorama |
6 | hjson | 6 | hjson |
7 | nose2 | ||
8 | flake8 | ||
9 | pep8-naming | ||