@@ -93,17 +93,144 @@ run the hook from outside Vagrant).
93
93
94
94
## Adding zulint to a codebase
95
95
96
- TODO. Will roughly include ` pip install zulint ` , copying an example
97
- ` lint ` script, and adding your rules.
96
+ TODO: Make a pypi release
98
97
98
+ Add ` zulint ` to your codebase requirements file or just do:
99
+
100
+ ```
101
+ pip install zulint
102
+ ```
103
+
104
+ See [ example-lint] ( ./example-lint ) file for a simple example of adding zulint to
105
+ your codebase. For a more advanced usage example, you can look at
106
+ [ Zulip's linter] ( https://github.com/zulip/zulip/blob/master/tools/lint ) .
107
+
108
+ ** NOTE**
109
+
110
+ * Remember to mark your lint file executable using:
111
+
112
+ ``` bash
113
+ > chmod +x < YOUR LINT FILE>
114
+ ```
115
+
116
+ * Add ` <YOUR LINTER VARIABLE NAME>.do_lint() ` add the end of your lint file.
99
117
100
118
## Adding third-party linters
101
119
102
- TODO: Document the linter_config API.
120
+ First import the ` LinterConfig ` and initialize it with default arguments.
121
+ You can then use the ` external_linter ` method to register the linter.
122
+
123
+ eg:
124
+
125
+ ``` python
126
+ import argparse
127
+ from zulint.command import add_default_linter_arguments, LinterConfig
128
+ parser = argparse.ArgumentParser()
129
+ # Add custom parser arguments here.
130
+
131
+ add_default_linter_arguments(parser)
132
+ args = parser.parse_args()
133
+
134
+ linter_config = LinterConfig(args)
135
+
136
+ # Add your external litner:
137
+ linter_config.external_linter(' eslint' , [' node' , ' node_modules/.bin/eslint' ,
138
+ ' --quiet' , ' --cache' , ' --ext' , ' .js,.ts' ], [' js' , ' ts' ],
139
+ fix_arg = ' --fix' ,
140
+ description = " Standard JavaScript style and formatting linter"
141
+ " (config: .eslintrc)." )
142
+
143
+ linter_config.do_lint()
144
+ ```
145
+
146
+ Please make sure external linter (here ` eslint ` ) is accessible via bash or in the
147
+ virtual env where this linter will run.
103
148
104
149
## Writing custom rules
105
150
106
- TODO: Document all the features of the ` RuleList ` and ` custom_check ` system.
151
+ You can write your own custom rules for any language using regular expression
152
+ in zulint. Doing it is very simple and there are tons of examples available
153
+ in [ Zulip's custom_check.py file] ( https://github.com/zulip/zulip/blob/master/tools/linter_lib/custom_check.py ) .
154
+
155
+ In the [ above example] ( #adding-third-party-linters ) you can add custom rules via ` @linter_config.lint ` decorator.
156
+ For eg:
157
+
158
+ ``` python
159
+
160
+ from zulint.custom_rules import RuleList
161
+
162
+ @linter_config.lint
163
+ def check_custom_rules ():
164
+ # type: () -> int
165
+ """ Check trailing whitespace for specified files"""
166
+ trailing_whitespace_rule = RuleList(
167
+ langs = file_types,
168
+ rules = [{
169
+ ' pattern' : r ' \s + $ ' ,
170
+ ' strip' : ' \n ' ,
171
+ ' description' : ' Fix trailing whitespace'
172
+ }]
173
+ )
174
+ failed = trailing_whitespace_rule.check(by_lang, verbose = args.verbose)
175
+ return 1 if failed else 0
176
+ ```
177
+
178
+ #### RuleList
179
+ A new custom rule is defined via the ` RuleList ` class. ` RuleList ` takes the following arguments:
180
+
181
+ ``` python
182
+ langs # The languages this rule will run on. eg: ['py', 'bash']
183
+ rules # List of custom `Rule`s to run. See definition of Rule below for more details.
184
+ max_length # Set a max length value for each line in the files. eg: 79
185
+ length_exclude # List of files to exclude from `max_length` limit. eg: ["README"]
186
+ shebang_rules # List of shebang `Rule`s to run in `langs`. Default: []
187
+ exclude_files_in # Directory to exclude from all rules. eg: 'app/' Default: None
188
+ exclude_max_length_fns # List of file names to exclude from max_length limit. eg: [test, example] Defautl: []
189
+ exclude_max_length_line_patterns # List of line patterns to exclude from max_length limit. eg: ["`\{\{ api_url \}\}[^`]+`"]
190
+ ```
191
+
192
+ #### Rule
193
+ A rule is a python dictionary containing regular expression,
194
+ which will be run on each line in the ` langs ` ' files specified in the ` RuleList ` .
195
+ It has a lot of additional features which you can use to run the pattern in
196
+ specific areas of your codebase.
197
+
198
+ Find below all the keys that a ` Rule ` can have along with the
199
+ type of inputs they take.
200
+
201
+ ``` python
202
+ Rule = TypedDict(" Rule" , {
203
+ " bad_lines" : List[str ],
204
+ " description" : str ,
205
+ " exclude" : Set[str ],
206
+ " exclude_line" : Set[Tuple[str , str ]],
207
+ " exclude_pattern" : str ,
208
+ " good_lines" : List[str ],
209
+ " include_only" : Set[str ],
210
+ " pattern" : str ,
211
+ " strip" : str ,
212
+ " strip_rule" : str ,
213
+ }, total = False )
214
+ ```
215
+
216
+ * ` pattern ` is your regular expression to be run on all the eligible lines (i.e. lines which haven't been excluded by you).
217
+ * ` description ` is the message that will be displayed if a pattern match is found.
218
+ * ` good_lines ` are the list of sample lines which shouldn't match the pattern.
219
+ * ` bad_lines ` are like ` good_lines ` but they match the pattern.
220
+
221
+ ** NOTE** : ` patten ` is run on ` bad_lines ` and ` good_lines ` and you can use them as an example to tell the developer
222
+ what is wrong with their code and how to fix it.
223
+
224
+ * ` exclude ` List of folders to exclude.
225
+ * ` exclude_line ` Tuple of filename and pattern to exclude from pattern check.
226
+ eg:
227
+
228
+ ``` python
229
+ (' zerver/lib/actions.py' , " user_profile.save() # Can't use update_fields because of how the foreign key works." )`
230
+ ```
231
+
232
+ * ` exclude_pattern ` : pattern to exclude from the matching patterns.
233
+ * ` include_only ` : ` pattern ` is only run on these files.
107
234
108
235
## Development Setup
109
236
@@ -112,5 +239,5 @@ Run the following commands in a terminal to install zulint.
112
239
git clone [email protected] :zulip/zulint.git
113
240
python3 -m venv zulint_env
114
241
source zulint_env/bin/activate
115
- python3 setup.py install
242
+ pip install -e .
116
243
```
0 commit comments