coveralls: 
[![Coverage Status](https://coveralls.io/builds/18799556/badge)](https://coveralls.io/builds/18799556)

Coverage increased (+0.0008%) to 99.744% when pulling **ce1be80ae54f53a780066da0592aa8f587cfdf22 on wmvanvliet:sorting** into **50f0c7eaa8084e3a54c88bfec02e477e419f4c12 on pydoit:master**.

schettino72: Oh. and it seems docs also need to be updated `cmd-other.rst`. Currently it has the wording:

```
Tasks are listed in alphabetical order, not by order of execution.
```

Instead it should mention both way are possible.
diff --git a/AUTHORS b/AUTHORS
index 89e6941..045960b 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -24,3 +24,4 @@
  * Simon Mutch - https://github.com/smutch
  * Michael Milton - https://github.com/tmiguelt
  * Mike Pagel - https://github.com/moltob
+ * Marijn van Vliet - https://github.com/wmvanvliet
diff --git a/CHANGES b/CHANGES
index da0f984..42ffcbd 100644
--- a/CHANGES
+++ b/CHANGES
@@ -16,6 +16,7 @@ Changes
  - Fix #113: `tools.config_changed` deals with nested dictionaries.
              Using json instead of repr.
  - Fix #261: help organize command options in sections, and improve formatting.
+ - Fix #267: `doit list` now has a `--sort` parameter to determine the order in which the tasks are listed.
 
 
 0.31.1 (*2018-03-18*)
diff --git a/doc/cmd_other.rst b/doc/cmd_other.rst
index ff8d069..b9a2a3f 100644
--- a/doc/cmd_other.rst
+++ b/doc/cmd_other.rst
@@ -34,7 +34,8 @@ list
 ------
 
 *list* is used to show all tasks available in a *dodo* file.
-Tasks are listed in alphabetical order, not by order of execution.
+Tasks are listed in alphabetical order by default, but *--sort=definition* can
+be speficied to sort them in the order in which they appear in the `dodo` file.
 
 .. code-block:: console
 
diff --git a/doit/cmd_list.py b/doit/cmd_list.py
index 3473231..4652152 100644
--- a/doit/cmd_list.py
+++ b/doit/cmd_list.py
@@ -55,6 +55,18 @@ opt_template = {
     'help': "display entries with template"
     }
 
+opt_sort = {
+    'name': 'sort',
+    'short': '',
+    'long': 'sort',
+    'type': str,
+    'choices': [('name', 'sort by task name'),
+                ('definition', 'list tasks in the order they were defined')],
+    'default': 'name',
+    'help': ("choose the manner in which the task list is sorted. "
+             "[default: %(default)s]")
+    }
+
 
 class List(DoitCmdBase):
     doc_purpose = "list tasks from dodo file"
@@ -62,7 +74,8 @@ class List(DoitCmdBase):
     doc_description = None
 
     cmd_options = (opt_listall, opt_list_quiet, opt_list_status,
-                   opt_list_private, opt_list_dependencies, opt_template)
+                   opt_list_private, opt_list_dependencies, opt_template,
+                   opt_sort)
 
 
     STATUS_MAP = {'ignore': 'I', 'up-to-date': 'U', 'run': 'R', 'error': 'E'}
@@ -113,10 +126,9 @@ class List(DoitCmdBase):
         return print_list
 
 
-    def _execute(self, subtasks=False, quiet=True, status=False,
-                 private=False, list_deps=False, template=None, pos_args=None):
-        """List task generators, in the order they were defined.
-        """
+    def _execute(self, subtasks=False, quiet=True, status=False, private=False,
+                 list_deps=False, template=None, sort='name', pos_args=None):
+        """List task generators"""
         filter_tasks = pos_args
         # dict of all tasks
         tasks = dict([(t.name, t) for t in self.task_list])
@@ -144,7 +156,13 @@ class List(DoitCmdBase):
                 template = '{status} ' + template
         template += '\n'
 
+        # sort list of tasks
+        if sort == 'name':
+            print_list = sorted(print_list)
+        elif sort == 'definition':
+            pass  # task list is already sorted in order of definition
+
         # print list of tasks
-        for task in sorted(print_list):
+        for task in print_list:
             self._print_task(template, task, status, list_deps, tasks)
         return 0

Use natural order of task names when listed
```bash
$ doit list
buildhtml  Build HTML documentation.
buildpdf   Build PDF documentation.
publish    Publish documentation to FTP.
spell	   Spell document source files.
```
Tasks are today listed in alphabetical order.

As seen, it can look quite confusing and user would appreciate natural order:

```bash
$ doit list
spell	   Spell document source files.
buildhtml  Build HTML documentation.
buildpdf   Build PDF documentation.
publish    Publish documentation to FTP.
```

I guess, changing order of listed items is not likely to break anything and I would prefer do it this way by default. Author has good control of order of tasks definitions in dodo file.

If alphabetical order would be (sometime) required, we could add a key "listorder" into `DOIT_CONFIG`.

I had similar issue with Click https://github.com/pallets/click/issues/513 (and I managed to resolve it).

diff --git a/tests/test_cmd_list.py b/tests/test_cmd_list.py
index 6b35eba..9df6942 100644
--- a/tests/test_cmd_list.py
+++ b/tests/test_cmd_list.py
@@ -163,3 +163,23 @@ class TestCmdList(object):
         cmd_list._execute()
         got = [line.strip() for line in output.getvalue().split('\n') if line]
         assert 't做' == got[0]
+
+    def testSortByName(self):
+        # by default, the task list should be ordered by name
+        task_list = list(tasks_sample())
+        output = StringIO()
+        cmd_list = CmdFactory(List, outstream=output, task_list=task_list)
+        cmd_list._execute()
+        got = [line.strip() for line in output.getvalue().split('\n') if line]
+        expected = ['g1', 't1', 't2', 't3']
+        assert expected == got
+
+    def testSortByDefinition(self):
+        # test sorting task list by order of definition
+        task_list = list(tasks_sample())
+        output = StringIO()
+        cmd_list = CmdFactory(List, outstream=output, task_list=task_list)
+        cmd_list._execute(sort='definition')
+        got = [line.strip() for line in output.getvalue().split('\n') if line]
+        expected = ['t1', 't2', 'g1', 't3']
+        assert expected == got

pip install -e .
parse_log_pytest
pytest
pytest pytest-ignore-flaky
apt-get update apt-get install -y gcc
3.7
pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
attrs @ file:///croot/attrs_1668696182826/work
certifi @ file:///croot/certifi_1671487769961/work/certifi
cloudpickle==2.2.1
-e git+https://github.com/pydoit/doit.git@50f0c7eaa8084e3a54c88bfec02e477e419f4c12#egg=doit
flit_core @ file:///opt/conda/conda-bld/flit-core_1644941570762/work/source/flit_core
importlib-metadata @ file:///tmp/build/80754af9/importlib-metadata_1648562407465/work
iniconfig @ file:///home/linux1/recipes/ci/iniconfig_1610983019677/work
packaging @ file:///croot/packaging_1671697413597/work
pluggy @ file:///tmp/build/80754af9/pluggy_1648042572264/work
py @ file:///opt/conda/conda-bld/py_1644396412707/work
pyinotify==0.9.6
pytest==7.1.2
pytest-ignore-flaky==2.1.0
tomli @ file:///opt/conda/conda-bld/tomli_1657175507142/work
typing_extensions @ file:///croot/typing_extensions_1669924550328/work
zipp @ file:///croot/zipp_1672387121353/work

name: doit
channels:
  - defaults
  - https://repo.anaconda.com/pkgs/main
  - https://repo.anaconda.com/pkgs/r
  - conda-forge
dependencies:
  - _libgcc_mutex=0.1=main
  - _openmp_mutex=5.1=1_gnu
  - attrs=22.1.0=py37h06a4308_0
  - ca-certificates=2025.2.25=h06a4308_0
  - certifi=2022.12.7=py37h06a4308_0
  - flit-core=3.6.0=pyhd3eb1b0_0
  - importlib-metadata=4.11.3=py37h06a4308_0
  - importlib_metadata=4.11.3=hd3eb1b0_0
  - iniconfig=1.1.1=pyhd3eb1b0_0
  - ld_impl_linux-64=2.40=h12ee557_0
  - libffi=3.4.4=h6a678d5_1
  - libgcc-ng=11.2.0=h1234567_1
  - libgomp=11.2.0=h1234567_1
  - libstdcxx-ng=11.2.0=h1234567_1
  - ncurses=6.4=h6a678d5_0
  - openssl=1.1.1w=h7f8727e_0
  - packaging=22.0=py37h06a4308_0
  - pip=22.3.1=py37h06a4308_0
  - pluggy=1.0.0=py37h06a4308_1
  - py=1.11.0=pyhd3eb1b0_0
  - pytest=7.1.2=py37h06a4308_0
  - python=3.7.16=h7a1cb2a_0
  - readline=8.2=h5eee18b_0
  - setuptools=65.6.3=py37h06a4308_0
  - sqlite=3.45.3=h5eee18b_0
  - tk=8.6.14=h39e8969_0
  - tomli=2.0.1=py37h06a4308_0
  - typing_extensions=4.4.0=py37h06a4308_0
  - wheel=0.38.4=py37h06a4308_0
  - xz=5.6.4=h5eee18b_1
  - zipp=3.11.0=py37h06a4308_0
  - zlib=1.2.13=h5eee18b_1
  - pip:
      - cloudpickle==2.2.1
      - pyinotify==0.9.6
      - pytest-ignore-flaky==2.1.0
prefix: /opt/conda/envs/doit

tests/test_cmd_list.py::TestCmdList::testSortByDefinition
tests/test_cmd_list.py::TestCmdList::testQuiet tests/test_cmd_list.py::TestCmdList::testDoc tests/test_cmd_list.py::TestCmdList::testCustomTemplate tests/test_cmd_list.py::TestCmdList::testDependencies tests/test_cmd_list.py::TestCmdList::testSubTask tests/test_cmd_list.py::TestCmdList::testFilter tests/test_cmd_list.py::TestCmdList::testFilterSubtask tests/test_cmd_list.py::TestCmdList::testFilterAll tests/test_cmd_list.py::TestCmdList::testStatus tests/test_cmd_list.py::TestCmdList::testErrorStatus tests/test_cmd_list.py::TestCmdList::testStatus_result_dep_bug_gh44 tests/test_cmd_list.py::TestCmdList::testNoPrivate tests/test_cmd_list.py::TestCmdList::testWithPrivate tests/test_cmd_list.py::TestCmdList::testListInvalidTask tests/test_cmd_list.py::TestCmdList::test_unicode_name tests/test_cmd_list.py::TestCmdList::testSortByName
doc/cmd_other.rst CHANGES doit/cmd_list.py AUTHORS
doc/cmd_other.rst CHANGES doit/cmd_list.py AUTHORS