summaryrefslogtreecommitdiffstats
path: root/docs
diff options
context:
space:
mode:
Diffstat (limited to 'docs')
-rw-r--r--docs/configuration.md432
-rw-r--r--docs/contrib_rules.md67
-rw-r--r--docs/contributing.md132
-rw-r--r--docs/demos/asciicinema.json3798
-rw-r--r--docs/demos/scenario.txt75
-rw-r--r--docs/extra.css4
-rw-r--r--docs/images/RuleViolation.pngbin0 -> 27806 bytes
-rw-r--r--docs/images/RuleViolations.grafflebin0 -> 3291 bytes
-rw-r--r--docs/index.md351
-rw-r--r--docs/rules.md243
-rw-r--r--docs/user_defined_rules.md312
11 files changed, 5414 insertions, 0 deletions
diff --git a/docs/configuration.md b/docs/configuration.md
new file mode 100644
index 0000000..641b361
--- /dev/null
+++ b/docs/configuration.md
@@ -0,0 +1,432 @@
+# Configuration
+Gitlint can be configured through different means.
+
+# Config files #
+You can modify gitlint's behavior by adding a ```.gitlint``` file to your git repository.
+
+Generate a default ```.gitlint``` config file by running:
+```bash
+gitlint generate-config
+```
+You can also use a different config file like so:
+
+```bash
+gitlint --config myconfigfile.ini
+```
+
+The block below shows a sample ```.gitlint``` file. Details about rule config options can be found on the
+[Rules](rules.md) page, details about the ```[general]``` section can be found in the
+[General Configuration](configuration.md#general-configuration) section of this page.
+
+```ini
+# Edit this file as you like.
+#
+# All these sections are optional. Each section with the exception of [general] represents
+# one rule and each key in it is an option for that specific rule.
+#
+# Rules and sections can be referenced by their full name or by id. For example
+# section "[body-max-line-length]" could be written as "[B1]". Full section names are
+# used in here for clarity.
+# Rule reference documentation: http://jorisroovers.github.io/gitlint/rules/
+#
+# Use 'gitlint generate-config' to generate a config file with all possible options
+[general]
+# Ignore certain rules (comma-separated list), you can reference them by their
+# id or by their full name
+ignore=title-trailing-punctuation, T3
+
+# verbosity should be a value between 1 and 3, the commandline -v flags take
+# precedence over this
+verbosity = 2
+
+# By default gitlint will ignore merge, revert, fixup and squash commits.
+ignore-merge-commits=true
+ignore-revert-commits=true
+ignore-fixup-commits=true
+ignore-squash-commits=true
+
+# Ignore any data send to gitlint via stdin
+ignore-stdin=true
+
+# Fetch additional meta-data from the local repository when manually passing a
+# commit message to gitlint via stdin or --commit-msg. Disabled by default.
+staged=true
+
+# Enable debug mode (prints more output). Disabled by default.
+debug=true
+
+# Enable community contributed rules
+# See http://jorisroovers.github.io/gitlint/contrib_rules for details
+contrib=contrib-title-conventional-commits,CC1
+
+# Set the extra-path where gitlint will search for user defined rules
+# See http://jorisroovers.github.io/gitlint/user_defined_rules for details
+extra-path=examples/
+
+# This is an example of how to configure the "title-max-length" rule and
+# set the line-length it enforces to 80
+[title-max-length]
+line-length=80
+
+[title-must-not-contain-word]
+# Comma-separated list of words that should not occur in the title. Matching is case
+# insensitive. It's fine if the keyword occurs as part of a larger word (so "WIPING"
+# will not cause a violation, but "WIP: my title" will.
+words=wip
+
+[title-match-regex]
+# python like regex (https://docs.python.org/2/library/re.html) that the
+# commit-msg title must be matched to.
+# Note that the regex can contradict with other rules if not used correctly
+# (e.g. title-must-not-contain-word).
+regex=^US[0-9]*
+
+[body-max-line-length]
+line-length=120
+
+[body-min-length]
+min-length=5
+
+[body-is-missing]
+# Whether to ignore this rule on merge commits (which typically only have a title)
+# default = True
+ignore-merge-commits=false
+
+[body-changed-file-mention]
+# List of files that need to be explicitly mentioned in the body when they are changed
+# This is useful for when developers often erroneously edit certain files or git submodules.
+# By specifying this rule, developers can only change the file when they explicitly reference
+# it in the commit message.
+files=gitlint/rules.py,README.md
+
+[author-valid-email]
+# python like regex (https://docs.python.org/2/library/re.html) that the
+# commit author email address should be matched to
+# For example, use the following regex if you only want to allow email addresses from foo.com
+regex=[^@]+@foo.com
+
+[ignore-by-title]
+# Ignore certain rules for commits of which the title matches a regex
+# E.g. Match commit titles that start with "Release"
+regex=^Release(.*)
+
+# Ignore certain rules, you can reference them by their id or by their full name
+# Use 'all' to ignore all rules
+ignore=T1,body-min-length
+
+[ignore-by-body]
+# Ignore certain rules for commits of which the body has a line that matches a regex
+# E.g. Match bodies that have a line that that contain "release"
+# regex=(.*)release(.*)
+#
+# Ignore certain rules, you can reference them by their id or by their full name
+# Use 'all' to ignore all rules
+ignore=T1,body-min-length
+
+# This is a contrib rule - a community contributed rule. These are disabled by default.
+# You need to explicitly enable them one-by-one by adding them to the "contrib" option
+# under [general] section above.
+[contrib-title-conventional-commits]
+# Specify allowed commit types. For details see: https://www.conventionalcommits.org/
+types = bugfix,user-story,epic
+```
+
+# Commandline config #
+
+You can also use one or more ```-c``` flags like so:
+
+```
+$ gitlint -c general.verbosity=2 -c title-max-length.line-length=80 -c B1.line-length=100
+```
+The generic config flag format is ```-c <rule>.<option>=<value>``` and supports all the same rules and options which
+you can also use in a ```.gitlint``` config file.
+
+# Commit specific config #
+
+You can also configure gitlint by adding specific lines to your commit message.
+For now, we only support ignoring commits by adding ```gitlint-ignore: all``` to the commit
+message like so:
+
+```
+WIP: This is my commit message
+
+I want gitlint to ignore this entire commit message.
+gitlint-ignore: all
+```
+
+```gitlint-ignore: all``` can occur on any line, as long as it is at the start of the line.
+
+You can also specify specific rules to be ignored as follows:
+```
+WIP: This is my commit message
+
+I want gitlint to ignore this entire commit message.
+gitlint-ignore: T1, body-hard-tab
+```
+
+
+
+# Configuration precedence #
+gitlint configuration is applied in the following order of precedence:
+
+1. Commit specific config (e.g.: ```gitlint-ignore: all``` in the commit message)
+2. Configuration Rules (e.g.: [ignore-by-title](/rules/#i1-ignore-by-title))
+3. Commandline convenience flags (e.g.: ```-vv```, ```--silent```, ```--ignore```)
+4. Commandline configuration flags (e.g.: ```-c title-max-length=123```)
+5. Configuration file (local ```.gitlint``` file, or file specified using ```-C```/```--config```)
+6. Default gitlint config
+
+# General Options
+Below we outline all configuration options that modify gitlint's overall behavior. These options can be specified
+using commandline flags or in ```[general]``` section in a ```.gitlint``` configuration file.
+
+## silent
+
+Enable silent mode (no output). Use [exit](index.md#exit-codes) code to determine result.
+
+Default value | gitlint version | commandline flag
+---------------|------------------|-------------------
+ false | >= 0.1.0 | ```--silent```
+
+### Examples
+```sh
+# CLI
+gitlint --silent
+```
+
+## verbosity
+
+Amount of output gitlint will show when printing errors.
+
+Default value | gitlint version | commandline flag
+---------------|------------------|-------------------
+ 3 | >= 0.1.0 | `-v`
+
+
+### Examples
+```sh
+# CLI
+gitlint -vvv # default (level 3)
+gitlint -vv # less output (level 2)
+gitlint -v # even less (level 1)
+gitlint --silent # no output (level 0)
+gitlint -c general.verbosity=1 # Set specific level
+gitlint -c general.verbosity=0 # Same as --silent
+```
+```ini
+.gitlint
+[general]
+verbosity=2
+```
+
+## ignore-merge-commits
+
+Whether or not to ignore merge commits.
+
+Default value | gitlint version | commandline flag
+---------------|------------------|-------------------
+ true | >= 0.7.0 | Not Available
+
+### Examples
+```sh
+# CLI
+gitlint -c general.ignore-merge-commits=false
+```
+```ini
+#.gitlint
+[general]
+ignore-merge-commits=false
+```
+
+## ignore-revert-commits
+
+Whether or not to ignore revert commits.
+
+Default value | gitlint version | commandline flag
+---------------|------------------|-------------------
+ true | >= 0.13.0 | Not Available
+
+### Examples
+```sh
+# CLI
+gitlint -c general.ignore-revert-commits=false
+```
+```ini
+#.gitlint
+[general]
+ignore-revert-commits=false
+```
+
+## ignore-fixup-commits
+
+Whether or not to ignore [fixup](https://git-scm.com/docs/git-commit#git-commit---fixupltcommitgt) commits.
+
+Default value | gitlint version | commandline flag
+---------------|------------------|-------------------
+ true | >= 0.9.0 | Not Available
+
+### Examples
+```sh
+# CLI
+gitlint -c general.ignore-fixup-commits=false
+```
+```ini
+#.gitlint
+[general]
+ignore-fixup-commits=false
+```
+
+## ignore-squash-commits
+
+Whether or not to ignore [squash](https://git-scm.com/docs/git-commit#git-commit---squashltcommitgt) commits.
+
+Default value | gitlint version | commandline flag
+---------------|------------------|-------------------
+ true | >= 0.9.0 | Not Available
+
+### Examples
+```sh
+# CLI
+gitlint -c general.ignore-squash-commits=false
+```
+```ini
+#.gitlint
+[general]
+ignore-squash-commits=false
+```
+
+## ignore
+
+Comma separated list of rules to ignore (by name or id).
+
+Default value | gitlint version | commandline flag
+---------------------------|------------------|-------------------
+ [] (=empty list) | >= 0.1.0 | `--ignore`
+
+### Examples
+```sh
+# CLI
+gitlint --ignore=body-min-length # ignore single rule
+gitlint --ignore=T1,body-min-length # ignore multiple rule
+gitlint -c general.ignore=T1,body-min-length # different way of doing the same
+```
+```ini
+#.gitlint
+[general]
+ignore=T1,body-min-length
+```
+
+## debug
+
+Enable debugging output.
+
+Default value | gitlint version | commandline flag
+---------------|------------------|-------------------
+ false | >= 0.7.1 | `--debug`
+
+### Examples
+```sh
+# CLI
+gitlint --debug
+# --debug is special, the following does NOT work
+# gitlint -c general.debug=true
+```
+
+## target
+
+Target git repository gitlint should be linting against.
+
+Default value | gitlint version | commandline flag
+---------------------------|------------------|-------------------
+ (empty) | >= 0.8.0 | `--target`
+
+### Examples
+```sh
+# CLI
+gitlint --target=/home/joe/myrepo/
+gitlint -c general.target=/home/joe/myrepo/ # different way of doing the same
+```
+```ini
+#.gitlint
+[general]
+target=/home/joe/myrepo/
+```
+
+## extra-path
+
+Path where gitlint looks for [user-defined rules](user_defined_rules.md).
+
+Default value | gitlint version | commandline flag
+---------------------------|------------------|-------------------
+ (empty) | >= 0.8.0 | `--extra-path`
+
+### Examples
+```sh
+# CLI
+gitlint --extra-path=/home/joe/rules/
+gitlint -c general.extra-path=/home/joe/rules/ # different way of doing the same
+```
+```ini
+#.gitlint
+[general]
+extra-path=/home/joe/rules/
+```
+
+## contrib
+
+[Contrib rules](contrib_rules) to enable.
+
+Default value | gitlint version | commandline flag
+---------------------------|------------------|-------------------
+ (empty) | >= 0.12.0 | `--contrib`
+
+### Examples
+```sh
+# CLI
+gitlint --contrib=contrib-title-conventional-commits,CC1
+gitlint -c general.contrib=contrib-title-conventional-commits,CC1 # different way of doing the same
+```
+```ini
+#.gitlint
+[general]
+contrib=contrib-title-conventional-commits,CC1
+```
+## ignore-stdin
+
+Ignore any stdin data. Sometimes useful when running gitlint in a CI server.
+
+Default value | gitlint version | commandline flag
+---------------|------------------|-------------------
+ false | >= 0.12.0 | `--ignore-stdin`
+
+### Examples
+```sh
+# CLI
+gitlint --ignore-stdin
+gitlint -c general.ignore-stdin=true # different way of doing the same
+```
+```ini
+#.gitlint
+[general]
+ignore-stdin=true
+```
+
+## staged
+
+Fetch additional meta-data from the local `repository when manually passing a commit message to gitlint via stdin or ```--commit-msg```.
+
+Default value | gitlint version | commandline flag
+---------------|------------------|-------------------
+ false | >= 0.13.0 | `--staged`
+
+### Examples
+```sh
+# CLI
+gitlint --staged
+gitlint -c general.staged=true # different way of doing the same
+```
+```ini
+#.gitlint
+[general]
+staged=true
+``` \ No newline at end of file
diff --git a/docs/contrib_rules.md b/docs/contrib_rules.md
new file mode 100644
index 0000000..a4f4f0d
--- /dev/null
+++ b/docs/contrib_rules.md
@@ -0,0 +1,67 @@
+# Using Contrib Rules
+_Introduced in gitlint v0.12.0_
+
+Contrib rules are community-**contrib**uted rules that are disabled by default, but can be enabled through configuration.
+
+Contrib rules are meant to augment default gitlint behavior by providing users with rules for common use-cases without
+forcing these rules on all gitlint users. This also means that users don't have to
+re-implement these commonly used rules themselves as [user-defined](user_defined_rules) rules.
+
+To enable certain contrib rules, you can use the ```--contrib``` flag.
+```sh
+$ cat examples/commit-message-1 | gitlint --contrib contrib-title-conventional-commits,CC1
+1: CC1 Body does not contain a 'Signed-Off-By' line
+1: CL1 Title does not start with one of fix, feat, chore, docs, style, refactor, perf, test: "WIP: This is the title of a commit message."
+
+# These are the default violations
+1: T3 Title has trailing punctuation (.): "WIP: This is the title of a commit message."
+1: T5 Title contains the word 'WIP' (case-insensitive): "WIP: This is the title of a commit message."
+2: B4 Second line is not empty: "The second line should typically be empty"
+3: B1 Line exceeds max length (123>80): "Lines typically need to have a max length, meaning that they can't exceed a preset number of characters, usually 80 or 120."
+```
+
+Same thing using a ```.gitlint``` file:
+
+```ini
+[general]
+# You HAVE to add the rule here to enable it, only configuring (such as below)
+# does NOT enable it.
+contrib=contrib-title-conventional-commits,CC1
+
+
+[contrib-title-conventional-commits]
+# Specify allowed commit types. For details see: https://www.conventionalcommits.org/
+types = bugfix,user-story,epic
+```
+
+You can also configure contrib rules using [any of the other ways to configure gitlint](configuration.md).
+
+# Available Contrib Rules
+
+ID | Name | gitlint version | Description
+------|-------------------------------------|------------------ |-------------------------------------------
+CT1 | contrib-title-conventional-commits | >= 0.12.0 | Enforces [Conventional Commits](https://www.conventionalcommits.org/) commit message style on the title.
+CC1 | contrib-requires-signed-off-by | >= 0.12.0 | Commit body must contain a `Signed-Off-By` line.
+
+## CT1: contrib-title-conventional-commits ##
+
+ID | Name | gitlint version | Description
+------|---------------------------------------|--------------------|-------------------------------------------
+CT1 | contrib-title-conventional-commits | >= 0.12.0 | Enforces [Conventional Commits](https://www.conventionalcommits.org/) commit message style on the title.
+
+### Options ###
+
+Name | gitlint version | Default | Description
+---------------|--------------------|--------------|----------------------------------
+types | >= 0.12.0 | `fix,feat,chore,docs,style,refactor,perf,test,revert` | Comma separated list of allowed commit types.
+
+
+## CC1: contrib-requires-signed-off-by ##
+
+ID | Name | gitlint version | Description
+------|---------------------------------------|--------------------|-------------------------------------------
+CC1 | contrib-requires-signed-off-by | >= 0.12.0 | Commit body must contain a `Signed-Off-By` line. This means, a line that starts with the `Signed-Off-By` keyword.
+
+
+# Contributing Contrib rules
+We'd love for you to contribute new Contrib rules to gitlint or improve existing ones! Please visit the [Contributing](contributing) page on how to get started. \ No newline at end of file
diff --git a/docs/contributing.md b/docs/contributing.md
new file mode 100644
index 0000000..0cd6eaf
--- /dev/null
+++ b/docs/contributing.md
@@ -0,0 +1,132 @@
+# Contributing
+
+We'd love for you to contribute to gitlint. Thanks for your interest!
+The [source-code and issue tracker](https://github.com/jorisroovers/gitlint) are hosted on Github.
+
+Often it takes a while for us (well, actually just [me](https://github.com/jorisroovers)) to get back to you
+(sometimes up to a few months, this is a hobby project), but rest assured that we read your message and appreciate
+your interest!
+We maintain a [loose roadmap on our wiki](https://github.com/jorisroovers/gitlint/wiki/Roadmap), but
+that's open to a lot of change and input.
+
+# Guidelines
+
+When contributing code, please consider all the parts that are typically required:
+
+- [Unit tests](https://github.com/jorisroovers/gitlint/tree/master/gitlint/tests) (automatically
+ [enforced by CI](https://github.com/jorisroovers/gitlint/actions)). Please consider writing
+ new ones for your functionality, not only updating existing ones to make the build pass.
+- [Integration tests](https://github.com/jorisroovers/gitlint/tree/master/qa) (also automatically
+ [enforced by CI](https://github.com/jorisroovers/gitlint/actions)). Again, please consider writing new ones
+ for your functionality, not only updating existing ones to make the build pass.
+- [Documentation](https://github.com/jorisroovers/gitlint/tree/master/docs)
+
+Since we want to maintain a high standard of quality, all of these things will have to be done regardless before code
+can make it as part of a release. If you can already include them as part of your PR, it's a huge timesaver for us
+and it's likely that your PR will be merged and released a lot sooner. Thanks!
+
+# Development #
+
+There is a Vagrantfile in this repository that can be used for development.
+```bash
+vagrant up
+vagrant ssh
+```
+
+Or you can choose to use your local environment:
+
+```bash
+virtualenv .venv
+pip install -r requirements.txt -r test-requirements.txt -r doc-requirements.txt
+python setup.py develop
+```
+
+To run tests:
+```bash
+./run_tests.sh # run unit tests and print test coverage
+./run_test.sh gitlint/tests/test_body_rules.py::BodyRuleTests::test_body_missing # run a single test
+./run_tests.sh --no-coverage # run unit tests without test coverage
+./run_tests.sh --collect-only --no-coverage # Only collect, don't run unit tests
+./run_tests.sh --integration # Run integration tests (requires that you have gitlint installed)
+./run_tests.sh --build # Run build tests (=build python package)
+./run_tests.sh --pep8 # pep8 checks
+./run_tests.sh --stats # print some code stats
+./run_tests.sh --git # inception: run gitlint against itself
+./run_tests.sh --lint # run pylint checks
+./run_tests.sh --all # Run unit, integration, pep8 and gitlint checks
+
+
+```
+
+The ```Vagrantfile``` comes with ```virtualenv```s for python 2.7, 3.5, 3.6, 3.7 and pypy2.
+You can easily run tests against specific python environments by using the following commands *inside* of the Vagrant VM:
+```
+./run_tests.sh --envs 27 # Run the unit tests against Python 2.7
+./run_tests.sh --envs 27,35,pypy2 # Run the unit tests against Python 2.7, Python 3.5 and Pypy2
+./run_tests.sh --envs 27,35 --pep8 # Run pep8 checks against Python 2.7 and Python 3.5 (also works for ```--git```, ```--integration```, ```--pep8```, ```--stats``` and ```--lint```).
+./run_tests.sh --envs all --all # Run all tests against all environments
+./run_tests.sh --all-env --all # Idem: Run all tests against all environments
+```
+
+!!! important
+ Gitlint commits and pull requests are gated on all of our tests and checks.
+
+# Packaging #
+
+To see the package description in HTML format
+```
+pip install docutils
+export LC_ALL=en_US.UTF-8
+export LANG=en_US.UTF-8
+python setup.py --long-description | rst2html.py > output.html
+```
+
+# Documentation #
+We use [mkdocs](https://www.mkdocs.org/) for generating our documentation from markdown.
+
+To use it, do the following outside of the vagrant box (on your host machine):
+```bash
+pip install -r doc-requirements.txt # install doc requirements
+mkdocs serve
+```
+
+Then access the documentation website on your host machine on [http://localhost:8000]().
+
+# Tools #
+We keep a small set of scripts in the ```tools/``` directory:
+
+```sh
+tools/create-test-repo.sh # Create a test git repo in your /tmp directory
+tools/windows/create-test-repo.bat # Windows: create git test repo
+tools/windows/run_tests.bat # Windows run unit tests
+```
+
+# Contrib rules
+Since gitlint 0.12.0, we support [Contrib rules](../contrib_rules): community contributed rules that are part of gitlint
+itself. Thanks for considering to add a new one to gitlint!
+
+Before starting, please read all the other documentation on this page about contributing first.
+Then, we suggest taking the following approach to add a Contrib rule:
+
+1. **Write your rule as a [user-defined rule](../user_defined_rules)**. In terms of code, Contrib rules are identical to
+ user-defined rules, they just happen to have their code sit within the gitlint codebase itself.
+2. **Add your user-defined rule to gitlint**. You should put your file(s) in the [gitlint/contrib/rules](https://github.com/jorisroovers/gitlint/tree/master/gitlint/contrib/rules) directory.
+3. **Write unit tests**. The gitlint codebase contains [Contrib rule test files you can copy and modify](https://github.com/jorisroovers/gitlint/tree/master/gitlint/tests/contrib).
+4. **Write documentation**. In particular, you should update the [gitlint/docs/contrib_rules.md](https://github.com/jorisroovers/gitlint/blob/master/docs/contrib_rules.md) file with details on your Contrib rule.
+5. **Create a Pull Request**: code review typically requires a bit of back and forth. Thanks for your contribution!
+
+
+## Contrib rule requirements
+If you follow the steps above and follow the existing gitlint conventions wrt naming things, you should already be fairly close to done.
+
+In case you're looking for a slightly more formal spec, here's what gitlint requires of Contrib rules.
+
+- Since Contrib rules are really just user-defined rules that live within the gitlint code-base, all the [user-rule requirements](../user_defined_rules/#rule-requirements) also apply to Contrib rules.
+- All contrib rules **must** have associated unit tests. We *sort of* enforce this by a unit test that verifies that there's a
+ test file for each contrib file.
+- All contrib rules **must** have names that start with `contrib-`. This is to easily distinguish them from default gitlint rules.
+- All contrib rule ids **must** start with `CT` (for LineRules targeting the title), `CB` (for LineRules targeting the body) or `CC` (for CommitRules). Again, this is to easily distinguish them from default gitlint rules.
+- All contrib rules **must** have unique names and ids.
+- You **can** add multiple rule classes to the same file, but classes **should** be logically grouped together in a single file that implements related rules.
+- Contrib rules **should** be meaningfully different from one another. If a behavior change or tweak can be added to an existing rule by adding options, that should be considered first. However, large [god classes](https://en.wikipedia.org/wiki/God_object) that implement multiple rules in a single class should obviously also be avoided.
+- Contrib rules **should** use [options](../user_defined_rules/#options) to make rules configurable.
diff --git a/docs/demos/asciicinema.json b/docs/demos/asciicinema.json
new file mode 100644
index 0000000..b499765
--- /dev/null
+++ b/docs/demos/asciicinema.json
@@ -0,0 +1,3798 @@
+{
+ "version": 1,
+ "width": 102,
+ "height": 28,
+ "duration": 161.307896,
+ "command": "/bin/bash",
+ "title": "",
+ "env": {
+ "TERM": "xterm-256color",
+ "SHELL": "/bin/bash"
+ },
+ "stdout": [
+ [
+ 0.007348,
+ "\u001b[?1034h"
+ ],
+ [
+ 0.000015,
+ "bash-3.2$ "
+ ],
+ [
+ 0.504301,
+ "#"
+ ],
+ [
+ 0.139436,
+ " "
+ ],
+ [
+ 0.324556,
+ "I"
+ ],
+ [
+ 0.088019,
+ "n"
+ ],
+ [
+ 0.104007,
+ "s"
+ ],
+ [
+ 0.079986,
+ "t"
+ ],
+ [
+ 0.056291,
+ "a"
+ ],
+ [
+ 0.063684,
+ "l"
+ ],
+ [
+ 0.136015,
+ "l"
+ ],
+ [
+ 0.047705,
+ " "
+ ],
+ [
+ 0.144308,
+ "g"
+ ],
+ [
+ 0.087760,
+ "i"
+ ],
+ [
+ 0.088234,
+ "t"
+ ],
+ [
+ 0.119918,
+ "l"
+ ],
+ [
+ 0.031966,
+ "i"
+ ],
+ [
+ 0.056016,
+ "n"
+ ],
+ [
+ 0.104074,
+ "t"
+ ],
+ [
+ 0.151839,
+ "\r\n"
+ ],
+ [
+ 0.000117,
+ "bash-3.2$ "
+ ],
+ [
+ 0.247690,
+ "p"
+ ],
+ [
+ 0.064297,
+ "i"
+ ],
+ [
+ 0.119980,
+ "p"
+ ],
+ [
+ 0.112350,
+ " "
+ ],
+ [
+ 0.119395,
+ "i"
+ ],
+ [
+ 0.055802,
+ "n"
+ ],
+ [
+ 0.064480,
+ "s"
+ ],
+ [
+ 0.048012,
+ "t"
+ ],
+ [
+ 0.039930,
+ "a"
+ ],
+ [
+ 0.071932,
+ "l"
+ ],
+ [
+ 0.152065,
+ "l"
+ ],
+ [
+ 0.432253,
+ " "
+ ],
+ [
+ 0.143697,
+ "g"
+ ],
+ [
+ 0.056276,
+ "i"
+ ],
+ [
+ 0.127369,
+ "t"
+ ],
+ [
+ 0.104317,
+ "l"
+ ],
+ [
+ 0.039881,
+ "i"
+ ],
+ [
+ 0.072170,
+ "n"
+ ],
+ [
+ 0.119946,
+ "t"
+ ],
+ [
+ 0.168100,
+ "\r\n"
+ ],
+ [
+ 0.179873,
+ "Collecting gitlint\r\n"
+ ],
+ [
+ 0.031411,
+ " Using cached gitlint-0.6.1-py2.py3-none-any.whl\r\n"
+ ],
+ [
+ 0.011427,
+ "Requirement already satisfied (use --upgrade to upgrade): sh==1.11 in ./repos/demo-env/lib/python2.7/site-packages (from gitlint)\r\n"
+ ],
+ [
+ 0.000262,
+ "Requirement already satisfied (use --upgrade to upgrade): Click==5.1 in ./repos/demo-env/lib/python2.7/site-packages (from gitlint)\r\n"
+ ],
+ [
+ 0.000334,
+ "Installing collected packages: gitlint\r\n"
+ ],
+ [
+ 0.047796,
+ "Successfully installed gitlint-0.6.1\r\n"
+ ],
+ [
+ 0.022382,
+ "bash-3.2$ "
+ ],
+ [
+ 0.762766,
+ "#"
+ ],
+ [
+ 0.151744,
+ " "
+ ],
+ [
+ 0.431785,
+ "G"
+ ],
+ [
+ 0.095891,
+ "o"
+ ],
+ [
+ 0.192284,
+ " "
+ ],
+ [
+ 0.184164,
+ "t"
+ ],
+ [
+ 0.039770,
+ "o"
+ ],
+ [
+ 0.127949,
+ " "
+ ],
+ [
+ 0.232071,
+ "y"
+ ],
+ [
+ 0.071710,
+ "o"
+ ],
+ [
+ 0.023881,
+ "u"
+ ],
+ [
+ 0.184228,
+ "r"
+ ],
+ [
+ 0.144517,
+ " "
+ ],
+ [
+ 0.159631,
+ "g"
+ ],
+ [
+ 0.087950,
+ "i"
+ ],
+ [
+ 0.087976,
+ "t"
+ ],
+ [
+ 0.136095,
+ " "
+ ],
+ [
+ 0.183896,
+ "r"
+ ],
+ [
+ 0.047895,
+ "e"
+ ],
+ [
+ 0.072082,
+ "p"
+ ],
+ [
+ 0.072384,
+ "o"
+ ],
+ [
+ 0.359651,
+ "\r\n"
+ ],
+ [
+ 0.000096,
+ "bash-3.2$ "
+ ],
+ [
+ 0.463951,
+ "c"
+ ],
+ [
+ 0.463994,
+ "d"
+ ],
+ [
+ 0.079579,
+ " "
+ ],
+ [
+ 0.192355,
+ "m"
+ ],
+ [
+ 0.183732,
+ "\u0007"
+ ],
+ [
+ 0.496586,
+ "y"
+ ],
+ [
+ 0.175813,
+ "-git-repo/"
+ ],
+ [
+ 0.455841,
+ "\r\n"
+ ],
+ [
+ 0.000186,
+ "bash-3.2$ "
+ ],
+ [
+ 1.791755,
+ "#"
+ ],
+ [
+ 0.255933,
+ " "
+ ],
+ [
+ 0.296001,
+ "R"
+ ],
+ [
+ 0.159913,
+ "u"
+ ],
+ [
+ 0.064074,
+ "n"
+ ],
+ [
+ 0.175969,
+ " "
+ ],
+ [
+ 0.352173,
+ "g"
+ ],
+ [
+ 0.079863,
+ "i"
+ ],
+ [
+ 0.095948,
+ "t"
+ ],
+ [
+ 0.111985,
+ "l"
+ ],
+ [
+ 0.040922,
+ "i"
+ ],
+ [
+ 0.055153,
+ "n"
+ ],
+ [
+ 0.095944,
+ "t"
+ ],
+ [
+ 0.096118,
+ " "
+ ],
+ [
+ 0.095832,
+ "t"
+ ],
+ [
+ 0.024113,
+ "o"
+ ],
+ [
+ 0.144015,
+ " "
+ ],
+ [
+ 0.455972,
+ "c"
+ ],
+ [
+ 0.120097,
+ "h"
+ ],
+ [
+ 0.000354,
+ "e"
+ ],
+ [
+ 0.103450,
+ "c"
+ ],
+ [
+ 0.104258,
+ "k"
+ ],
+ [
+ 0.127354,
+ " "
+ ],
+ [
+ 0.536192,
+ "y"
+ ],
+ [
+ 0.088300,
+ "o"
+ ],
+ [
+ 0.055953,
+ "u"
+ ],
+ [
+ 0.111366,
+ "r"
+ ],
+ [
+ 0.136559,
+ " "
+ ],
+ [
+ 0.207924,
+ "l"
+ ],
+ [
+ 0.056410,
+ "a"
+ ],
+ [
+ 0.095988,
+ "s"
+ ],
+ [
+ 0.087665,
+ "t"
+ ],
+ [
+ 0.112209,
+ " "
+ ],
+ [
+ 0.215799,
+ "c"
+ ],
+ [
+ 0.015909,
+ "o"
+ ],
+ [
+ 0.159743,
+ "m"
+ ],
+ [
+ 0.200550,
+ "m"
+ ],
+ [
+ 0.135722,
+ "i"
+ ],
+ [
+ 0.120069,
+ "t"
+ ],
+ [
+ 0.087796,
+ " "
+ ],
+ [
+ 0.152194,
+ "m"
+ ],
+ [
+ 0.096258,
+ "e"
+ ],
+ [
+ 0.200052,
+ "s"
+ ],
+ [
+ 0.167944,
+ "s"
+ ],
+ [
+ 0.079747,
+ "a"
+ ],
+ [
+ 0.079582,
+ "g"
+ ],
+ [
+ 0.120304,
+ "e"
+ ],
+ [
+ 0.039891,
+ " "
+ ],
+ [
+ 0.208356,
+ "f"
+ ],
+ [
+ 0.071741,
+ "o"
+ ],
+ [
+ 0.080006,
+ "r"
+ ],
+ [
+ 0.119789,
+ " "
+ ],
+ [
+ 0.144509,
+ "s"
+ ],
+ [
+ 0.128456,
+ "t"
+ ],
+ [
+ 0.103452,
+ "y"
+ ],
+ [
+ 0.104515,
+ "l"
+ ],
+ [
+ 0.143681,
+ "e"
+ ],
+ [
+ 0.368030,
+ "\r\n"
+ ],
+ [
+ 0.000109,
+ "bash-3.2$ "
+ ],
+ [
+ 0.463969,
+ "g"
+ ],
+ [
+ 0.080036,
+ "i"
+ ],
+ [
+ 0.143920,
+ "t"
+ ],
+ [
+ 0.120008,
+ "l"
+ ],
+ [
+ 0.040025,
+ "i"
+ ],
+ [
+ 0.072262,
+ "n"
+ ],
+ [
+ 0.087179,
+ "t"
+ ],
+ [
+ 0.560443,
+ "\r\n"
+ ],
+ [
+ 0.123301,
+ "1: T3 Title has trailing punctuation (.): \"WIP: This is a commit message title.\"\r\n1: T5 Title contains the word 'WIP' (case-insensitive): \"WIP: This is a commit message title.\"\r\n"
+ ],
+ [
+ 0.000027,
+ "2: B4 Second line is not empty: \"Second line not empty\"\r\n3: B1 Line exceeds max length (97\u003e80): \"This body line exceeds the defacto standard length of 80 characters per line in a commit message.\"\r\n"
+ ],
+ [
+ 0.005792,
+ "bash-3.2$ "
+ ],
+ [
+ 2.814656,
+ "#"
+ ],
+ [
+ 0.376209,
+ " "
+ ],
+ [
+ 0.167631,
+ "F"
+ ],
+ [
+ 0.104242,
+ "o"
+ ],
+ [
+ 0.112316,
+ "r"
+ ],
+ [
+ 0.103655,
+ " "
+ ],
+ [
+ 0.112300,
+ "r"
+ ],
+ [
+ 0.079789,
+ "e"
+ ],
+ [
+ 0.111886,
+ "f"
+ ],
+ [
+ 0.096013,
+ "e"
+ ],
+ [
+ 0.080098,
+ "r"
+ ],
+ [
+ 0.087892,
+ "e"
+ ],
+ [
+ 0.064119,
+ "n"
+ ],
+ [
+ 0.192204,
+ "c"
+ ],
+ [
+ 0.112131,
+ "e"
+ ],
+ [
+ 0.375630,
+ ","
+ ],
+ [
+ 0.056176,
+ " "
+ ],
+ [
+ 0.239821,
+ "h"
+ ],
+ [
+ 0.047836,
+ "e"
+ ],
+ [
+ 0.080354,
+ "r"
+ ],
+ [
+ 0.080001,
+ "e"
+ ],
+ [
+ 0.095738,
+ "'"
+ ],
+ [
+ 0.216132,
+ "s"
+ ],
+ [
+ 0.071779,
+ " "
+ ],
+ [
+ 0.128086,
+ "t"
+ ],
+ [
+ 0.104034,
+ "h"
+ ],
+ [
+ 0.055946,
+ "a"
+ ],
+ [
+ 0.072018,
+ "t"
+ ],
+ [
+ 0.128240,
+ " "
+ ],
+ [
+ 0.239827,
+ "l"
+ ],
+ [
+ 0.080168,
+ "a"
+ ],
+ [
+ 0.055749,
+ "s"
+ ],
+ [
+ 0.103959,
+ "t"
+ ],
+ [
+ 0.080368,
+ " "
+ ],
+ [
+ 0.168008,
+ "c"
+ ],
+ [
+ 0.047675,
+ "o"
+ ],
+ [
+ 0.199913,
+ "m"
+ ],
+ [
+ 0.168041,
+ "m"
+ ],
+ [
+ 0.184377,
+ "i"
+ ],
+ [
+ 0.111843,
+ "t"
+ ],
+ [
+ 0.104075,
+ " "
+ ],
+ [
+ 0.119731,
+ "m"
+ ],
+ [
+ 0.079482,
+ "e"
+ ],
+ [
+ 0.216511,
+ "s"
+ ],
+ [
+ 0.167541,
+ "s"
+ ],
+ [
+ 0.176420,
+ "a"
+ ],
+ [
+ 0.487983,
+ "g"
+ ],
+ [
+ 0.063926,
+ "e"
+ ],
+ [
+ 0.240043,
+ "\r\n"
+ ],
+ [
+ 0.000103,
+ "bash-3.2$ "
+ ],
+ [
+ 0.303813,
+ "g"
+ ],
+ [
+ 0.088101,
+ "i"
+ ],
+ [
+ 0.095792,
+ "t"
+ ],
+ [
+ 0.535908,
+ " "
+ ],
+ [
+ 0.080185,
+ "l"
+ ],
+ [
+ 0.112012,
+ "o"
+ ],
+ [
+ 0.056328,
+ "g"
+ ],
+ [
+ 0.127542,
+ " "
+ ],
+ [
+ 0.136200,
+ "-"
+ ],
+ [
+ 0.143844,
+ "1"
+ ],
+ [
+ 0.416074,
+ "\r\n"
+ ],
+ [
+ 0.012270,
+ "\u001b[?1h\u001b=\r"
+ ],
+ [
+ 0.000209,
+ "\u001b[33mcommit c8ad52bbf7386d2e6ca39e479456a8bfae086629\u001b[m\u001b[m\r\nAuthor: Joris Roovers \u003cjroovers@cisco.com\u003e\u001b[m\r\nDate: Sun Nov 22 17:31:49 2015 +0100\u001b[m\r\n\u001b[m\r\n WIP: This is a commit message title.\u001b[m\r\n Second line not empty\u001b[m\r\n This body line exceeds the defacto standard length of 80 characters per line in a commit message.\u001b[m\r\n\r\u001b[K\u001b[?1l\u001b\u003e"
+ ],
+ [
+ 0.000643,
+ "bash-3.2$ "
+ ],
+ [
+ 1.618373,
+ "#"
+ ],
+ [
+ 0.152173,
+ " "
+ ],
+ [
+ 0.296271,
+ "Y"
+ ],
+ [
+ 0.143886,
+ "o"
+ ],
+ [
+ 0.032116,
+ "u"
+ ],
+ [
+ 0.255972,
+ " "
+ ],
+ [
+ 0.056004,
+ "c"
+ ],
+ [
+ 0.080252,
+ "a"
+ ],
+ [
+ 0.095730,
+ "n"
+ ],
+ [
+ 0.136000,
+ " "
+ ],
+ [
+ 0.112007,
+ "a"
+ ],
+ [
+ 0.119993,
+ "l"
+ ],
+ [
+ 0.104070,
+ "s"
+ ],
+ [
+ 0.095935,
+ "o"
+ ],
+ [
+ 0.191605,
+ " "
+ ],
+ [
+ 0.456320,
+ "i"
+ ],
+ [
+ 0.032035,
+ "n"
+ ],
+ [
+ 0.071923,
+ "s"
+ ],
+ [
+ 0.080070,
+ "t"
+ ],
+ [
+ 0.079964,
+ "a"
+ ],
+ [
+ 0.088007,
+ "l"
+ ],
+ [
+ 0.144266,
+ "l"
+ ],
+ [
+ 0.071532,
+ " "
+ ],
+ [
+ 0.424083,
+ "g"
+ ],
+ [
+ 0.064402,
+ "i"
+ ],
+ [
+ 0.119971,
+ "t"
+ ],
+ [
+ 0.087788,
+ "l"
+ ],
+ [
+ 0.047978,
+ "i"
+ ],
+ [
+ 0.055909,
+ "n"
+ ],
+ [
+ 0.104026,
+ "t"
+ ],
+ [
+ 0.079939,
+ " "
+ ],
+ [
+ 0.152052,
+ "a"
+ ],
+ [
+ 0.079983,
+ "s"
+ ],
+ [
+ 0.127987,
+ " "
+ ],
+ [
+ 0.776097,
+ "a"
+ ],
+ [
+ 0.416226,
+ " "
+ ],
+ [
+ 0.191962,
+ "c"
+ ],
+ [
+ 0.031735,
+ "o"
+ ],
+ [
+ 0.200042,
+ "m"
+ ],
+ [
+ 0.159913,
+ "m"
+ ],
+ [
+ 0.127947,
+ "i"
+ ],
+ [
+ 0.456063,
+ "t"
+ ],
+ [
+ 0.136031,
+ "-"
+ ],
+ [
+ 0.215964,
+ "m"
+ ],
+ [
+ 0.175984,
+ "s"
+ ],
+ [
+ 0.272013,
+ "g"
+ ],
+ [
+ 0.119964,
+ " "
+ ],
+ [
+ 0.184214,
+ "h"
+ ],
+ [
+ 0.192024,
+ "o"
+ ],
+ [
+ 0.119950,
+ "o"
+ ],
+ [
+ 0.047751,
+ "k"
+ ],
+ [
+ 0.431743,
+ "\r\n"
+ ],
+ [
+ 0.000085,
+ "bash-3.2$ "
+ ],
+ [
+ 0.760296,
+ "g"
+ ],
+ [
+ 0.079911,
+ "i"
+ ],
+ [
+ 0.191987,
+ "t"
+ ],
+ [
+ 0.304096,
+ "l"
+ ],
+ [
+ 0.287428,
+ "i"
+ ],
+ [
+ 0.064628,
+ "n"
+ ],
+ [
+ 0.127768,
+ "t"
+ ],
+ [
+ 0.072263,
+ " "
+ ],
+ [
+ 0.351385,
+ "i"
+ ],
+ [
+ 0.031803,
+ "n"
+ ],
+ [
+ 0.088639,
+ "s"
+ ],
+ [
+ 0.080034,
+ "t"
+ ],
+ [
+ 0.064156,
+ "a"
+ ],
+ [
+ 0.071949,
+ "l"
+ ],
+ [
+ 0.135713,
+ "l"
+ ],
+ [
+ 0.192018,
+ "-"
+ ],
+ [
+ 0.191953,
+ "h"
+ ],
+ [
+ 0.207996,
+ "o"
+ ],
+ [
+ 0.127991,
+ "o"
+ ],
+ [
+ 0.088152,
+ "k"
+ ],
+ [
+ 0.431858,
+ "\r\n"
+ ],
+ [
+ 0.072226,
+ "Successfully installed gitlint commit-msg hook in /Users/jroovers/my-git-repo/.git/hooks/commit-msg\r\n"
+ ],
+ [
+ 0.003614,
+ "bash-3.2$ "
+ ],
+ [
+ 1.036119,
+ "#"
+ ],
+ [
+ 0.160217,
+ " "
+ ],
+ [
+ 0.295771,
+ "L"
+ ],
+ [
+ 0.151619,
+ "e"
+ ],
+ [
+ 0.096263,
+ "t"
+ ],
+ [
+ 0.895797,
+ "'"
+ ],
+ [
+ 0.184596,
+ "s"
+ ],
+ [
+ 0.143677,
+ " "
+ ],
+ [
+ 0.103909,
+ "t"
+ ],
+ [
+ 0.175892,
+ "r"
+ ],
+ [
+ 0.072131,
+ "y"
+ ],
+ [
+ 0.144032,
+ " "
+ ],
+ [
+ 0.160272,
+ "i"
+ ],
+ [
+ 0.119444,
+ "t"
+ ],
+ [
+ 0.088258,
+ " "
+ ],
+ [
+ 0.207962,
+ "o"
+ ],
+ [
+ 0.056392,
+ "u"
+ ],
+ [
+ 0.103632,
+ "t"
+ ],
+ [
+ 0.552056,
+ "\r\n"
+ ],
+ [
+ 0.000096,
+ "bash-3.2$ "
+ ],
+ [
+ 0.0591595,
+ "e"
+ ],
+ [
+ 0.104138,
+ "c"
+ ],
+ [
+ 0.104065,
+ "h"
+ ],
+ [
+ 0.064048,
+ "o"
+ ],
+ [
+ 0.135782,
+ " "
+ ],
+ [
+ 0.192483,
+ "\""
+ ],
+ [
+ 0.175634,
+ "t"
+ ],
+ [
+ 0.072179,
+ "e"
+ ],
+ [
+ 0.151799,
+ "s"
+ ],
+ [
+ 0.080120,
+ "t"
+ ],
+ [
+ 0.175911,
+ "\""
+ ],
+ [
+ 0.135948,
+ " "
+ ],
+ [
+ 0.208327,
+ "\u003e"
+ ],
+ [
+ 0.079867,
+ " "
+ ],
+ [
+ 0.240416,
+ "f"
+ ],
+ [
+ 0.096300,
+ "o"
+ ],
+ [
+ 0.119709,
+ "o"
+ ],
+ [
+ 0.184111,
+ "."
+ ],
+ [
+ 0.199981,
+ "t"
+ ],
+ [
+ 0.223634,
+ "x"
+ ],
+ [
+ 0.232100,
+ "t"
+ ],
+ [
+ 0.839909,
+ "\r\n"
+ ],
+ [
+ 0.000434,
+ "bash-3.2$ "
+ ],
+ [
+ 0.743621,
+ "g"
+ ],
+ [
+ 0.047948,
+ "i"
+ ],
+ [
+ 0.103991,
+ "t"
+ ],
+ [
+ 0.088317,
+ " "
+ ],
+ [
+ 0.159935,
+ "a"
+ ],
+ [
+ 0.200067,
+ "d"
+ ],
+ [
+ 0.159339,
+ "d"
+ ],
+ [
+ 0.144280,
+ " "
+ ],
+ [
+ 0.136254,
+ "."
+ ],
+ [
+ 0.399760,
+ "\r\n"
+ ],
+ [
+ 0.010930,
+ "bash-3.2$ "
+ ],
+ [
+ 0.213093,
+ "g"
+ ],
+ [
+ 0.095974,
+ "i"
+ ],
+ [
+ 0.103967,
+ "t"
+ ],
+ [
+ 0.120050,
+ " "
+ ],
+ [
+ 0.176294,
+ "c"
+ ],
+ [
+ 0.127966,
+ "o"
+ ],
+ [
+ 0.183809,
+ "m"
+ ],
+ [
+ 0.160022,
+ "m"
+ ],
+ [
+ 0.120056,
+ "i"
+ ],
+ [
+ 0.143736,
+ "t"
+ ],
+ [
+ 1.104266,
+ "\r\n"
+ ],
+ [
+ 0.090605,
+ "\u001b[?1049h\u001b[?1h\u001b="
+ ],
+ [
+ 0.003626,
+ "\u001b[1;28r\u001b[?12;25h\u001b[?12l\u001b[?25h\u001b[27m\u001b[m\u001b[H\u001b[2J\u001b[?25l\u001b[28;1H\"~/my-git-repo/.git/COMMIT_EDITMSG\""
+ ],
+ [
+ 0.000779,
+ " 7L, 206C"
+ ],
+ [
+ 0.004938,
+ "\u001b[\u003ec"
+ ],
+ [
+ 0.002767,
+ "\u001b[1;1H\u001b[93m 1 \r\n 2 \u001b[m\u001b[96m# Please enter the commit message for your changes. Lines starting\u001b[m\r\n\u001b[93m 3 \u001b[m\u001b[96m# with '#' will be ignored, and an empty message aborts the commit.\u001b[m\r\n\u001b[93m 4 \u001b[m\u001b[96m# On branch \u001b[m\u001b[38;5;224mmaster\u001b[m\r\n\u001b[93m 5 \u001b[m\u001b[96m# \u001b[m\u001b[38;5;81mChanges to be committed:\u001b[m\r\n\u001b[93m 6 \u001b[m\u001b[96m# \u001b[m\u001b[38;5;121mnew file\u001b[m\u001b[96m: \u001b[m\u001b[95m foo.txt\u001b[m\r\n\u001b[93m 7 \u001b[m\u001b[96m#\u001b[m\r\n\u001b[94m~ \u001b[9;1H~ \u001b[10;1H~ \u001b[11;1H~ \u001b[12;1H~ \u001b[13;1H~ "
+ ],
+ [
+ 0.000062,
+ " \u001b[14;1H~ \u001b[15;1H~ \u001b[16;1H~ \u001b[17;1H~ \u001b[18;1H~ \u001b[19;1H~ \u001b[20;1H~ \u001b[21;1H~ \u001b[22;1H~ "
+ ],
+ [
+ 0.000865,
+ "\u001b[23;1H~ \u001b[24;1H~ \u001b[25;1H~ \u001b[26;1H~ \u001b[27;1H~ \u001b[1;5H\u001b[?12l\u001b[?25h"
+ ],
+ [
+ 0.468652,
+ "\u001b[?25l\u001b[m\u001b[28;1H\u001b[1m-- INSERT --\u001b[m\u001b[28;13H\u001b[K\u001b[1;5H\u001b[?12l\u001b[?25h"
+ ],
+ [
+ 0.292362,
+ "\u001b[?25l\u0008\u001b[93m W\u001b[?12l\u001b[?25h"
+ ],
+ [
+ 0.112916,
+ "\u001b[?25l\u0008WI"
+ ],
+ [
+ 0.000464,
+ "\u001b[m\u001b[28;1H\u001b[K\u001b[28;1H="
+ ],
+ [
+ 0.000027,
+ "acp#onPopupPost()\r"
+ ],
+ [
+ 0.000025,
+ "\u001b[28;1H\u001b[K"
+ ],
+ [
+ 0.000084,
+ "\u001b[28;1H="
+ ],
+ [
+ 0.000029,
+ "acp#onPopupPost()\r"
+ ],
+ [
+ 0.000004,
+ "\u001b[28;1H\u001b[K"
+ ],
+ [
+ 0.000273,
+ "\u001b[28;1H\u001b[1m-- Keyword completion (^N^P) \u001b[m\u001b[97m\u001b[41mPattern not found\u001b[m\u001b[28;1H\u001b[K"
+ ],
+ [
+ 0.000004,
+ "\u001b[28;1H\u001b[1m-- INSERT --"
+ ],
+ [
+ 0.000920,
+ "\u001b[1;7H\u001b[?12l\u001b[?25h"
+ ],
+ [
+ 0.076999,
+ "\u001b[?25l\u001b[m\u0008\u001b[93mIP\u001b[?12l\u001b[?25h"
+ ],
+ [
+ 0.463368,
+ "\u001b[?25l \u001b[?12l\u001b[?25h"
+ ],
+ [
+ 0.352661,
+ "\u001b[?25l\u001b[m\u001b[1;8H\u001b[K"
+ ],
+ [
+ 0.000019,
+ "\u001b[28;1H\u001b[K\u001b[28;1H="
+ ],
+ [
+ 0.000039,
+ "acp#onPopupPost()\r"
+ ],
+ [
+ 0.000039,
+ "\u001b[28;1H\u001b[K"
+ ],
+ [
+ 0.000081,
+ "\u001b[28;1H="
+ ],
+ [
+ 0.000018,
+ "acp#onPopupPost()\r"
+ ],
+ [
+ 0.000022,
+ "\u001b[28;1H\u001b[K"
+ ],
+ [
+ 0.000227,
+ "\u001b[28;1H\u001b[1m-- Keyword completion (^N^P) \u001b[m\u001b[97m\u001b[41mPattern not found\u001b[m\u001b[28;1H\u001b[K"
+ ],
+ [
+ 0.000004,
+ "\u001b[28;1H\u001b[1m-- INSERT --"
+ ],
+ [
+ 0.000839,
+ "\u001b[1;8H\u001b[?12l\u001b[?25h"
+ ],
+ [
+ 0.214580,
+ "\u001b[?25l\u001b[m\u0008\u001b[93mP:\u001b[?12l\u001b[?25h"
+ ],
+ [
+ 0.208063,
+ "\u001b[?25l \u001b[?12l\u001b[?25h"
+ ],
+ [
+ 0.167897,
+ "\u001b[?25l\u0008 T\u001b[?12l\u001b[?25h"
+ ],
+ [
+ 0.119757,
+ "\u001b[?25l\u0008Th"
+ ],
+ [
+ 0.000048,
+ "\u001b[m\u001b[28;1H\u001b[K\u001b[28;1H="
+ ],
+ [
+ 0.000014,
+ "acp#onPopupPost()\r"
+ ],
+ [
+ 0.000022,
+ "\u001b[28;1H\u001b[K"
+ ],
+ [
+ 0.000070,
+ "\u001b[28;1H="
+ ],
+ [
+ 0.000016,
+ "acp#onPopupPost()\r"
+ ],
+ [
+ 0.000022,
+ "\u001b[28;1H\u001b[K"
+ ],
+ [
+ 0.000225,
+ "\u001b[28;1H\u001b[1m-- Keyword completion (^N^P) \u001b[m\u001b[97m\u001b[41mPattern not found\u001b[m\u001b[28;1H\u001b[K"
+ ],
+ [
+ 0.000031,
+ "\u001b[28;1H\u001b[1m-- INSERT --"
+ ],
+ [
+ 0.000752,
+ "\u001b[1;12H\u001b[?12l\u001b[?25h"
+ ],
+ [
+ 0.055116,
+ "\u001b[?25l\u001b[m\u0008\u001b[93mhi\u001b[?12l\u001b[?25h"
+ ],
+ [
+ 0.128002,
+ "\u001b[?25l\u0008is\u001b[?12l\u001b[?25h"
+ ],
+ [
+ 0.064056,
+ "\u001b[?25l \u001b[?12l\u001b[?25h"
+ ],
+ [
+ 0.143867,
+ "\u001b[?25l\u0008 i\u001b[?12l\u001b[?25h"
+ ],
+ [
+ 0.072155,
+ "\u001b[?25l\u0008is"
+ ],
+ [
+ 0.000057,
+ "\u001b[m\u001b[28;1H\u001b[K\u001b[28;1H="
+ ],
+ [
+ 0.000040,
+ "acp#onPopupPost()\r"
+ ],
+ [
+ 0.000019,
+ "\u001b[28;1H\u001b[K"
+ ],
+ [
+ 0.000100,
+ "\u001b[28;1H="
+ ],
+ [
+ 0.000040,
+ "acp#onPopupPost()\r"
+ ],
+ [
+ 0.000005,
+ "\u001b[28;1H\u001b[K"
+ ],
+ [
+ 0.000279,
+ "\u001b[28;1H\u001b[1m-- Keyword completion (^N^P) \u001b[m\u001b[97m\u001b[41mPattern not found\u001b[m\u001b[28;1H\u001b[K"
+ ],
+ [
+ 0.000004,
+ "\u001b[28;1H\u001b[1m-- INSERT --"
+ ],
+ [
+ 0.000905,
+ "\u001b[1;17H\u001b[?12l\u001b[?25h"
+ ],
+ [
+ 0.134356,
+ "\u001b[?25l\u001b[m\u001b[93m \u001b[?12l\u001b[?25h"
+ ],
+ [
+ 0.072054,
+ "\u001b[?25l\u0008 a\u001b[?12l\u001b[?25h"
+ ],
+ [
+ 0.520162,
+ "\u001b[?25l\u0008an"
+ ],
+ [
+ 0.000090,
+ "\u001b[m\u001b[2;17H\u001b[48;5;242m and \u001b[m\u001b[3;17H\u001b[105m an \u001b[m\u001b[28;1H\u001b[K\u001b[28;1H="
+ ],
+ [
+ 0.000021,
+ "acp#onPopupPost()\r"
+ ],
+ [
+ 0.000023,
+ "\u001b[28;1H\u001b[K"
+ ],
+ [
+ 0.000074,
+ "\u001b[2;17H\u001b[105m and "
+ ],
+ [
+ 0.000043,
+ "\u001b[m\u001b[28;1H\u001b[1m-- Keyword completion (^N^P)"
+ ],
+ [
+ 0.000355,
+ "\u001b[m\u001b[2;16H\u001b[96mter the commit me\u001b[3;16Hwill be ignored, "
+ ],
+ [
+ 0.000123,
+ "\u001b[m\u001b[28;29H\u001b[1m \u001b[m\u001b[38;5;121mmatch 1 of 2"
+ ],
+ [
+ 0.000067,
+ "\u001b[1;20H"
+ ],
+ [
+ 0.000004,
+ "\u001b[m\u001b[2;17H\u001b[48;5;242m and \u001b[m\u001b[3;17H\u001b[105m an "
+ ],
+ [
+ 0.000021,
+ "\u001b[1;20H"
+ ],
+ [
+ 0.000078,
+ "\u001b[?12l\u001b[?25h"
+ ],
+ [
+ 0.157947,
+ "\u001b[?25l"
+ ],
+ [
+ 0.000033,
+ "\u001b[m\u001b[28;1H\u001b[K"
+ ],
+ [
+ 0.000037,
+ "\u001b[28;1H\u001b[1m-- INSERT --"
+ ],
+ [
+ 0.000308,
+ "\u001b[m\u001b[1;20H\u001b[93m \u001b[m\u001b[2;16H\u001b[96mter the commit me\u001b[3;16Hwill be ignored, "
+ ],
+ [
+ 0.000548,
+ "\u001b[1;21H\u001b[?12l\u001b[?25h"
+ ],
+ [
+ 0.735999,
+ "\u001b[?25l\u001b[m\u0008\u001b[93m p\u001b[?12l\u001b[?25h"
+ ],
+ [
+ 0.104200,
+ "\u001b[?25l\u0008pa"
+ ],
+ [
+ 0.000005,
+ "\u001b[m\u001b[28;1H\u001b[K\u001b[28;1H="
+ ],
+ [
+ 0.000041,
+ "acp#onPopupPost()\r"
+ ],
+ [
+ 0.000033,
+ "\u001b[28;1H\u001b[K"
+ ],
+ [
+ 0.000071,
+ "\u001b[28;1H="
+ ],
+ [
+ 0.000038,
+ "acp#onPopupPost()\r"
+ ],
+ [
+ 0.000020,
+ "\u001b[28;1H\u001b[K"
+ ],
+ [
+ 0.000245,
+ "\u001b[28;1H\u001b[1m-- Keyword completion (^N^P) \u001b[m\u001b[97m\u001b[41mPattern not found\u001b[m\u001b[28;1H\u001b[K"
+ ],
+ [
+ 0.000033,
+ "\u001b[28;1H\u001b[1m-- INSERT --"
+ ],
+ [
+ 0.000896,
+ "\u001b[1;23H\u001b[?12l\u001b[?25h"
+ ],
+ [
+ 0.086431,
+ "\u001b[?25l\u001b[m\u0008\u001b[93mat\u001b[?12l\u001b[?25h"
+ ],
+ [
+ 0.176505,
+ "\u001b[?25l\u0008tc\u001b[?12l\u001b[?25h"
+ ],
+ [
+ 0.103498,
+ "\u001b[?25l\u0008ch\u001b[?12l\u001b[?25h"
+ ],
+ [
+ 0.080001,
+ "\u001b[?25l\u0008hs\u001b[?12l\u001b[?25h"
+ ],
+ [
+ 0.176470,
+ "\u001b[?25l\u0008se\u001b[?12l\u001b[?25h"
+ ],
+ [
+ 0.063481,
+ "\u001b[?25l\u0008et\u001b[?12l\u001b[?25h"
+ ],
+ [
+ 0.079520,
+ "\u001b[?25l \u001b[?12l\u001b[?25h"
+ ],
+ [
+ 0.128786,
+ "\u001b[?25l\u0008 t\u001b[?12l\u001b[?25h"
+ ],
+ [
+ 0.199925,
+ "\u001b[?25l\u0008th"
+ ],
+ [
+ 0.000115,
+ "\u001b[m\u001b[2;29H\u001b[48;5;242m the \u001b[m\u001b[3;29H\u001b[105m This \u001b[m\u001b[28;1H\u001b[K\u001b[28;1H="
+ ],
+ [
+ 0.000013,
+ "acp#onPopupPost()\r"
+ ],
+ [
+ 0.000024,
+ "\u001b[28;1H\u001b[K"
+ ],
+ [
+ 0.000064,
+ "\u001b[2;29H\u001b[105m the "
+ ],
+ [
+ 0.000048,
+ "\u001b[m\u001b[28;1H\u001b[1m-- Keyword completion (^N^P)"
+ ],
+ [
+ 0.000335,
+ "\u001b[m\u001b[2;28H\u001b[96mit message for yo\u001b[3;28Hred, and an empty"
+ ],
+ [
+ 0.000100,
+ "\u001b[m\u001b[28;29H\u001b[1m \u001b[m\u001b[38;5;121mmatch 1 of 2"
+ ],
+ [
+ 0.000048,
+ "\u001b[1;32H"
+ ],
+ [
+ 0.000004,
+ "\u001b[m\u001b[2;29H\u001b[48;5;242m the \u001b[m\u001b[3;29H\u001b[105m This "
+ ],
+ [
+ 0.000026,
+ "\u001b[1;32H"
+ ],
+ [
+ 0.000068,
+ "\u001b[?12l\u001b[?25h"
+ ],
+ [
+ 0.014726,
+ "\u001b[?25l\u001b[m\u0008\u001b[93mha\u001b[m\u001b[2;28H\u001b[96mit message for yo\u001b[3;28Hred, and an empty"
+ ],
+ [
+ 0.000780,
+ "\u001b[1;33H\u001b[?12l\u001b[?25h"
+ ],
+ [
+ 0.679312,
+ "\u001b[?25l\u001b[m\u0008\u001b[93mat"
+ ],
+ [
+ 0.000870,
+ "\u001b[m\u001b[28;1H\u001b[K\u001b[28;1H="
+ ],
+ [
+ 0.000049,
+ "acp#onPopupPost()\r"
+ ],
+ [
+ 0.000015,
+ "\u001b[28;1H\u001b[K"
+ ],
+ [
+ 0.000129,
+ "\u001b[28;1H="
+ ],
+ [
+ 0.000035,
+ "acp#onPopupPost()\r"
+ ],
+ [
+ 0.000020,
+ "\u001b[28;1H\u001b[K"
+ ],
+ [
+ 0.000373,
+ "\u001b[28;1H\u001b[1m-- Keyword completion (^N^P) \u001b[m\u001b[97m\u001b[41mPattern not found\u001b[m\u001b[28;1H\u001b[K"
+ ],
+ [
+ 0.000006,
+ "\u001b[28;1H\u001b[1m-- INSERT --"
+ ],
+ [
+ 0.001035,
+ "\u001b[1;34H\u001b[?12l\u001b[?25h"
+ ],
+ [
+ 0.085617,
+ "\u001b[?25l\u001b[m\u001b[93m \u001b[?12l\u001b[?25h"
+ ],
+ [
+ 0.327942,
+ "\u001b[?25l\u0008 I\u001b[?12l\u001b[?25h"
+ ],
+ [
+ 0.167989,
+ "\u001b[?25l \u001b[?12l\u001b[?25h"
+ ],
+ [
+ 0.136505,
+ "\u001b[?25l\u0008 n\u001b[?12l\u001b[?25h"
+ ],
+ [
+ 0.111668,
+ "\u001b[?25l\u0008ne"
+ ],
+ [
+ 0.000119,
+ "\u001b[m\u001b[2;36H\u001b[48;5;242m new \u001b[m\u001b[28;1H\u001b[K\u001b[28;1H="
+ ],
+ [
+ 0.000024,
+ "acp#onPopupPost()\r"
+ ],
+ [
+ 0.000051,
+ "\u001b[28;1H\u001b[K"
+ ],
+ [
+ 0.000054,
+ "\u001b[2;36H\u001b[105m new "
+ ],
+ [
+ 0.000066,
+ "\u001b[m\u001b[28;1H\u001b[1m-- Keyword completion (^N^P)"
+ ],
+ [
+ 0.000361,
+ "\u001b[m\u001b[2;35H\u001b[96mage for your chan"
+ ],
+ [
+ 0.000117,
+ "\u001b[m\u001b[28;29H\u001b[1m The only match"
+ ],
+ [
+ 0.000049,
+ "\u001b[1;39H"
+ ],
+ [
+ 0.000030,
+ "\u001b[m\u001b[2;36H\u001b[48;5;242m new "
+ ],
+ [
+ 0.000008,
+ "\u001b[1;39H"
+ ],
+ [
+ 0.000084,
+ "\u001b[?12l\u001b[?25h"
+ ],
+ [
+ 0.142635,
+ "\u001b[?25l\u001b[m\u0008\u001b[93mee\u001b[m\u001b[2;35H\u001b[96mage for your chan"
+ ],
+ [
+ 0.000743,
+ "\u001b[1;40H\u001b[?12l\u001b[?25h"
+ ],
+ [
+ 0.079680,
+ "\u001b[?25l\u001b[m\u0008\u001b[93med\u001b[m\u001b[28;1H\u001b[K\u001b[28;1H="
+ ],
+ [
+ 0.000006,
+ "acp#onPopupPost()\r"
+ ],
+ [
+ 0.000047,
+ "\u001b[28;1H\u001b[K"
+ ],
+ [
+ 0.000099,
+ "\u001b[28;1H="
+ ],
+ [
+ 0.000010,
+ "acp#onPopupPost()\r"
+ ],
+ [
+ 0.000027,
+ "\u001b[28;1H\u001b[K"
+ ],
+ [
+ 0.000251,
+ "\u001b[28;1H\u001b[1m-- Keyword completion (^N^P) \u001b[m\u001b[97m\u001b[41mPattern not found\u001b[m\u001b[28;1H\u001b[K"
+ ],
+ [
+ 0.000026,
+ "\u001b[28;1H\u001b[1m-- INSERT --"
+ ],
+ [
+ 0.000876,
+ "\u001b[1;41H\u001b[?12l\u001b[?25h"
+ ],
+ [
+ 0.086590,
+ "\u001b[?25l\u001b[m\u001b[93m \u001b[?12l\u001b[?25h"
+ ],
+ [
+ 0.159864,
+ "\u001b[?25l\u0008 t\u001b[?12l\u001b[?25h"
+ ],
+ [
+ 0.079981,
+ "\u001b[?25l\u0008to"
+ ],
+ [
+ 0.000080,
+ "\u001b[m\u001b[2;41H\u001b[48;5;242m to \u001b[m\u001b[28;1H\u001b[K\u001b[28;1H="
+ ],
+ [
+ 0.000021,
+ "acp#onPopupPost()\r"
+ ],
+ [
+ 0.000020,
+ "\u001b[28;1H\u001b[K"
+ ],
+ [
+ 0.000076,
+ "\u001b[2;41H\u001b[105m to "
+ ],
+ [
+ 0.000039,
+ "\u001b[m\u001b[28;1H\u001b[1m-- Keyword completion (^N^P)"
+ ],
+ [
+ 0.000345,
+ "\u001b[m\u001b[2;40H\u001b[96mor your changes. "
+ ],
+ [
+ 0.000085,
+ "\u001b[m\u001b[28;29H\u001b[1m The only match"
+ ],
+ [
+ 0.000041,
+ "\u001b[1;44H"
+ ],
+ [
+ 0.000029,
+ "\u001b[m\u001b[2;41H\u001b[48;5;242m to "
+ ],
+ [
+ 0.000009,
+ "\u001b[1;44H"
+ ],
+ [
+ 0.000071,
+ "\u001b[?12l\u001b[?25h"
+ ],
+ [
+ 0.190677,
+ "\u001b[?25l"
+ ],
+ [
+ 0.000033,
+ "\u001b[m\u001b[28;1H\u001b[K"
+ ],
+ [
+ 0.000040,
+ "\u001b[28;1H\u001b[1m-- INSERT --"
+ ],
+ [
+ 0.000500,
+ "\u001b[m\u001b[1;44H\u001b[93m \u001b[m\u001b[2;40H\u001b[96mor your changes. "
+ ],
+ [
+ 0.000827,
+ "\u001b[1;45H\u001b[?12l\u001b[?25h"
+ ],
+ [
+ 0.095121,
+ "\u001b[?25l\u001b[m\u0008\u001b[93m c\u001b[?12l\u001b[?25h"
+ ],
+ [
+ 0.096188,
+ "\u001b[?25l\u0008co"
+ ],
+ [
+ 0.000114,
+ "\u001b[m\u001b[2;44H\u001b[48;5;242m commit \u001b[m\u001b[3;44H\u001b[105m committed \u001b[m\u001b[28;1H\u001b[K\u001b[28;1H="
+ ],
+ [
+ 0.000027,
+ "acp#onPopupPost()\r"
+ ],
+ [
+ 0.000025,
+ "\u001b[28;1H\u001b[K"
+ ],
+ [
+ 0.000098,
+ "\u001b[2;44H\u001b[105m commit "
+ ],
+ [
+ 0.000033,
+ "\u001b[m\u001b[28;1H\u001b[1m-- Keyword completion (^N^P)"
+ ],
+ [
+ 0.000401,
+ "\u001b[m\u001b[2;43H\u001b[96myour changes. Lin\u001b[3;43Hty message aborts"
+ ],
+ [
+ 0.000108,
+ "\u001b[m\u001b[28;29H\u001b[1m \u001b[m\u001b[38;5;121mmatch 1 of 2"
+ ],
+ [
+ 0.000043,
+ "\u001b[1;47H"
+ ],
+ [
+ 0.000031,
+ "\u001b[m\u001b[2;44H\u001b[48;5;242m commit \u001b[m\u001b[3;44H\u001b[105m committed "
+ ],
+ [
+ 0.000011,
+ "\u001b[1;47H"
+ ],
+ [
+ 0.000074,
+ "\u001b[?12l\u001b[?25h"
+ ],
+ [
+ 0.070604,
+ "\u001b[?25l\u001b[m\u0008\u001b[93mon\u001b[m\u001b[2;43H\u001b[96myour changes. Lin\u001b[3;43Hty message aborts"
+ ],
+ [
+ 0.000833,
+ "\u001b[1;48H\u001b[?12l\u001b[?25h"
+ ],
+ [
+ 0.110931,
+ "\u001b[?25l\u001b[m\u0008\u001b[93mnt"
+ ],
+ [
+ 0.000665,
+ "\u001b[m\u001b[28;1H\u001b[K\u001b[28;1H="
+ ],
+ [
+ 0.000021,
+ "acp#onPopupPost()\r"
+ ],
+ [
+ 0.000027,
+ "\u001b[28;1H\u001b[K"
+ ],
+ [
+ 0.000096,
+ "\u001b[28;1H="
+ ],
+ [
+ 0.000013,
+ "acp#onPopupPost()\r"
+ ],
+ [
+ 0.000026,
+ "\u001b[28;1H\u001b[K"
+ ],
+ [
+ 0.000273,
+ "\u001b[28;1H\u001b[1m-- Keyword completion (^N^P) \u001b[m\u001b[97m\u001b[41mPattern not found\u001b[m\u001b[28;1H\u001b[K"
+ ],
+ [
+ 0.000034,
+ "\u001b[28;1H\u001b[1m-- INSERT --"
+ ],
+ [
+ 0.000994,
+ "\u001b[1;49H\u001b[?12l\u001b[?25h"
+ ],
+ [
+ 0.158110,
+ "\u001b[?25l\u001b[m\u0008\u001b[93mti\u001b[?12l\u001b[?25h"
+ ],
+ [
+ 0.120153,
+ "\u001b[?25l\u0008in\u001b[?12l\u001b[?25h"
+ ],
+ [
+ 0.456043,
+ "\u001b[?25l\u0008nu\u001b[?12l\u001b[?25h"
+ ],
+ [
+ 0.136040,
+ "\u001b[?25l\u0008ue\u001b[?12l\u001b[?25h"
+ ],
+ [
+ 0.087847,
+ "\u001b[?25l \u001b[?12l\u001b[?25h"
+ ],
+ [
+ 0.200047,
+ "\u001b[?25l\u0008 w\u001b[?12l\u001b[?25h"
+ ],
+ [
+ 0.072235,
+ "\u001b[?25l\u0008w\u001b[mo"
+ ],
+ [
+ 0.000052,
+ "\u001b[28;1H\u001b[K\u001b[28;1H="
+ ],
+ [
+ 0.000004,
+ "acp#onPopupPost()\r"
+ ],
+ [
+ 0.000027,
+ "\u001b[28;1H\u001b[K"
+ ],
+ [
+ 0.000071,
+ "\u001b[28;1H="
+ ],
+ [
+ 0.000014,
+ "acp#onPopupPost()\r"
+ ],
+ [
+ 0.000021,
+ "\u001b[28;1H\u001b[K"
+ ],
+ [
+ 0.000258,
+ "\u001b[28;1H\u001b[1m-- Keyword completion (^N^P) \u001b[m\u001b[97m\u001b[41mPattern not found\u001b[m\u001b[28;1H\u001b[K"
+ ],
+ [
+ 0.000004,
+ "\u001b[28;1H\u001b[1m-- INSERT --"
+ ],
+ [
+ 0.000928,
+ "\u001b[1;56H\u001b[?12l\u001b[?25h"
+ ],
+ [
+ 0.142550,
+ "\u001b[?25l\u001b[m\u0008or\u001b[?12l\u001b[?25h"
+ ],
+ [
+ 0.072562,
+ "\u001b[?25l\u0008rk\u001b[?12l\u001b[?25h"
+ ],
+ [
+ 0.143446,
+ "\u001b[?25l\u0008ki\u001b[?12l\u001b[?25h"
+ ],
+ [
+ 0.064195,
+ "\u001b[?25l\u0008in\u001b[?12l\u001b[?25h"
+ ],
+ [
+ 0.064352,
+ "\u001b[?25l\u0008ng\u001b[?12l\u001b[?25h"
+ ],
+ [
+ 0.135448,
+ "\u001b[?25l \u001b[?12l\u001b[?25h"
+ ],
+ [
+ 0.431640,
+ "\u001b[?25l\u0008 o\u001b[?12l\u001b[?25h"
+ ],
+ [
+ 0.080069,
+ "\u001b[?25l\u0008on"
+ ],
+ [
+ 0.000051,
+ "\u001b[2;61H\u001b[48;5;242m On \u001b[m\u001b[28;1H\u001b[K\u001b[28;1H="
+ ],
+ [
+ 0.000018,
+ "acp#onPopupPost()\r"
+ ],
+ [
+ 0.000040,
+ "\u001b[28;1H\u001b[K"
+ ],
+ [
+ 0.000054,
+ "\u001b[2;61H\u001b[105m On "
+ ],
+ [
+ 0.000010,
+ "\u001b[m\u001b[28;1H\u001b[1m-- Keyword completion (^N^P)"
+ ],
+ [
+ 0.000288,
+ "\u001b[m\u001b[2;60H\u001b[96mes starting\u001b[m\u001b[2;71H\u001b[K"
+ ],
+ [
+ 0.000076,
+ "\u001b[28;29H\u001b[1m The only match"
+ ],
+ [
+ 0.000039,
+ "\u001b[1;64H"
+ ],
+ [
+ 0.000016,
+ "\u001b[m\u001b[2;61H\u001b[48;5;242m On "
+ ],
+ [
+ 0.000028,
+ "\u001b[1;64H"
+ ],
+ [
+ 0.000055,
+ "\u001b[?12l\u001b[?25h"
+ ],
+ [
+ 1.438871,
+ "\u001b[?25l"
+ ],
+ [
+ 0.000006,
+ "\u001b[m\u001b[28;1H\u001b[K"
+ ],
+ [
+ 0.000050,
+ "\u001b[28;1H\u001b[1m-- INSERT --"
+ ],
+ [
+ 0.000498,
+ "\u001b[m\u001b[1;63Hn!\u001b[2;60H\u001b[96mes starting\u001b[m\u001b[2;71H\u001b[K"
+ ],
+ [
+ 0.000856,
+ "\u001b[1;65H\u001b[?12l\u001b[?25h"
+ ],
+ [
+ 0.435983,
+ "\u001b[28;1H\u001b[K\u001b[1;64H"
+ ],
+ [
+ 0.314354,
+ "\u001b[?25l"
+ ],
+ [
+ 0.000414,
+ "\u001b[?12l\u001b[?25h\u001b[?25l\u001b[28;1H:"
+ ],
+ [
+ 0.000020,
+ "\u001b[?12l\u001b[?25h"
+ ],
+ [
+ 0.191831,
+ "w"
+ ],
+ [
+ 0.039852,
+ "q"
+ ],
+ [
+ 0.560137,
+ "\r"
+ ],
+ [
+ 0.000384,
+ "\u001b[?25l"
+ ],
+ [
+ 0.000061,
+ "\".git/COMMIT_EDITMSG\""
+ ],
+ [
+ 0.001403,
+ " 7L, 266C written"
+ ],
+ [
+ 0.001698,
+ "\r\r\r\n\u001b[?1l\u001b\u003e\u001b[?12l\u001b[?25h\u001b[?1049l"
+ ],
+ [
+ 0.003162,
+ "gitlint: checking commit message...\r\n"
+ ],
+ [
+ 0.052844,
+ "1: T3 Title has trailing punctuation (!): \"WIP: This is an patchset that I need to continue working on!\"\r\n1: T5 Title contains the word 'WIP' (case-insensitive): \"WIP: This is an patchset that I need to continue working on!\"\r\n3: B6 Body message is missing\r\n"
+ ],
+ [
+ 0.006075,
+ "-----------------------------------------------\r\n"
+ ],
+ [
+ 0.000020,
+ "gitlint: \u001b[31mYour commit message contains the above violations.\u001b[0m\r\n"
+ ],
+ [
+ 0.002541,
+ "\u001b[?1034h"
+ ],
+ [
+ 0.000014,
+ "Continue with commit anyways (this keeps the current commit message)? [y/n] "
+ ],
+ [
+ 6.778903,
+ "y"
+ ],
+ [
+ 0.376370,
+ "\r\n"
+ ],
+ [
+ 0.004763,
+ "[master 4b1f92d] WIP: This is an patchset that I need to continue working on!\r\n"
+ ],
+ [
+ 0.001504,
+ " 1 file changed, 1 insertion(+)\r\n create mode 100644 foo.txt\r\n"
+ ],
+ [
+ 0.000420,
+ "bash-3.2$ "
+ ],
+ [
+ 0.913122,
+ "#"
+ ],
+ [
+ 0.143873,
+ " "
+ ],
+ [
+ 1.040537,
+ "Y"
+ ],
+ [
+ 0.159468,
+ "o"
+ ],
+ [
+ 0.032403,
+ "u"
+ ],
+ [
+ 0.255831,
+ " "
+ ],
+ [
+ 0.128028,
+ "c"
+ ],
+ [
+ 0.056381,
+ "a"
+ ],
+ [
+ 0.047650,
+ "n"
+ ],
+ [
+ 0.144010,
+ " "
+ ],
+ [
+ 0.143892,
+ "m"
+ ],
+ [
+ 0.096047,
+ "o"
+ ],
+ [
+ 0.127988,
+ "d"
+ ],
+ [
+ 0.144268,
+ "i"
+ ],
+ [
+ 0.183322,
+ "f"
+ ],
+ [
+ 0.136376,
+ "y"
+ ],
+ [
+ 0.192288,
+ " "
+ ],
+ [
+ 0.127701,
+ "g"
+ ],
+ [
+ 0.088308,
+ "i"
+ ],
+ [
+ 0.495279,
+ "t"
+ ],
+ [
+ 0.192340,
+ "l"
+ ],
+ [
+ 0.055845,
+ "i"
+ ],
+ [
+ 0.072236,
+ "n"
+ ],
+ [
+ 0.111890,
+ "t"
+ ],
+ [
+ 0.320013,
+ "'"
+ ],
+ [
+ 0.167698,
+ "s"
+ ],
+ [
+ 0.088331,
+ " "
+ ],
+ [
+ 0.208264,
+ "b"
+ ],
+ [
+ 0.087663,
+ "e"
+ ],
+ [
+ 0.352021,
+ "h"
+ ],
+ [
+ 0.191971,
+ "a"
+ ],
+ [
+ 0.176006,
+ "v"
+ ],
+ [
+ 0.104268,
+ "i"
+ ],
+ [
+ 0.023762,
+ "o"
+ ],
+ [
+ 0.128201,
+ "r"
+ ],
+ [
+ 0.119900,
+ " "
+ ],
+ [
+ 0.183877,
+ "b"
+ ],
+ [
+ 0.143917,
+ "y"
+ ],
+ [
+ 0.240199,
+ " "
+ ],
+ [
+ 0.647870,
+ "c"
+ ],
+ [
+ 0.041003,
+ "o"
+ ],
+ [
+ 0.063052,
+ "n"
+ ],
+ [
+ 0.144261,
+ "f"
+ ],
+ [
+ 0.103317,
+ "i"
+ ],
+ [
+ 0.128402,
+ "g"
+ ],
+ [
+ 0.080038,
+ "u"
+ ],
+ [
+ 0.128003,
+ "r"
+ ],
+ [
+ 0.480050,
+ "i"
+ ],
+ [
+ 0.047741,
+ "n"
+ ],
+ [
+ 0.103828,
+ "g"
+ ],
+ [
+ 0.126593,
+ " "
+ ],
+ [
+ 0.113591,
+ "a"
+ ],
+ [
+ 0.104071,
+ " "
+ ],
+ [
+ 0.343976,
+ "."
+ ],
+ [
+ 0.215812,
+ "g"
+ ],
+ [
+ 0.088229,
+ "i"
+ ],
+ [
+ 0.167944,
+ "t"
+ ],
+ [
+ 0.104389,
+ "l"
+ ],
+ [
+ 0.055649,
+ "i"
+ ],
+ [
+ 0.064009,
+ "n"
+ ],
+ [
+ 0.128039,
+ "t"
+ ],
+ [
+ 0.111929,
+ " "
+ ],
+ [
+ 0.151932,
+ "f"
+ ],
+ [
+ 0.072042,
+ "i"
+ ],
+ [
+ 0.072020,
+ "l"
+ ],
+ [
+ 0.079850,
+ "e"
+ ],
+ [
+ 0.656150,
+ "\r\n"
+ ],
+ [
+ 0.000100,
+ "bash-3.2$ "
+ ],
+ [
+ 0.735877,
+ "g"
+ ],
+ [
+ 0.103942,
+ "i"
+ ],
+ [
+ 0.184038,
+ "t"
+ ],
+ [
+ 0.111946,
+ "l"
+ ],
+ [
+ 0.064269,
+ "i"
+ ],
+ [
+ 0.063764,
+ "n"
+ ],
+ [
+ 0.472229,
+ "t"
+ ],
+ [
+ 0.183704,
+ " "
+ ],
+ [
+ 0.416073,
+ "g"
+ ],
+ [
+ 0.096000,
+ "e"
+ ],
+ [
+ 0.143925,
+ "n"
+ ],
+ [
+ 0.064290,
+ "e"
+ ],
+ [
+ 0.079792,
+ "r"
+ ],
+ [
+ 0.095868,
+ "a"
+ ],
+ [
+ 0.104267,
+ "t"
+ ],
+ [
+ 0.207732,
+ "e"
+ ],
+ [
+ 0.184086,
+ "-"
+ ],
+ [
+ 0.171619,
+ "c"
+ ],
+ [
+ 0.084287,
+ "o"
+ ],
+ [
+ 0.064003,
+ "n"
+ ],
+ [
+ 0.111626,
+ "f"
+ ],
+ [
+ 0.168397,
+ "i"
+ ],
+ [
+ 0.135945,
+ "g"
+ ],
+ [
+ 0.344287,
+ "\r\n"
+ ],
+ [
+ 0.054614,
+ "Please specify a location for the sample gitlint config file [.gitlint]: "
+ ],
+ [
+ 1.281099,
+ "\r\n"
+ ],
+ [
+ 0.001231,
+ "Successfully generated /Users/jroovers/my-git-repo/.gitlint\r\n"
+ ],
+ [
+ 0.005057,
+ "bash-3.2$ "
+ ],
+ [
+ 1.481485,
+ "v"
+ ],
+ [
+ 0.056099,
+ "i"
+ ],
+ [
+ 0.063695,
+ "m"
+ ],
+ [
+ 0.159794,
+ " "
+ ],
+ [
+ 0.138400,
+ "."
+ ],
+ [
+ 0.198256,
+ "g"
+ ],
+ [
+ 0.119954,
+ "i"
+ ],
+ [
+ 0.119891,
+ "t"
+ ],
+ [
+ 0.120085,
+ "l"
+ ],
+ [
+ 0.055836,
+ "i"
+ ],
+ [
+ 0.080111,
+ "n"
+ ],
+ [
+ 0.135971,
+ "t"
+ ],
+ [
+ 0.928127,
+ "\r\n"
+ ],
+ [
+ 0.039380,
+ "\u001b[?1049h\u001b[?1h\u001b="
+ ],
+ [
+ 0.001629,
+ "\u001b[1;28r\u001b[?12;25h\u001b[?12l\u001b[?25h\u001b[27m\u001b[m\u001b[H\u001b[2J\u001b[?25l\u001b[28;1H\".gitlint\""
+ ],
+ [
+ 0.000064,
+ " 41L, 1416C"
+ ],
+ [
+ 0.003242,
+ "\u001b[\u003ec"
+ ],
+ [
+ 0.007250,
+ "\u001b[1;1H\u001b[93m 1 \u001b[m\u001b[96m# All these sections are optional, edit this file as you like.\u001b[m\r\n\u001b[93m 2 \u001b[m\u001b[96m# [general]\u001b[m\r\n\u001b[93m 3 \u001b[m\u001b[96m# ignore=title-trailing-punctuation, T3\u001b[m\r\n\u001b[93m 4 \u001b[m\u001b[96m# verbosity should be a value between 1 and 3, the commandline -v flags take pre\u001b[m\u001b[97m\u001b[101mcedence over\u001b[m\r\n\u001b[93m 5 \u001b[m\u001b[96m# this\u001b[m\r\n\u001b[93m 6 \u001b[m\u001b[96m# verbosity = 2\u001b[m\r\n\u001b[93m 7 \r\n 8 \u001b[m\u001b[96m# [title-max-length]\u001b[m\r\n\u001b[93m 9 \u001b[m\u001b[96m# line-length=80\u001b[m\r\n\u001b[93m 10 \r\n 11 \u001b[m\u001b[96m# [title-must-not-contain-word]\u001b[m\r\n\u001b[93m 12 \u001b[m\u001b[96m# Comma-separated list of words that should not occur in the title. Matching is \u001b[m\u001b[97m\u001b[101mcase\u001b[m\r\n\u001b[93m 13 \u001b[m\u001b[96m# insensitive. It's fine if the keyword occurs as part of a larger word (so \"WIP\u001b[m\u001b[97m\u001b[101mING\"\u001b[m\r\n\u001b[93m 14 \u001b[m\u001b[96m# will not cause a violation, but \"WIP: my title\" will.\u001b[m\r\n\u001b[93m 15 \u001b[m\u001b[96m# words=wip\u001b[m\r\n\u001b[93m 16 \r\n 17 \u001b[m\u001b[96m# [title-match-regex]\u001b[m\r\n\u001b[93m 18 \u001b[m\u001b[96m# python like regex (https://docs.python.org/2/library/re.html) that the\u001b[m\r\n\u001b[93m 19 "
+ ],
+ [
+ 0.000011,
+ "\u001b[m\u001b[96m# commit-msg title must be matched to.\u001b[m\r\n\u001b[93m 20 \u001b[m\u001b[96m# Note that the regex can contradict with other rules if not used correctly\u001b[m\r\n\u001b[93m 21 \u001b[m\u001b[96m# (e.g. title-must-not-contain-word).\u001b[m\r\n\u001b[93m 22 \u001b[m\u001b[96m# regex=^US[0-9]*\u001b[m\r\n\u001b[93m 23 \r\n 24 \u001b[m\u001b[96m# [B1]\u001b[m\r\n\u001b[93m 25 \u001b[m\u001b[96m# B1 = body-max-line-length\u001b[m\r\n\u001b[93m 26 \u001b[m\u001b[96m# line-length=120\u001b[m\r\n\u001b[93m 27 \u001b[1;5H\u001b[?12l\u001b[?25h"
+ ],
+ [
+ 1.532701,
+ "\r\n 2 "
+ ],
+ [
+ 0.104014,
+ "\r\n 3 "
+ ],
+ [
+ 0.191728,
+ "\r\n 4 "
+ ],
+ [
+ 0.135939,
+ "\r\n 5 "
+ ],
+ [
+ 0.144151,
+ "\r\n 6 "
+ ],
+ [
+ 0.151956,
+ "\r\n 7 "
+ ],
+ [
+ 0.143897,
+ "\r\n 8 "
+ ],
+ [
+ 0.424058,
+ "\u001b[?25l\u0008 \u001b[m [title-max-length]\u001b[8;24H\u001b[K\u001b[8;5H\u001b[?12l\u001b[?25h"
+ ],
+ [
+ 0.160610,
+ "\u001b[?25l\u0008\u001b[93m \u001b[m\u001b[46m[\u001b[mtitle-max-length\u001b[46m]\u001b[m\u001b[8;23H\u001b[K\u001b[8;5H\u001b[?12l\u001b[?25h"
+ ],
+ [
+ 0.192102,
+ "\u001b[?25l[\u001b[16C]\u001b[9;5H\u001b[?12l\u001b[?25h"
+ ],
+ [
+ 0.231348,
+ "\u001b[?25l\u0008\u001b[93m \u001b[m line-length=80\u001b[9;20H\u001b[K\u001b[9;5H\u001b[?12l\u001b[?25h"
+ ],
+ [
+ 0.144198,
+ "\u001b[?25l\u0008\u001b[93m \u001b[mline-length=80\u001b[9;19H\u001b[K\u001b[9;5H\u001b[?12l\u001b[?25h"
+ ],
+ [
+ 0.552150,
+ "\u001b[?25l\u001b[28;1H\u001b[1m-- INSERT --\u001b[m\u001b[28;13H\u001b[K\u001b[9;5H\u001b[?12l\u001b[?25h"
+ ],
+ [
+ 0.303680,
+ "l"
+ ],
+ [
+ 0.201138,
+ "i"
+ ],
+ [
+ 0.017440,
+ "n"
+ ],
+ [
+ 0.017353,
+ "e"
+ ],
+ [
+ 0.016784,
+ "-"
+ ],
+ [
+ 0.017813,
+ "l"
+ ],
+ [
+ 0.017864,
+ "e"
+ ],
+ [
+ 0.017036,
+ "n"
+ ],
+ [
+ 0.017743,
+ "g"
+ ],
+ [
+ 0.017214,
+ "t"
+ ],
+ [
+ 0.017098,
+ "h"
+ ],
+ [
+ 0.018114,
+ "="
+ ],
+ [
+ 0.017698,
+ "8"
+ ],
+ [
+ 0.015624,
+ "0"
+ ],
+ [
+ 0.391058,
+ "\u0008"
+ ],
+ [
+ 0.320130,
+ "\u001b[?25l\u0008\u0008=0\u001b[9;18H\u001b[K\u001b[9;17H\u001b[?12l\u001b[?25h"
+ ],
+ [
+ 0.271868,
+ "\u001b[?25l\u0008=50\u0008\u001b[?12l\u001b[?25h"
+ ],
+ [
+ 0.581296,
+ "\u001b[28;1H\u001b[K\u001b[9;17H"
+ ],
+ [
+ 0.242328,
+ "\u001b[?25l"
+ ],
+ [
+ 0.000209,
+ "\u001b[?12l\u001b[?25h\u001b[?25l\u001b[28;1H:"
+ ],
+ [
+ 0.000006,
+ "\u001b[?12l\u001b[?25h"
+ ],
+ [
+ 0.199592,
+ "w"
+ ],
+ [
+ 0.048010,
+ "q"
+ ],
+ [
+ 1.080364,
+ "\r"
+ ],
+ [
+ 0.000041,
+ "\u001b[?25l"
+ ],
+ [
+ 0.000082,
+ "\".gitlint\""
+ ],
+ [
+ 0.001253,
+ " 41L, 1412C written"
+ ],
+ [
+ 0.001495,
+ "\r\r\r\n\u001b[?1l\u001b\u003e\u001b[?12l\u001b[?25h\u001b[?1049l"
+ ],
+ [
+ 0.000815,
+ "bash-3.2$ "
+ ],
+ [
+ 1.491944,
+ "g"
+ ],
+ [
+ 0.071961,
+ "i"
+ ],
+ [
+ 0.160254,
+ "t"
+ ],
+ [
+ 0.128030,
+ "l"
+ ],
+ [
+ 0.071789,
+ "i"
+ ],
+ [
+ 0.055927,
+ "n"
+ ],
+ [
+ 0.127907,
+ "t"
+ ],
+ [
+ 0.728389,
+ "\r\n"
+ ],
+ [
+ 0.053628,
+ "Using config from /Users/jroovers/my-git-repo/.gitlint\r\n"
+ ],
+ [
+ 0.050694,
+ "1: T1 Title exceeds max length (60\u003e50): \"WIP: This is an patchset that I need to continue working on!\"\r\n"
+ ],
+ [
+ 0.000006,
+ "1: T3 Title has trailing punctuation (!): \"WIP: This is an patchset that I need to continue working on!\"\r\n1: T5 Title contains the word 'WIP' (case-insensitive): \"WIP: This is an patchset that I need to continue working on!\"\r\n3: B6 Body message is missing\r\n"
+ ],
+ [
+ 0.005418,
+ "bash-3.2$ "
+ ],
+ [
+ 2.577825,
+ "#"
+ ],
+ [
+ 0.264000,
+ " "
+ ],
+ [
+ 1.095576,
+ "O"
+ ],
+ [
+ 0.205521,
+ "r"
+ ],
+ [
+ 0.083054,
+ " "
+ ],
+ [
+ 0.127713,
+ "s"
+ ],
+ [
+ 0.096301,
+ "p"
+ ],
+ [
+ 0.079687,
+ "e"
+ ],
+ [
+ 0.088075,
+ "c"
+ ],
+ [
+ 0.087991,
+ "i"
+ ],
+ [
+ 0.144246,
+ "f"
+ ],
+ [
+ 0.839973,
+ "y"
+ ],
+ [
+ 0.392068,
+ " "
+ ],
+ [
+ 0.487898,
+ "a"
+ ],
+ [
+ 0.208003,
+ "d"
+ ],
+ [
+ 0.135717,
+ "d"
+ ],
+ [
+ 0.079782,
+ "i"
+ ],
+ [
+ 0.151837,
+ "t"
+ ],
+ [
+ 0.096448,
+ "i"
+ ],
+ [
+ 0.079993,
+ "o"
+ ],
+ [
+ 0.000349,
+ "n"
+ ],
+ [
+ 0.135585,
+ "a"
+ ],
+ [
+ 0.095980,
+ "l"
+ ],
+ [
+ 0.151930,
+ " "
+ ],
+ [
+ 0.151950,
+ "c"
+ ],
+ [
+ 0.079947,
+ "o"
+ ],
+ [
+ 0.032040,
+ "n"
+ ],
+ [
+ 0.103990,
+ "f"
+ ],
+ [
+ 0.112311,
+ "i"
+ ],
+ [
+ 0.127670,
+ "g"
+ ],
+ [
+ 0.191958,
+ " "
+ ],
+ [
+ 0.335974,
+ "v"
+ ],
+ [
+ 0.072137,
+ "i"
+ ],
+ [
+ 0.127902,
+ "a"
+ ],
+ [
+ 0.103834,
+ " "
+ ],
+ [
+ 0.168232,
+ "t"
+ ],
+ [
+ 0.112211,
+ "h"
+ ],
+ [
+ 0.095730,
+ "e"
+ ],
+ [
+ 0.112047,
+ " "
+ ],
+ [
+ 0.087745,
+ "c"
+ ],
+ [
+ 0.063982,
+ "o"
+ ],
+ [
+ 0.368225,
+ "m"
+ ],
+ [
+ 0.168146,
+ "m"
+ ],
+ [
+ 0.063823,
+ "a"
+ ],
+ [
+ 0.112252,
+ "n"
+ ],
+ [
+ 0.087711,
+ "d"
+ ],
+ [
+ 0.112231,
+ "l"
+ ],
+ [
+ 0.079753,
+ "i"
+ ],
+ [
+ 0.056014,
+ "n"
+ ],
+ [
+ 0.111900,
+ "e"
+ ],
+ [
+ 1.128086,
+ "\r\n"
+ ],
+ [
+ 0.000116,
+ "bash-3.2$ "
+ ],
+ [
+ 1.096057,
+ "g"
+ ],
+ [
+ 0.063721,
+ "i"
+ ],
+ [
+ 0.151557,
+ "t"
+ ],
+ [
+ 0.288291,
+ "l"
+ ],
+ [
+ 0.040064,
+ "i"
+ ],
+ [
+ 0.063972,
+ "n"
+ ],
+ [
+ 0.119883,
+ "t"
+ ],
+ [
+ 0.192140,
+ " "
+ ],
+ [
+ 0.383892,
+ "-"
+ ],
+ [
+ 0.143814,
+ "-"
+ ],
+ [
+ 0.200589,
+ "i"
+ ],
+ [
+ 0.063787,
+ "g"
+ ],
+ [
+ 0.151539,
+ "n"
+ ],
+ [
+ 0.112696,
+ "o"
+ ],
+ [
+ 0.095761,
+ "r"
+ ],
+ [
+ 0.056248,
+ "e"
+ ],
+ [
+ 0.471314,
+ " "
+ ],
+ [
+ 0.496411,
+ "t"
+ ],
+ [
+ 0.032231,
+ "i"
+ ],
+ [
+ 0.775702,
+ "t"
+ ],
+ [
+ 0.071997,
+ "l"
+ ],
+ [
+ 0.119928,
+ "e"
+ ],
+ [
+ 0.152044,
+ "-"
+ ],
+ [
+ 0.192289,
+ "t"
+ ],
+ [
+ 0.168098,
+ "r"
+ ],
+ [
+ 0.095641,
+ "a"
+ ],
+ [
+ 0.079916,
+ "i"
+ ],
+ [
+ 0.088017,
+ "l"
+ ],
+ [
+ 0.208343,
+ "i"
+ ],
+ [
+ 0.087674,
+ "n"
+ ],
+ [
+ 0.192216,
+ "g"
+ ],
+ [
+ 0.463349,
+ "-"
+ ],
+ [
+ 0.224422,
+ "p"
+ ],
+ [
+ 0.303974,
+ "u"
+ ],
+ [
+ 0.071948,
+ "n"
+ ],
+ [
+ 0.472005,
+ "c"
+ ],
+ [
+ 0.368016,
+ "t"
+ ],
+ [
+ 0.303934,
+ "u"
+ ],
+ [
+ 0.112267,
+ "a"
+ ],
+ [
+ 0.087621,
+ "t"
+ ],
+ [
+ 0.080151,
+ "i"
+ ],
+ [
+ 0.048003,
+ "o"
+ ],
+ [
+ 0.031962,
+ "n"
+ ],
+ [
+ 1.887520,
+ "\r\n"
+ ],
+ [
+ 0.052100,
+ "Using config from /Users/jroovers/my-git-repo/.gitlint\r\n"
+ ],
+ [
+ 0.050989,
+ "1: T1 Title exceeds max length (60\u003e50): \"WIP: This is an patchset that I need to continue working on!\"\r\n1: T5 Title contains the word 'WIP' (case-insensitive): \"WIP: This is an patchset that I need to continue working on!\"\r\n"
+ ],
+ [
+ 0.000025,
+ "3: B6 Body message is missing\r\n"
+ ],
+ [
+ 0.006495,
+ "bash-3.2$ "
+ ],
+ [
+ 1.578501,
+ "#"
+ ],
+ [
+ 0.177781,
+ " "
+ ],
+ [
+ 0.222470,
+ "F"
+ ],
+ [
+ 0.088284,
+ "o"
+ ],
+ [
+ 0.127955,
+ "r"
+ ],
+ [
+ 0.056062,
+ " "
+ ],
+ [
+ 0.144004,
+ "m"
+ ],
+ [
+ 0.095681,
+ "o"
+ ],
+ [
+ 0.032018,
+ "r"
+ ],
+ [
+ 0.047994,
+ "e"
+ ],
+ [
+ 0.096045,
+ " "
+ ],
+ [
+ 0.111871,
+ "i"
+ ],
+ [
+ 0.071986,
+ "n"
+ ],
+ [
+ 0.056142,
+ "f"
+ ],
+ [
+ 0.095939,
+ "o"
+ ],
+ [
+ 0.279967,
+ ","
+ ],
+ [
+ 0.087962,
+ " "
+ ],
+ [
+ 0.175948,
+ "v"
+ ],
+ [
+ 0.072089,
+ "i"
+ ],
+ [
+ 0.144243,
+ "s"
+ ],
+ [
+ 0.031668,
+ "i"
+ ],
+ [
+ 0.232173,
+ "t"
+ ],
+ [
+ 0.143995,
+ ":"
+ ],
+ [
+ 0.200215,
+ " "
+ ],
+ [
+ 0.359698,
+ "h"
+ ],
+ [
+ 0.127942,
+ "t"
+ ],
+ [
+ 0.151997,
+ "t"
+ ],
+ [
+ 0.048065,
+ "p"
+ ],
+ [
+ 0.319959,
+ ":"
+ ],
+ [
+ 0.256283,
+ "/"
+ ],
+ [
+ 0.143558,
+ "/"
+ ],
+ [
+ 0.487848,
+ "j"
+ ],
+ [
+ 0.048256,
+ "o"
+ ],
+ [
+ 0.079996,
+ "r"
+ ],
+ [
+ 0.104020,
+ "i"
+ ],
+ [
+ 0.095905,
+ "s"
+ ],
+ [
+ 0.240093,
+ "r"
+ ],
+ [
+ 0.136044,
+ "o"
+ ],
+ [
+ 0.127483,
+ "o"
+ ],
+ [
+ 0.072697,
+ "v"
+ ],
+ [
+ 0.103625,
+ "e"
+ ],
+ [
+ 0.088072,
+ "r"
+ ],
+ [
+ 0.112033,
+ "s"
+ ],
+ [
+ 0.143951,
+ "."
+ ],
+ [
+ 0.648188,
+ "g"
+ ],
+ [
+ 0.279829,
+ "i"
+ ],
+ [
+ 0.463949,
+ "t"
+ ],
+ [
+ 0.079922,
+ "h"
+ ],
+ [
+ 0.120064,
+ "u"
+ ],
+ [
+ 0.080043,
+ "b"
+ ],
+ [
+ 0.231966,
+ "."
+ ],
+ [
+ 0.239964,
+ "i"
+ ],
+ [
+ 0.056111,
+ "o"
+ ],
+ [
+ 0.303921,
+ "/"
+ ],
+ [
+ 0.367976,
+ "g"
+ ],
+ [
+ 0.055984,
+ "i"
+ ],
+ [
+ 0.135983,
+ "t"
+ ],
+ [
+ 0.104035,
+ "l"
+ ],
+ [
+ 0.056048,
+ "i"
+ ],
+ [
+ 0.072242,
+ "n"
+ ],
+ [
+ 0.111889,
+ "t"
+ ],
+ [
+ 0.439701,
+ "\r\n"
+ ],
+ [
+ 0.000100,
+ "bash-3.2$ "
+ ],
+ [
+ 0.919921,
+ "e"
+ ],
+ [
+ 0.176231,
+ "x"
+ ],
+ [
+ 0.119224,
+ "i"
+ ],
+ [
+ 0.104616,
+ "t"
+ ],
+ [
+ 1.008087,
+ "\r\n"
+ ],
+ [
+ 0.000129,
+ "exit\r\n"
+ ]
+ ]
+}
diff --git a/docs/demos/scenario.txt b/docs/demos/scenario.txt
new file mode 100644
index 0000000..7a4b692
--- /dev/null
+++ b/docs/demos/scenario.txt
@@ -0,0 +1,75 @@
+sudo pip uninstall gitlint
+
+virtualenv ~/gitlint-demo
+
+source ~/gitlint-demo
+
+mkdir ~/my-git-repo
+
+git init
+
+echo "test" > myfile.txt
+
+git add .
+
+git commit
+
+WIP: This is a commit message title.
+Second line not empty
+This body line exceeds the defacto standard length of 80 characters per line in a commit m
+essage.
+
+cd ..
+
+
+asciicinema rec demo.json
+
+------------------------------------
+
+pip install gitlint
+
+# Go to your git repo
+
+cd my-git-repo
+
+# Run gitlint to check for violations in the last commit message
+
+gitlint
+
+# For reference, here you can see that last commit message
+
+git log -1
+
+# You can also install gitlint as a git commit-msg hook
+
+gitlint install-hook
+
+# Let's try it out
+
+echo "This is a test" > foo.txt
+
+git add .
+
+git commit
+
+WIP: Still working on this awesome patchset that will change the world forever!
+
+[Keep commit -> yes]
+
+# You can modify gitlint's behavior by adding a .gitlint file
+
+gitlint generate-config
+
+vim .gitlint
+
+gitlint
+
+# Or specify additional config via the commandline
+
+gitlint --ignore title-trailing-punctuation
+
+# For more info, visit: http://jorisroovers.github.io/gitlint
+
+exit
+
+------------------------------ \ No newline at end of file
diff --git a/docs/extra.css b/docs/extra.css
new file mode 100644
index 0000000..5643925
--- /dev/null
+++ b/docs/extra.css
@@ -0,0 +1,4 @@
+a.toctree-l3 {
+ margin-left: 10px;
+ /* display: none; */
+}
diff --git a/docs/images/RuleViolation.png b/docs/images/RuleViolation.png
new file mode 100644
index 0000000..410dca9
--- /dev/null
+++ b/docs/images/RuleViolation.png
Binary files differ
diff --git a/docs/images/RuleViolations.graffle b/docs/images/RuleViolations.graffle
new file mode 100644
index 0000000..1fea2dd
--- /dev/null
+++ b/docs/images/RuleViolations.graffle
Binary files differ
diff --git a/docs/index.md b/docs/index.md
new file mode 100644
index 0000000..3155b19
--- /dev/null
+++ b/docs/index.md
@@ -0,0 +1,351 @@
+# Intro
+Gitlint is a git commit message linter written in python: it checks your commit messages for style.
+
+Great for use as a [commit-msg git hook](#using-gitlint-as-a-commit-msg-hook) or as part of your gating script in a
+[CI pipeline (e.g. Jenkins)](index.md#using-gitlint-in-a-ci-environment).
+
+<script type="text/javascript" src="https://asciinema.org/a/30477.js" id="asciicast-30477" async></script>
+
+!!! note
+ **Gitlint support for Windows is experimental**, and [there are some known issues](https://github.com/jorisroovers/gitlint/issues?q=is%3Aissue+is%3Aopen+label%3Awindows).
+
+ Also, gitlint is not the only git commit message linter out there, if you are looking for an alternative written in a different language,
+ have a look at [fit-commit](https://github.com/m1foley/fit-commit) (Ruby),
+ [node-commit-msg](https://github.com/clns/node-commit-msg) (Node.js) or [commitlint](http://marionebl.github.io/commitlint) (Node.js).
+
+## Features ##
+ - **Commit message hook**: [Auto-trigger validations against new commit message right when you're committing](#using-gitlint-as-a-commit-msg-hook). Also [works with pre-commit](#using-gitlint-through-pre-commit).
+ - **Easily integrated**: Gitlint is designed to work [with your own scripts or CI system](#using-gitlint-in-a-ci-environment).
+ - **Sane defaults:** Many of gitlint's validations are based on
+[well-known](http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html),
+[community](http://addamhardy.com/2013/06/05/good-commit-messages-and-enforcing-them-with-git-hooks.html),
+[standards](http://chris.beams.io/posts/git-commit/), others are based on checks that we've found
+useful throughout the years.
+ - **Easily configurable:** Gitlint has sane defaults, but [you can also easily customize it to your own liking](configuration.md).
+ - **Community contributed rules**: Conventions that are common but not universal [can be selectively enabled](contrib_rules).
+ - **User-defined rules:** Want to do more then what gitlint offers out of the box? Write your own [user defined rules](user_defined_rules.md).
+ - **Broad python version support:** Gitlint supports python versions 2.7, 3.5+, PyPy2 and PyPy3.5.
+ - **Full unicode support:** Lint your Russian, Chinese or Emoji commit messages with ease!
+ - **Production-ready:** Gitlint checks a lot of the boxes you're looking for: actively maintained, high unit test coverage, integration tests,
+ python code standards (pep8, pylint), good documentation, widely used, proven track record.
+
+# Getting Started
+## Installation
+```bash
+# Pip is recommended to install the latest version
+pip install gitlint
+
+# macOS
+brew tap rockyluke/devops
+brew install gitlint
+
+# Ubuntu
+apt-get install gitlint
+
+# Docker: https://hub.docker.com/r/jorisroovers/gitlint
+docker run -v $(pwd):/repo jorisroovers/gitlint
+```
+
+## Usage
+```sh
+# Check the last commit message
+gitlint
+# Alternatively, pipe a commit message to gitlint:
+cat examples/commit-message-1 | gitlint
+# or
+git log -1 --pretty=%B | gitlint
+# Or read the commit-msg from a file, like so:
+gitlint --msg-filename examples/commit-message-2
+# Lint all commits in your repo
+gitlint --commits HEAD
+
+# To install a gitlint as a commit-msg git hook:
+gitlint install-hook
+```
+
+Output example:
+```bash
+$ cat examples/commit-message-2 | gitlint
+1: T1 Title exceeds max length (134>80): "This is the title of a commit message that is over 80 characters and contains hard tabs and trailing whitespace and the word wiping "
+1: T2 Title has trailing whitespace: "This is the title of a commit message that is over 80 characters and contains hard tabs and trailing whitespace and the word wiping "
+1: T4 Title contains hard tab characters (\t): "This is the title of a commit message that is over 80 characters and contains hard tabs and trailing whitespace and the word wiping "
+2: B4 Second line is not empty: "This line should not contain text"
+3: B1 Line exceeds max length (125>80): "Lines typically need to have a max length, meaning that they can't exceed a preset number of characters, usually 80 or 120. "
+3: B2 Line has trailing whitespace: "Lines typically need to have a max length, meaning that they can't exceed a preset number of characters, usually 80 or 120. "
+3: B3 Line contains hard tab characters (\t): "Lines typically need to have a max length, meaning that they can't exceed a preset number of characters, usually 80 or 120. "
+```
+!!! note
+ The returned exit code equals the number of errors found. [Some exit codes are special](index.md#exit-codes).
+
+# Configuration
+
+For in-depth documentation of general and rule-specific configuration options, have a look at the [Configuration](configuration.md) and [Rules](rules.md) pages.
+
+Short example ```.gitlint``` file ([full reference](configuration.md)):
+
+```ini
+[general]
+# Ignore certain rules (comma-separated list), you can reference them by
+# their id or by their full name
+ignore=body-is-missing,T3
+
+# Ignore any data send to gitlint via stdin
+ignore-stdin=true
+
+# Configure title-max-length rule, set title length to 80 (72 = default)
+[title-max-length]
+line-length=80
+
+# You can also reference rules by their id (B1 = body-max-line-length)
+[B1]
+line-length=123
+```
+
+Example use of flags:
+
+```bash
+# Change gitlint's verbosity.
+$ gitlint -v
+# Ignore certain rules
+$ gitlint --ignore body-is-missing,T3
+# Enable debug mode
+$ gitlint --debug
+# Load user-defined rules (see http://jorisroovers.github.io/gitlint/user_defined_rules)
+$ gitlint --extra-path /home/joe/mygitlint_rules
+```
+
+Other commands and variations:
+
+```no-highlight
+$ gitlint --help
+Usage: gitlint [OPTIONS] COMMAND [ARGS]...
+
+ Git lint tool, checks your git commit messages for styling issues
+
+ Documentation: http://jorisroovers.github.io/gitlint
+
+Options:
+ --target DIRECTORY Path of the target git repository. [default:
+ current working directory]
+ -C, --config FILE Config file location [default: .gitlint]
+ -c TEXT Config flags in format <rule>.<option>=<value>
+ (e.g.: -c T1.line-length=80). Flag can be used
+ multiple times to set multiple config values.
+ --commits TEXT The range of commits to lint. [default: HEAD]
+ -e, --extra-path PATH Path to a directory or python module with extra
+ user-defined rules
+ --ignore TEXT Ignore rules (comma-separated by id or name).
+ --contrib TEXT Contrib rules to enable (comma-separated by id or
+ name).
+ --msg-filename FILENAME Path to a file containing a commit-msg.
+ --ignore-stdin Ignore any stdin data. Useful for running in CI
+ server.
+ --staged Read staged commit meta-info from the local
+ repository.
+ -v, --verbose Verbosity, more v's for more verbose output (e.g.:
+ -v, -vv, -vvv). [default: -vvv]
+ -s, --silent Silent mode (no output). Takes precedence over -v,
+ -vv, -vvv.
+ -d, --debug Enable debugging output.
+ --version Show the version and exit.
+ --help Show this message and exit.
+
+Commands:
+ generate-config Generates a sample gitlint config file.
+ install-hook Install gitlint as a git commit-msg hook.
+ lint Lints a git repository [default command]
+ uninstall-hook Uninstall gitlint commit-msg hook.
+
+ When no COMMAND is specified, gitlint defaults to 'gitlint lint'.
+```
+
+
+# Using gitlint as a commit-msg hook ##
+_Introduced in gitlint v0.4.0_
+
+You can also install gitlint as a git ```commit-msg``` hook so that gitlint checks your commit messages automatically
+after each commit.
+
+```bash
+gitlint install-hook
+# To remove the hook
+gitlint uninstall-hook
+```
+
+!!! important
+
+ Gitlint cannot work together with an existing hook. If you already have a ```.git/hooks/commit-msg```
+ file in your local repository, gitlint will refuse to install the ```commit-msg``` hook. Gitlint will also only
+ uninstall unmodified commit-msg hooks that were installed by gitlint.
+ If you're looking to use gitlint in conjunction with other hooks, you should consider
+ [using gitlint with pre-commit](#using-gitlint-through-pre-commit).
+
+# Using gitlint through [pre-commit](https://pre-commit.com)
+
+`gitlint` can be configured as a plugin for the `pre-commit` git hooks
+framework. Simply add the configuration to your `.pre-commit-config.yaml`:
+
+```yaml
+- repo: https://github.com/jorisroovers/gitlint
+ rev: # Fill in a tag / sha here
+ hooks:
+ - id: gitlint
+```
+
+You then need to install the pre-commit hook like so:
+```sh
+pre-commit install --hook-type commit-msg
+```
+!!! important
+
+ It's important that you run ```pre-commit install --hook-type commit-msg```, even if you've already used
+ ```pre-commit install``` before. ```pre-commit install``` does **not** install commit-msg hooks by default!
+
+To manually trigger gitlint using ```pre-commit``` for your last commit message, use the following command:
+```sh
+pre-commit run gitlint --hook-stage commit-msg --commit-msg-filename .git/COMMIT_EDITMSG
+```
+
+In case you want to change gitlint's behavior, you should either use a `.gitlint` file
+(see [Configuration](configuration.md)) or modify the gitlint invocation in
+your `.pre-commit-config.yaml` file like so:
+```yaml
+- repo: https://github.com/jorisroovers/gitlint
+ rev: # Fill in a tag / sha here
+ hooks:
+ - id: gitlint
+ stages: [commit-msg]
+ entry: gitlint
+ args: [--contrib=CT1, --msg-filename]
+```
+
+# Using gitlint in a CI environment ##
+By default, when just running ```gitlint``` without additional parameters, gitlint lints the last commit in the current
+working directory.
+
+This makes it easy to use gitlint in a CI environment (Jenkins, TravisCI, Github Actions, pre-commit, CircleCI, Gitlab, etc).
+In fact, this is exactly what we do ourselves: on every commit,
+[we run gitlint as part of our CI checks](https://github.com/jorisroovers/gitlint/blob/v0.12.0/run_tests.sh#L133-L134).
+This will cause the build to fail when we submit a bad commit message.
+
+Alternatively, gitlint will also lint any commit message that you feed it via stdin like so:
+```bash
+# lint the last commit message
+git log -1 --pretty=%B | gitlint
+# lint a specific commit: 62c0519
+git log -1 --pretty=%B 62c0519 | gitlint
+```
+Note that gitlint requires that you specify ```--pretty=%B``` (=only print the log message, not the metadata),
+future versions of gitlint might fix this and not require the ```--pretty``` argument.
+
+## Linting a range of commits ##
+
+_Introduced in gitlint v0.9.0 (experimental in v0.8.0)_
+
+Gitlint allows users to commit a number of commits at once like so:
+
+```bash
+# Lint a specific commit range:
+gitlint --commits "019cf40...d6bc75a"
+# You can also use git's special references:
+gitlint --commits "origin..HEAD"
+# Or specify a single specific commit in refspec format, like so:
+gitlint --commits "019cf40^...019cf40"
+```
+
+The ```--commits``` flag takes a **single** refspec argument or commit range. Basically, any range that is understood
+by [git rev-list](https://git-scm.com/docs/git-rev-list) as a single argument will work.
+
+Prior to v0.8.1 gitlint didn't support this feature. However, older versions of gitlint can still lint a range or set
+of commits at once by creating a simple bash script that pipes the commit messages one by one into gitlint. This
+approach can still be used with newer versions of gitlint in case ```--commits``` doesn't provide the flexibility you
+are looking for.
+
+```bash
+#!/bin/bash
+
+for commit in $(git rev-list master); do
+ commit_msg=$(git log -1 --pretty=%B $commit)
+ echo "$commit"
+ echo "$commit_msg" | gitlint
+ echo "--------"
+done
+```
+
+!!! note
+ One downside to this approach is that you invoke gitlint once per commit vs. once per set of commits.
+ This means you'll incur the gitlint startup time once per commit, making this approach rather slow if you want to
+ lint a large set of commits. Always use ```--commits``` if you can to avoid this performance penalty.
+
+
+# Merge, fixup and squash commits ##
+_Introduced in gitlint v0.7.0 (merge), v0.9.0 (fixup, squash) and v0.13.0 (revert)_
+
+**Gitlint ignores merge, revert, fixup and squash commits by default.**
+
+For merge and revert commits, the rationale for ignoring them is
+that most users keep git's default messages for these commits (i.e *Merge/Revert "[original commit message]"*).
+Often times these commit messages are also auto-generated through tools like github.
+These default/auto-generated commit messages tend to cause gitlint violations.
+For example, a common case is that *"Merge:"* being auto-prepended triggers a
+[title-max-length](rules.md#t1-title-max-length) violation. Most users don't want this, so we disable linting
+on Merge and Revert commits by default.
+
+For [squash](https://git-scm.com/docs/git-commit#git-commit---squashltcommitgt) and [fixup](https://git-scm.com/docs/git-commit#git-commit---fixupltcommitgt) commits, the rationale is that these are temporary
+commits that will be squashed into a different commit, and hence the commit messages for these commits are very
+short-lived and not intended to make it into the final commit history. In addition, by prepending *"fixup!"* or
+*"squash!"* to your commit message, certain gitlint rules might be violated
+(e.g. [title-max-length](rules.md#t1-title-max-length)) which is often undesirable.
+
+In case you *do* want to lint these commit messages, you can disable this behavior by setting the
+general ```ignore-merge-commits```, ```ignore-revert-commits```, ```ignore-fixup-commits``` or
+```ignore-squash-commits``` option to ```false```
+[using one of the various ways to configure gitlint](configuration.md).
+
+# Ignoring commits ##
+_Introduced in gitlint v0.10.0_
+
+You can configure gitlint to ignore specific commits.
+
+One way to do this, is to by [adding a gitline-ignore line to your commit message](configuration.md#commit-specific-config).
+
+If you have a case where you want to ignore a certain type of commits all-together, you can
+use gitlint's *ignore* rules.
+Here's an example gitlint file that configures gitlint to ignore rules ```title-max-length``` and ```body-min-length```
+for all commits with a title starting with *"Release"*.
+
+```ini
+[ignore-by-title]
+# Match commit titles starting with Release
+regex=^Release(.*)
+ignore=title-max-length,body-min-length
+# ignore all rules by setting ignore to 'all'
+# ignore=all
+
+[ignore-by-body]
+# Match commits message bodies that have a line that contains 'release'
+regex=(.*)release(.*)
+ignore=all
+```
+
+!!! note
+
+ Right now it's not possible to write user-defined ignore rules to handle more complex use-cases.
+ This is however something that we'd like to implement in a future version. If this is something you're interested in
+ please let us know by [opening an issue](https://github.com/jorisroovers/gitlint/issues).
+
+# Exit codes ##
+Gitlint uses the exit code as a simple way to indicate the number of violations found.
+Some exit codes are used to indicate special errors as indicated in the table below.
+
+Because of these special error codes and the fact that
+[bash only supports exit codes between 0 and 255](http://tldp.org/LDP/abs/html/exitcodes.html), the maximum number
+of violations counted by the exit code is 252. Note that gitlint does not have a limit on the number of violations
+it can detect, it will just always return with exit code 252 when the number of violations is greater than or equal
+to 252.
+
+Exit Code | Description
+-----------|------------------------------------------------------------
+253 | Wrong invocation of the ```gitlint``` command.
+254 | Something went wrong when invoking git.
+255 | Invalid gitlint configuration
diff --git a/docs/rules.md b/docs/rules.md
new file mode 100644
index 0000000..173c5b1
--- /dev/null
+++ b/docs/rules.md
@@ -0,0 +1,243 @@
+# Overview #
+
+The table below shows an overview of all gitlint's built-in rules.
+Note that you can also [write your own user-defined rule](user_defined_rules.md) in case you don't find
+what you're looking for.
+The rest of this page contains details on the available configuration options for each built-in rule.
+
+ID | Name | gitlint version | Description
+------|-----------------------------|-------------------|-------------------------------------------
+T1 | title-max-length | >= 0.1.0 | Title length must be &lt; 72 chars.
+T2 | title-trailing-whitespace | >= 0.1.0 | Title cannot have trailing whitespace (space or tab)
+T3 | title-trailing-punctuation | >= 0.1.0 | Title cannot have trailing punctuation (?:!.,;)
+T4 | title-hard-tab | >= 0.1.0 | Title cannot contain hard tab characters (\t)
+T5 | title-must-not-contain-word | >= 0.1.0 | Title cannot contain certain words (default: "WIP")
+T6 | title-leading-whitespace | >= 0.4.0 | Title cannot have leading whitespace (space or tab)
+T7 | title-match-regex | >= 0.5.0 | Title must match a given regex (default: .*)
+B1 | body-max-line-length | >= 0.1.0 | Lines in the body must be &lt; 80 chars
+B2 | body-trailing-whitespace | >= 0.1.0 | Body cannot have trailing whitespace (space or tab)
+B3 | body-hard-tab | >= 0.1.0 | Body cannot contain hard tab characters (\t)
+B4 | body-first-line-empty | >= 0.1.0 | First line of the body (second line of commit message) must be empty
+B5 | body-min-length | >= 0.4.0 | Body length must be at least 20 characters
+B6 | body-is-missing | >= 0.4.0 | Body message must be specified
+B7 | body-changed-file-mention | >= 0.4.0 | Body must contain references to certain files if those files are changed in the last commit
+M1 | author-valid-email | >= 0.9.0 | Author email address must be a valid email address
+I1 | ignore-by-title | >= 0.10.0 | Ignore a commit based on matching its title
+I2 | ignore-by-body | >= 0.10.0 | Ignore a commit based on matching its body
+
+## T1: title-max-length ##
+
+ID | Name | gitlint version | Description
+------|-----------------------------|-----------------|-------------------------------------------
+T1 | title-max-length | >= 0.1 | Title length must be &lt; 72 chars.
+
+### Options ###
+
+Name | gitlint version | Default | Description
+---------------|-----------------|---------|----------------------------------
+line-length | >= 0.2 | 72 | Maximum allowed title length
+
+## T2: title-trailing-whitespace ##
+
+ID | Name | gitlint version | Description
+------|-----------------------------|-----------------|-------------------------------------------
+T2 | title-trailing-whitespace | >= 0.1 | Title cannot have trailing whitespace (space or tab)
+
+
+## T3: title-trailing-punctuation ##
+
+ID | Name | gitlint version | Description
+------|-----------------------------|-----------------|-------------------------------------------
+T3 | title-trailing-punctuation | >= 0.1 | Title cannot have trailing punctuation (?:!.,;)
+
+
+## T4: title-hard-tab ##
+
+ID | Name | gitlint version | Description
+------|-----------------------------|-----------------|-------------------------------------------
+T4 | title-hard-tab | >= 0.1 | Title cannot contain hard tab characters (\t)
+
+
+## T5: title-must-not-contain-word ##
+
+ID | Name | gitlint version | Description
+------|-----------------------------|-----------------|-------------------------------------------
+T5 | title-must-not-contain-word | >= 0.1 | Title cannot contain certain words (default: "WIP")
+
+### Options ###
+
+Name | gitlint version | Default | Description
+---------------|-----------------|---------|----------------------------------
+words | >= 0.3 | WIP | Comma-separated list of words that should not be used in the title. Matching is case insensitive
+
+## T6: title-leading-whitespace ##
+
+ID | Name | gitlint version | Description
+------|-----------------------------|-----------------|-------------------------------------------
+T6 | title-leading-whitespace | >= 0.4 | Title cannot have leading whitespace (space or tab)
+
+## T7: title-match-regex ##
+
+ID | Name | gitlint version | Description
+------|-----------------------------|-----------------|-------------------------------------------
+T7 | title-match-regex | >= 0.5 | Title must match a given regex (default: .*)
+
+
+### Options ###
+
+Name | gitlint version | Default | Description
+---------------|-----------------|---------|----------------------------------
+regex | >= 0.5 | .* | [Python-style regular expression](https://docs.python.org/3.5/library/re.html) that the title should match.
+
+## B1: body-max-line-length ##
+
+ID | Name | gitlint version | Description
+------|-----------------------------|-----------------|-------------------------------------------
+B1 | body-max-line-length | >= 0.1 | Lines in the body must be &lt; 80 chars
+
+### Options ###
+
+Name | gitlint version | Default | Description
+---------------|-----------------|---------|----------------------------------
+line-length | >= 0.2 | 80 | Maximum allowed line length in the commit message body
+
+## B2: body-trailing-whitespace ##
+
+ID | Name | gitlint version | Description
+------|-----------------------------|-----------------|-------------------------------------------
+B2 | body-trailing-whitespace | >= 0.1 | Body cannot have trailing whitespace (space or tab)
+
+
+## B3: body-hard-tab ##
+
+ID | Name | gitlint version | Description
+------|-----------------------------|-----------------|-------------------------------------------
+B3 | body-hard-tab | >= 0.1 | Body cannot contain hard tab characters (\t)
+
+
+## B4: body-first-line-empty ##
+
+ID | Name | gitlint version | Description
+------|-----------------------------|-----------------|-------------------------------------------
+B4 | body-first-line-empty | >= 0.1 | First line of the body (second line of commit message) must be empty
+
+## B5: body-min-length ##
+
+ID | Name | gitlint version | Description
+------|-----------------------------|-----------------|-------------------------------------------
+B5 | body-min-length | >= 0.4 | Body length must be at least 20 characters. In versions >= 0.8.0, gitlint will not count newline characters.
+
+### Options ###
+
+Name | gitlint version | Default | Description
+---------------|-----------------|---------|----------------------------------
+min-length | >= 0.4 | 20 | Minimum number of required characters in body
+
+## B6: body-is-missing ##
+
+ID | Name | gitlint version | Description
+------|-----------------------------|-----------------|-------------------------------------------
+B6 | body-is-missing | >= 0.4 | Body message must be specified
+
+
+### Options ###
+
+Name | gitlint version | Default | Description
+----------------------|-----------------|-----------|----------------------------------
+ignore-merge-commits | >= 0.4 | true | Whether this rule should be ignored during merge commits. Allowed values: true,false.
+
+## B7: body-changed-file-mention ##
+
+ID | Name | gitlint version | Description
+------|-----------------------------|-----------------|-------------------------------------------
+B7 | body-changed-file-mention | >= 0.4 | Body must contain references to certain files if those files are changed in the last commit
+
+### Options ###
+
+Name | gitlint version | Default | Description
+----------------------|-----------------|--------------|----------------------------------
+files | >= 0.4 | (empty) | Comma-separated list of files that need to an explicit mention in the commit message in case they are changed.
+
+
+
+## M1: author-valid-email ##
+
+ID | Name | gitlint version | Description
+------|-----------------------------|-----------------|-------------------------------------------
+M1 | author-valid-email | >= 0.8.3 | Author email address must be a valid email address
+
+!!! note
+ Email addresses are [notoriously hard to validate and the official email valid spec is often too loose for any real world application](http://stackoverflow.com/a/201378/381010).
+ Gitlint by default takes a pragmatic approach and requires users to enter email addresses that contain a name, domain and tld and has no spaces.
+
+
+
+### Options ###
+
+Name | gitlint version | Default | Description
+----------------------|-------------------|------------------------------|----------------------------------
+regex | >= 0.9.0 | ```[^@ ]+@[^@ ]+\.[^@ ]+``` | Regex the commit author email address is matched against
+
+
+!!! note
+ An often recurring use-case is to only allow email addresses from a certain domain. The following regular expression achieves this: ```[^@]+@foo.com```
+
+
+## I1: ignore-by-title ##
+
+ID | Name | gitlint version | Description
+------|-----------------------------|-----------------|-------------------------------------------
+I1 | ignore-by-title | >= 0.10.0 | Ignore a commit based on matching its title.
+
+
+### Options ###
+
+Name | gitlint version | Default | Description
+----------------------|-------------------|------------------------------|----------------------------------
+regex | >= 0.10.0 | None | Regex to match against commit title. On match, the commit will be ignored.
+ignore | >= 0.10.0 | all | Comma-seperated list of rule names or ids to ignore when this rule is matched.
+
+### Examples
+
+#### .gitlint
+
+```ini
+# Match commit titles starting with Release
+# For those commits, ignore title-max-length and body-min-length rules
+[ignore-by-title]
+regex=^Release(.*)
+ignore=title-max-length,body-min-length
+# ignore all rules by setting ignore to 'all'
+# ignore=all
+```
+
+## I2: ignore-by-body ##
+
+ID | Name | gitlint version | Description
+------|-----------------------------|-----------------|-------------------------------------------
+I2 | ignore-by-body | >= 0.10.0 | Ignore a commit based on matching its body.
+
+
+### Options ###
+
+Name | gitlint version | Default | Description
+----------------------|-------------------|------------------------------|----------------------------------
+regex | >= 0.10.0 | None | Regex to match against each line of the body. On match, the commit will be ignored.
+ignore | >= 0.10.0 | all | Comma-seperated list of rule names or ids to ignore when this rule is matched.
+
+### Examples
+
+#### .gitlint
+
+```ini
+# Ignore all commits with a commit message body with a line that contains 'release'
+[ignore-by-body]
+regex=(.*)release(.*)
+ignore=all
+
+# For matching commits, only ignore rules T1, body-min-length, B6.
+# You can use both names as well as ids to refer to other rules.
+[ignore-by-body]
+regex=(.*)release(.*)
+ignore=T1,body-min-length,B6
+``` \ No newline at end of file
diff --git a/docs/user_defined_rules.md b/docs/user_defined_rules.md
new file mode 100644
index 0000000..a8a51d5
--- /dev/null
+++ b/docs/user_defined_rules.md
@@ -0,0 +1,312 @@
+# User Defined Rules
+_Introduced in gitlint v0.8.0_
+
+Gitlint supports the concept of **user-defined** rules: the ability for users to write their own custom rules in python.
+
+In a nutshell, use ```--extra-path /home/joe/myextensions``` to point gitlint to a ```myextensions``` directory where it will search
+for python files containing gitlint rule classes. You can also specify a single python module, ie
+```--extra-path /home/joe/my_rules.py```.
+
+```bash
+cat examples/commit-message-1 | gitlint --extra-path examples/
+# Example output of a user-defined Signed-Off-By rule
+1: UC2 Body does not contain a 'Signed-Off-By Line'
+# other violations were removed for brevity
+```
+
+The `SignedOffBy` user-defined ```CommitRule``` was discovered by gitlint when it scanned
+[examples/gitlint/my_commit_rules.py](https://github.com/jorisroovers/gitlint/blob/master/examples/my_commit_rules.py),
+which is part of the examples directory that was passed via ```--extra-path```:
+
+```python
+from gitlint.rules import CommitRule, RuleViolation
+
+class SignedOffBy(CommitRule):
+ """ This rule will enforce that each commit contains a "Signed-Off-By" line.
+ We keep things simple here and just check whether the commit body contains a
+ line that starts with "Signed-Off-By".
+ """
+
+ # A rule MUST have a human friendly name
+ name = "body-requires-signed-off-by"
+
+ # A rule MUST have a *unique* id, we recommend starting with UC
+ # (for User-defined Commit-rule).
+ id = "UC2"
+
+ def validate(self, commit):
+ for line in commit.message.body:
+ if line.startswith("Signed-Off-By"):
+ return
+
+ msg = "Body does not contain a 'Signed-Off-By' line"
+ return [RuleViolation(self.id, msg, line_nr=1)]
+```
+
+As always, ```--extra-path``` can also be set by adding it under the ```[general]``` section in your ```.gitlint``` file or using
+[one of the other ways to configure gitlint](configuration.md).
+
+If you want to check whether your rules are properly discovered by gitlint, you can use the ```--debug``` flag:
+
+```bash
+$ gitlint --debug --extra-path examples/
+# [output cut for brevity]
+ UC1: body-max-line-count
+ body-max-line-count=3
+ UC2: body-requires-signed-off-by
+ UL1: title-no-special-chars
+ special-chars=['$', '^', '%', '@', '!', '*', '(', ')']
+```
+
+!!! Note
+ In most cases it's really the easiest to just copy an example from the
+ [examples](https://github.com/jorisroovers/gitlint/tree/master/examples) directory and modify it to your needs.
+ The remainder of this page contains the technical details, mostly for reference.
+
+# Line and Commit Rules ##
+The ```SignedOffBy``` class above was an example of a user-defined ```CommitRule```. Commit rules are gitlint rules that
+act on the entire commit at once. Once the rules are discovered, gitlint will automatically take care of applying them
+to the entire commit. This happens exactly once per commit.
+
+A ```CommitRule``` contrasts with a ```LineRule```
+(see e.g.: [examples/my_line_rules.py](https://github.com/jorisroovers/gitlint/blob/master/examples/my_line_rules.py))
+in that a ```CommitRule``` is only applied once on an entire commit while a ```LineRule``` is applied for every line in the commit
+(you can also apply it once to the title using a ```target``` - see the examples section below).
+
+The benefit of a commit rule is that it allows commit rules to implement more complex checks that span multiple lines and/or checks
+that should only be done once per commit.
+
+While every ```LineRule``` can be implemented as a ```CommitRule```, it's usually easier and more concise to go with a ```LineRule``` if
+that fits your needs.
+
+## Examples ##
+
+In terms of code, writing your own ```CommitRule``` or ```LineRule``` is very similar.
+The only 2 differences between a ```CommitRule``` and a ```LineRule``` are the parameters of the ```validate(...)``` method and the extra
+```target``` attribute that ```LineRule``` requires.
+
+Consider the following ```CommitRule``` that can be found in [examples/my_commit_rules.py](https://github.com/jorisroovers/gitlint/blob/master/examples/my_commit_rules.py):
+
+```python
+from gitlint.rules import CommitRule, RuleViolation
+
+class SignedOffBy(CommitRule):
+ """ This rule will enforce that each commit contains a "Signed-Off-By" line.
+ We keep things simple here and just check whether the commit body contains a
+ line that starts with "Signed-Off-By".
+ """
+
+ # A rule MUST have a human friendly name
+ name = "body-requires-signed-off-by"
+
+ # A rule MUST have a *unique* id, we recommend starting with UC
+ # (for User-defined Commit-rule).
+ id = "UC2"
+
+ def validate(self, commit):
+ for line in commit.message.body:
+ if line.startswith("Signed-Off-By"):
+ return []
+
+ msg = "Body does not contain a 'Signed-Off-By Line'"
+ return [RuleViolation(self.id, msg, line_nr=1)]
+```
+Note the use of the ```name``` and ```id``` class attributes and the ```validate(...)``` method taking a single ```commit``` parameter.
+
+Contrast this with the following ```LineRule``` that can be found in [examples/my_line_rules.py](https://github.com/jorisroovers/gitlint/blob/master/examples/my_line_rules.py):
+
+```python
+from gitlint.rules import LineRule, RuleViolation, CommitMessageTitle
+from gitlint.options import ListOption
+
+class SpecialChars(LineRule):
+ """ This rule will enforce that the commit message title does not contai
+ any of the following characters:
+ $^%@!*() """
+
+ # A rule MUST have a human friendly name
+ name = "title-no-special-chars"
+
+ # A rule MUST have a *unique* id, we recommend starting with UL
+ # for User-defined Line-rule), but this can really be anything.
+ id = "UL1"
+
+ # A line-rule MUST have a target (not required for CommitRules).
+ target = CommitMessageTitle
+
+ # A rule MAY have an option_spec if its behavior should be configurable.
+ options_spec = [ListOption('special-chars', ['$', '^', '%', '@', '!', '*', '(', ')'],
+ "Comma separated list of characters that should not occur in the title")]
+
+ def validate(self, line, commit):
+ violations = []
+ # option values can be accessed via self.options
+ for char in self.options['special-chars'].value:
+ if char in line:
+ violation = RuleViolation(self.id, "Title contains the special character '{}'".format(char), line)
+ violations.append(violation)
+
+ return violations
+```
+
+Note the following 2 differences:
+
+- **extra ```target``` class attribute**: in this example set to ```CommitMessageTitle``` indicating that this ```LineRule```
+should only be applied once to the commit message title. The alternative value for ```target``` is ```CommitMessageBody```,
+ in which case gitlint will apply
+your rule to **every** line in the commit message body.
+- **```validate(...)``` takes 2 parameters**: Line rules get the ```line``` against which they are applied as the first parameter and
+the ```commit``` object of which the line is part of as second.
+
+In addition, you probably also noticed the extra ```options_spec``` class attribute which allows you to make your rules configurable.
+Options are not unique to ```LineRule```s, they can also be used by ```CommitRule```s and are further explained in the
+[Options](user_defined_rules.md#options) section below.
+
+
+# The commit object ##
+Both ```CommitRule```s and ```LineRule```s take a ```commit``` object in their ```validate(...)``` methods.
+The table below outlines the various attributes of that commit object that can be used during validation.
+
+
+Property | Type | Description
+-------------------------------| ---------------|-------------------
+commit.message | object | Python object representing the commit message
+commit.message.original | string | Original commit message as returned by git
+commit.message.full | string | Full commit message, with comments (lines starting with #) removed.
+commit.message.title | string | Title/subject of the commit message: the first line
+commit.message.body | string[] | List of lines in the body of the commit message (i.e. starting from the second line)
+commit.author_name | string | Name of the author, result of ```git log --pretty=%aN```
+commit.author_email | string | Email of the author, result of ```git log --pretty=%aE```
+commit.date | datetime | Python ```datetime``` object representing the time of commit
+commit.is_merge_commit | boolean | Boolean indicating whether the commit is a merge commit or not.
+commit.is_revert_commit | boolean | Boolean indicating whether the commit is a revert commit or not.
+commit.is_fixup_commit | boolean | Boolean indicating whether the commit is a fixup commit or not.
+commit.is_squash_commit | boolean | Boolean indicating whether the commit is a squash commit or not.
+commit.parents | string[] | List of parent commit ```sha```s (only for merge commits).
+commit.changed_files | string[] | List of files changed in the commit (relative paths).
+commit.branches | string[] | List of branch names the commit is part of
+commit.context | object | Object pointing to the bigger git context that the commit is part of
+commit.context.current_branch | string | Name of the currently active branch (of local repo)
+commit.context.repository_path | string | Absolute path pointing to the git repository being linted
+commit.context.commits | object[] | List of commits gitlint is acting on, NOT all commits in the repo.
+
+# Violations ##
+In order to let gitlint know that there is a violation in the commit being linted, users should have the ```validate(...)```
+method in their rules return a list of ```RuleViolation```s.
+
+!!! important
+ The ```validate(...)``` method doesn't always need to return a list, you can just skip the return statement in case there are no violations.
+ However, in case of a single violation, validate should return a **list** with a single item.
+
+The ```RuleViolation``` class has the following generic signature:
+
+```
+RuleViolation(rule_id, message, content=None, line_nr=None):
+```
+With the parameters meaning the following:
+
+Parameter | Type | Description
+--------------|---------|--------------------------------
+rule_id | string | Rule's unique string id
+message | string | Short description of the violation
+content | string | (optional) the violating part of commit or line
+line_nr | int | (optional) line number in the commit message where the violation occurs. **Automatically set to the correct line number for ```LineRule```s if not set explicitly.**
+
+A typical ```validate(...)``` implementation for a ```CommitRule``` would then be as follows:
+```python
+def validate(self, commit)
+ for line_nr, line in commit.message.body:
+ if "Jon Snow" in line:
+ # we add 1 to the line_nr because we offset the title which is on the first line
+ return [RuleViolation(self.id, "Commit message has the words 'Jon Snow' in it", line, line_nr + 1)]
+ return []
+```
+
+The parameters of this ```RuleViolation``` can be directly mapped onto gitlint's output as follows:
+
+![How Rule violations map to gitlint output](images/RuleViolation.png)
+
+# Options ##
+
+In order to make your own rules configurable, you can add an optional ```options_spec``` attribute to your rule class
+(supported for both ```LineRule``` and ```CommitRule```).
+
+```python
+from gitlint.rules import CommitRule, RuleViolation
+from gitlint.options import IntOption
+
+class BodyMaxLineCount(CommitRule):
+ # A rule MUST have a human friendly name
+ name = "body-max-line-count"
+
+ # A rule MUST have a *unique* id, we recommend starting with UC (for
+ # User-defined Commit-rule).
+ id = "UC1"
+
+ # A rule MAY have an option_spec if its behavior should be configurable.
+ options_spec = [IntOption('max-line-count', 3, "Maximum body line count")]
+
+ def validate(self, commit):
+ line_count = len(commit.message.body)
+ max_line_count = self.options['max-line-count'].value
+ if line_count > max_line_count:
+ message = "Body contains too many lines ({0} > {1})".format(line_count,
+ max_line_count)
+ return [RuleViolation(self.id, message, line_nr=1)]
+```
+
+
+By using ```options_spec```, you make your option available to be configured through a ```.gitlint``` file
+or one of the [other ways to configure gitlint](configuration.md). Gitlint automatically takes care of the parsing and input validation.
+
+For example, to change the value of the ```max-line-count``` option, add the following to your ```.gitlint``` file:
+```ini
+[body-max-line-count]
+body-max-line-count=1
+```
+
+As ```options_spec``` is a list, you can obviously have multiple options per rule. The general signature of an option is:
+```Option(name, default_value, description)```.
+
+Gitlint supports a variety of different option types, all can be imported from ```gitlint.options```:
+
+Option Class | Use for
+----------------|--------------
+StrOption | Strings
+IntOption | Integers. ```IntOption``` takes an optional ```allow_negative``` parameter if you want to allow negative integers.
+BoolOption | Booleans. Valid values: `true`, `false`. Case-insensitive.
+ListOption | List of strings. Comma separated.
+PathOption | Directory or file path. Takes an optional ```type``` parameter for specifying path type (```file```, ```dir``` (=default) or ```both```).
+
+!!! note
+ Gitlint currently does not support options for all possible types (e.g. float, list of int, etc).
+ [We could use a hand getting those implemented](contributing.md)!
+
+
+# Rule requirements ##
+
+As long as you stick with simple rules that are similar to the sample user-defined rules (see the
+[examples](https://github.com/jorisroovers/gitlint/blob/master/examples/my_commit_rules.py) directory), gitlint
+should be able to discover and execute them. While clearly you can run any python code you want in your rules,
+you might run into some issues if you don't follow the conventions that gitlint requires.
+
+While the [rule finding source-code](https://github.com/jorisroovers/gitlint/blob/master/gitlint/rule_finder.py) is the
+ultimate source of truth, here are some of the requirements that gitlint enforces.
+
+## Rule class requirements ###
+
+- Rules **must** extend from ```LineRule``` or ```CommitRule```
+- Rule classes **must** have ```id``` and ```name``` string attributes. The ```options_spec``` is optional,
+ but if set, it **must** be a list of gitlint Options.
+- Rule classes **must** have a ```validate``` method. In case of a ```CommitRule```, ```validate``` **must** take a single ```commit``` parameter.
+ In case of ```LineRule```, ```validate``` **must** take ```line``` and ```commit``` as first and second parameters.
+- LineRule classes **must** have a ```target``` class attributes that is set to either ```CommitMessageTitle``` or ```CommitMessageBody```.
+- User Rule id's **cannot** start with ```R```, ```T```, ```B``` or ```M``` as these rule ids are reserved for gitlint itself.
+- Rules **should** have a case-insensitive unique id as only one rule can exist with a given id. While gitlint does not enforce this, having multiple rules with
+ the same id might lead to unexpected or undeterministic behavior.
+
+## extra-path requirements ###
+- If ```extra-path``` is a directory, it does **not** need to be a proper python package, i.e. it doesn't require an ```__init__.py``` file.
+- Python files containing user-defined rules must have a ```.py``` extension. Files with a different extension will be ignored.
+- The ```extra-path``` will be searched non-recursively, i.e. all rule classes must be present at the top level ```extra-path``` directory.
+- User rule classes must be defined in the modules that are part of ```extra-path```, rules that are imported from outside the ```extra-path``` will be ignored.