summaryrefslogtreecommitdiffstats
path: root/tools/tryselect/docs/selectors/fuzzy.rst
blob: d50f801eb094935bb0cf90dcacf43eeee9c3764c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
Fuzzy Selector
==============

The fuzzy selector uses a tool called `fzf`_. It allows you to filter down all of the task labels
from a terminal based UI and an intelligent fuzzy finding algorithm. If the ``fzf`` binary is not
installed, you'll be prompted to bootstrap it on first run.


Understanding the Interface
---------------------------

When you run ``mach try fuzzy`` an interface similar to the one below will open. This is `fzf`_.

.. image:: fzf.png

There's a lot to unpack here, so let's examine each component a bit more closely.

   A. The set of tasks that match the currently typed-out query. In the above image only tasks that
   match the query ``'linux64 mochibrochr`` are displayed.

   B. The set of selected tasks. These are the tasks that will be scheduled once you hit ``Enter``.
   In other words, if the task you want does not appear here, *it won't be scheduled*.

   C. Count information of the form ``x/y (z)``, where ``x`` is the number of tasks that match the
   current query, ``y`` is the total number of tasks and ``z`` is the number of tasks you have
   selected.

   D. The input bar for entering queries. As you type you'll notice the list of tasks in ``A``
   starts to update immediately. In the image above, the query ``'linux64 mochibrochr`` is entered.
   Correspondingly only tasks matching that query are displayed.

In general terms, you first find tasks on the left. Then you move them over to the right by
selecting them. Once you are satisfied with your selection, press ``Enter`` to push to try.


Selecting Tasks
---------------

There are few ways you can select tasks. If you are feeling a bit overwhelmed, it might be best to
stick with the mouse to start:

   1. Enter a query (e.g ``mochitest``) to reduce the task list a little.
   2. Scroll up and look for the task(s) you want.
   3. ``Right-Click`` as many tasks as desired to select them.
   4. Optionally delete your query, go back to step 1) and repeat.
   5. Press ``Enter`` to push (or ``Esc`` to cancel).

.. note::

   Dependencies are automatically filled in, so you can select a test task without needing
   to select the build it depends on.

As you ``Right-Click``, notice that a little arrow appears to the left of the task label. This
indicates that the task is selected and exists in the preview pane to the right.

Once you are a bit more comfortable with the interface, using the keyboard is much better at quickly
selecting tasks. Here are the main shortcuts you'll need:

.. code-block:: text

    Ctrl-K / Up    => Move cursor up
    Ctrl-J / Down  => Move cursor down
    Tab            => Select task + move cursor down
    Shift-Tab      => Select task + move cursor up
    Ctrl-A         => Select all currently filtered tasks
    Ctrl-T         => Toggle select all currently filtered tasks
    Ctrl-D         => De-select all selected tasks (both filtered and not)
    Alt-Bspace     => Clear query from input bar
    Enter          => Accept selection and exit
    Ctrl-C / Esc   => Cancel selection and exit
    ?              => Toggle preview pane


The process for selecting tasks is otherwise the same as for a mouse. A particularly fast and
powerful way to select tasks is to:

.. code-block:: text

    Write a precise query => Ctrl-A => Alt-Bspace => Repeat

As before, when you are satisfied with your selection press ``Enter`` and all the tasks in the
preview pane will be pushed to try. If you change your mind you can press ``Esc`` or ``Ctrl-C`` to
exit the interface without pushing anything.

.. note::

   Initially ``fzf`` will automatically select whichever task is under your cursor. This is a
   convenience feature for the case where you are only selecting a single task. This feature will be
   turned off as soon as you *lock in* a selection with ``Right-Click``, ``Tab`` or ``Ctrl-A``.


Writing Queries
---------------

Queries are built from a series of terms, each separated by a space. Terms are logically joined by
the AND operator. For example:

.. code-block:: text

    'windows 'mochitest

This query has two terms, and is the equivalent of saying: Give me all the tasks that match both the
term ``'windows'`` and the term ``'mochitest'``. In other words, this query matches all Windows
mochitest tasks.

The single quote prefix before each term tells ``fzf`` to use exact substring matches, so only tasks
that contain both the literal string ``windows`` AND the literal string ``mochitest`` will be
matched.

Another thing to note is that the order of the terms makes no difference, so ``'windows 'mochitest``
and ``'mochitest 'windows`` are equivalent.


Fuzzy terms
~~~~~~~~~~~

If a term is *not* prefixed with a single quote, that makes it a fuzzy term. This means the
characters in the term need to show up in order, but not in sequence. E.g the fuzzy term ``max``
would match the string ``mozilla firefox`` (as first there is an ``m``, then an ``a`` and finally an
``x``), but not the string ``firefox by mozilla`` (since the ``x`` is now out of order). Here's a
less contrived example:

.. code-block:: text

    wndws mchtst

Like the query above, this one would also select all Windows mochitest tasks. But it will
additionally select:

.. code-block:: text

    test-macosx1014-64-shippable/opt-talos-sessionrestore-many-windows-e10s

This is because both sequences of letters (``wndws`` and ``mchtst``) independently appear in order
somewhere in this string (remember the order of the terms makes no difference).

At first fuzzy terms may not seem very useful, but they are actually extremely powerful! Let's use
the term from the interface image above, ``'linux64 mochibrochr``, as an example. First, just notice
how in the image ``fzf`` highlights the characters that constitute the match in green. Next, notice
how typing ``mochibrochr`` can quickly get us all mochitest browser-chrome tasks. The power of fuzzy
terms is that you don't need to memorize the exact task labels you are looking for. Just start
typing something you think is vaguely correct and chances are you'll see the task you're looking for.


Term Modifiers
~~~~~~~~~~~~~~

The following modifiers can be applied to a search term:

.. code-block:: text

    'word    => exact match (line must contain the literal string "word")
    ^word    => exact prefix match (line must start with literal "word")
    word$    => exact suffix match (line must end with literal "word")
    !word    => exact negation match (line must not contain literal "word")
    'a | 'b  => OR operator (joins two exact match operators together)

For example:

.. code-block:: text

    ^start 'exact | 'other !ignore fuzzy end$

would match the string:

.. code-block:: text

    starting to bake isn't exactly fun, but pizza is yummy in the end

.. note::

    The best way to learn how to write queries is to run ``mach try fuzzy --no-push`` and play
    around with all of these modifiers!


Specifying Queries on the Command Line
--------------------------------------

Sometimes it's more convenient to skip the interactive interface and specify a query on the command
line with ``-q/--query``. This is equivalent to opening the interface then typing:
``<query><ctrl-a><enter>``.

For example:

.. code-block:: shell

    # selects all mochitest tasks
    $ mach try fuzzy --query "mochitest"

You can pass in multiple queries at once and the results of each will be joined together:

.. code-block:: shell

    # selects all mochitest and reftest tasks
    $ mach try fuzzy -q "mochitest" -q "reftest"

If instead you want the intersection of queries, you can pass in ``-x/--and``:

.. code-block:: shell

    # selects all windows mochitest tasks
    $ mach try fuzzy --and -q "mochitest" -q "windows"


Modifying Presets
~~~~~~~~~~~~~~~~~

:doc:`Presets <../presets>` make it easy to run a pre-determined set of tasks. But sometimes you
might not want to run that set exactly as is, you may only want to use the preset as a starting
point then add or remove tasks as needed. This can be accomplished with ``-q/--query`` or
``-i/--interactive``.

Here are some examples of adding tasks to a preset:

.. code-block:: shell

    # selects all perf tasks plus all mochitest-chrome tasks
    $ mach try fuzzy --preset perf -q "mochitest-chrome"

    # adds tasks to the perf preset interactively
    $ mach try fuzzy --preset perf -i

Similarly, ``-x/--and`` can be used to filter down a preset by taking the intersection of the two
sets:

.. code-block:: shell

    # limits perf tasks to windows only
    $ mach try fuzzy --preset perf -xq "windows"

    # limits perf tasks interactively
    $ mach try fuzzy --preset perf -xi


Shell Conflicts
~~~~~~~~~~~~~~~

Unfortunately ``fzf``'s query language uses some characters (namely ``'``, ``!`` and ``$``) that can
interfere with your shell when using ``-q/--query``. Below are some tips for how to type out a query
on the command line.

The ``!`` character is typically used for history expansion. If you don't use this feature, the
easiest way to specify queries on the command line is to disable it:

.. code-block:: shell

    # bash
    $ set +H
    $ ./mach try fuzzy -q "'foo !bar"

    # zsh
    $ setopt no_banghist
    $ ./mach try fuzzy -q "'foo !bar"

If using ``bash``, add ``set +H`` to your ``~/.bashrc``, ``~/.bash_profile`` or equivalent. If using
``zsh``, add ``setopt no_banghist`` to your ``~/.zshrc`` or equivalent.

If you don't want to disable history expansion, you can escape your queries like this:

.. code-block:: shell

    # bash
    $ ./mach try fuzzy -q $'\'foo !bar'

    # zsh
    $ ./mach try fuzzy -q "'foo \!bar"


The third option is to use ``-e/--exact`` which reverses the behaviour of the ``'`` character (see
:ref:`additional-arguments` for more details). Using this flag means you won't need to escape the
``'`` character as often and allows you to run your queries like this:

.. code-block:: shell

    # bash and zsh
    $ ./mach try fuzzy -eq 'foo !bar'

This method is only useful if you find you almost always prefix terms with ``'`` (and rarely use
fuzzy terms). Otherwise as soon as you want to use a fuzzy match you'll run into the same problem as
before.

.. note:: All the examples in these three approaches will select the same set of tasks.

If you use ``fish`` shell, you won't need to escape ``!``, however you will need to escape ``$``:

.. code-block:: shell

    # fish
    $ ./mach try fuzzy -q "'foo !bar baz\$"


Test Paths
----------

One or more paths to a file or directory may be specified as positional arguments. When
specifying paths, the list of available tasks to choose from is filtered down such that
only suites that have tests in a specified path can be selected. Notably, only the first
chunk of each suite/platform appears. When the tasks are scheduled, only tests that live
under one of the specified paths will be run.

.. note::

    When using paths, be aware that all tests under the specified paths will run in the
    same chunk. This might produce a different ordering from what gets run on production
    branches, and may yield different results.

    For suites that restart the browser between each manifest (like mochitest), this
    shouldn't be as big of a concern.

Paths can be used with the interactive ``fzf`` window, or using the ``-q/--query`` argument.
For example, running:

.. code-block:: shell

    $ mach try fuzzy layout/reftests/reftest-sanity -q "!pgo !cov !asan 'linux64"

Would produce the following ``try_task_config.json``:

.. code-block:: json

    {
      "env":{
        "MOZHARNESS_TEST_PATHS":"{\"reftest\":\"layout/reftests/reftest-sanity\"}"
      },
      "tasks":[
        "test-linux64-qr/debug-reftest-e10s-1",
        "test-linux64-qr/opt-reftest-e10s-1",
        "test-linux64/debug-reftest-e10s-1",
        "test-linux64/debug-reftest-no-accel-e10s-1",
        "test-linux64/opt-reftest-e10s-1",
        "test-linux64/opt-reftest-no-accel-e10s-1",
      ]
    }

Inside of these tasks, the reftest harness will only run tests that live under
``layout/reftests/reftest-sanity``.


.. _additional-arguments:

Additional Arguments
--------------------

There are a few additional command line arguments you may wish to use:

``-e/--exact``
By default, ``fzf`` treats terms as a fuzzy match and prefixing a term with ``'`` turns it into an exact
match. If passing in ``--exact``, this behaviour is reversed. Non-prefixed terms become exact, and a
``'`` prefix makes a term fuzzy.

``--full``
By default, only target tasks (e.g tasks that would normally run on mozilla-central)
are generated. Passing in ``--full`` allows you to select from all tasks. This is useful for
things like nightly or release tasks.

``-u/--update``
Update the bootstrapped ``fzf`` binary to the latest version.

For a full list of command line arguments, run:

.. code-block:: shell

    $ mach try fuzzy --help

For more information on using ``fzf``, run:

.. code-block:: shell

    $ man fzf

.. _fzf: https://github.com/junegunn/fzf