# A toolchain to parse, analyze, and format Zeek scripts
[![Build and test](https://github.com/zeek/zeekscript/actions/workflows/build_wheels.yml/badge.svg)](https://github.com/zeek/zeekscript/actions/workflows/build_wheels.yml)
`zeekscript` is a Python package that provides tooling to operate on [Zeek](https://zeek.org)
scripts. `zeekscript` comes with command line tools that make common tasks accessible,
but its functionality is just an `import zeekscript` away in your own Python tools.
`zeekscript` is powered by [Tree-Sitter](https://tree-sitter.github.io/tree-sitter/),
its [Python bindings](https://github.com/tree-sitter/py-tree-sitter), and our
[tree-sitter-zeek](https://github.com/zeek/tree-sitter-zeek) grammar.
## Supported platforms and Python versions
`zeekscript` supports Python 3.7+ on Linux, MacOS, and Windows. We recommend
CPython. PyPy looks prone to crashing on Windows and MacOS, and we're not
currently building PyPy wheels on those platforms. (We've not investigated PyPy
in depth and feedback is welcome.)
## Installation
To install our ready-made Python wheels, say:
```console
pip install zeekscript
```
For a full list of available builds, you can check out the
[PyPI downloads](https://pypi.org/project/zeekscript/#files) or take a look at our
[CI build matrix](https://github.com/zeek/zeekscript/blob/main/.github/workflows/build_wheels.yml).
The `zeekscript` package includes native code (the compiled [tree-sitter Zeek
grammar](https://github.com/zeek/tree-sitter-zeek)). We strive to provide wheels
for popular platforms and Python versions. In case your setup isn't covered, the
installation process will build the package locally on your system, for which
some dependencies need to be available. Read on for details, and feel free to
file a ticket detailing your setup.
### Building from source
If our build matrix doesn't cover your platform and Python version, or if you'd
simply like to build and install the `zeekscript` package yourself, you need to
provide two dependencies:
* The [tree-sitter Python bindings](https://pypi.org/project/tree-sitter/),
available via
```console
pip install tree_sitter
```
* A C compiler, such as `gcc` or `clang`.
To obtain the sources, please clone this repository. **Note**: make sure to
clone recursively (`git clone --recurse-submodules`), since this pulls in the
needed Zeek grammar. We don't provide source packages on Github, but all
releases are tagged in `git`.
For installation from local sources, say:
```console
pip install .
```
The `zeekscript` package doesn't implement the Zeek grammar compilation itself,
it outsources it to the `tree-sitter` Python bindings, which provide this
ability directly from Python. `zeekscript` merely initiates compilation during
the package build. See our
[setup.py](https://github.com/zeek/zeekscript/blob/main/setup.py) for details.
### Testing
The package comes with a testsuite. To run it, say
```console
make
```
from the toplevel. For details on the tests, take a look at the `tests`
directory.
## Usage
### zeek-format
Most significantly, the package includes `zeek-format`, a tool that formats Zeek
scripts. Our philosophy is similar to `gofmt` and the opposite of
`clang-format`: there is only one way to layout Zeek scripts, and this tool
provides it. Accordingly, it features zero options for tweaking the formatting:
```console
$ zeek-format --help
usage: zeek-format [-h] [--version] [--inplace] [--recursive] [FILES ...]
A Zeek script formatter
positional arguments:
FILES Zeek script(s) to process. Use "-" to specify stdin as a filename. Omitting filenames entirely implies
reading from stdin.
options:
-h, --help show this help message and exit
--version, -v show version and exit
--inplace, -i change provided files instead of writing to stdout
--recursive, -r process *.zeek files recursively when provided directories instead of files. Requires --inplace.
```
Parsing errors are not fatal, and `zeek-format` does its best to continue
formatting in the presence of errors. When it encounters parser errors,
`zeek-format` exits with a non-zero exit code and reports the trouble it
encountered to stderr.
```console
$ echo 'event foo( a:count ) {print "hi" ; }' | zeek-format
event foo(a: count)
{
print "hi";
}
```
To format entire directory trees, combine `--inplace` and `--recursive`, and
point it at a directory:
```console
$ cd zeek
$ zeek-format -ir scripts
430 files processed successfully
```
### zeek-script
The `zeek-script` command is the Swiss army knife in the toolbox: it provides
access to a range of script-processing tools (including formatting) via
subcommands. (Okay, so far "range" == two, but expect that to grow in the future.)
```console
$ zeek-script --help
usage: zeek-script [-h] [--version] {format,parse} ...
A Zeek script analyzer
options:
-h, --help show this help message and exit
--version, -v show version and exit
commands:
{format,parse} See `zeek-script <command> -h` for per-command usage info.
format Format/indent Zeek scripts
parse Show Zeek script parse tree with parser metadata.
```
The `parse` command renders its script input as a parse tree. It resembles
`tree-sitter parse`, but shows more context about the relevant snippets of
content, including parsing errors.
```console
$ echo 'event zeek_init() { }' | zeek-script parse
source_file (0.0,1.0) 'event zeek_init() { }\n'
decl (0.0,0.21) 'event zeek_init() { }'
func_decl (0.0,0.21) 'event zeek_init() { }'
func_hdr (0.0,0.17) 'event zeek_init()'
event (0.0,0.17) 'event zeek_init()'
event (0.0,0.5)
id (0.6,0.15) 'zeek_init'
func_params (0.15,0.17) '()'
( (0.15,0.16)
) (0.16,0.17)
func_body (0.18,0.21) '{ }'
{ (0.18,0.19)
} (0.20,0.21)
```
Here's a syntax error:
```console
$ echo 'event zeek_init)() { }' | zeek-script parse
source_file (0.0,1.0) [error] 'event zeek_init)() { }\n'
decl (0.0,0.22) [error] 'event zeek_init)() { }'
func_decl (0.0,0.22) [error] 'event zeek_init)() { }'
func_hdr (0.0,0.18) [error] 'event zeek_init)()'
event (0.0,0.18) [error] 'event zeek_init)()'
event (0.0,0.5)
id (0.6,0.15) 'zeek_init'
ERROR (0.15,0.16) [error] ')'
) (0.15,0.16)
func_params (0.16,0.18) '()'
( (0.16,0.17)
) (0.17,0.18)
func_body (0.19,0.22) '{ }'
{ (0.19,0.20)
} (0.21,0.22)
parse tree has problems: cannot parse line 0, col 15: ")"
```
See `zeek-script parse --help` for more information.
## Autocomplete
`zeekscript` features command-line auto-completion for users of
[argcomplete](https://github.com/kislyuk/argcomplete).
## Integration into text editors
You can integrate `zeekscript` into any editor that supports the execution of
shell commands on the currently edited files. The relevant `zeekscript` commands
support reading from stdin or filename.
### Emacs
We offer an [Emacs mode](https://github.com/zeek/emacs-zeek-mode) with support
for script formatting and parse tree inspection via keyboard shortcuts.
### vim
The following snippet hooks up `zeek-format` to format the current script:
```vim
function RunZeekScript()
" Create a new undo block for reverting formatting without changing cursor
" position. https://github.com/rhysd/vim-clang-format/pull/55
silent execute "noautocmd normal! ii\<esc>\"_x"
let l:save = winsaveview()
execute "%!zeek-format"
call winrestview(l:save)
endfunction
nnoremap <silent><buffer> <leader>cf :call RunZeekScript()<CR>
```
## Using `zeek-format` with [pre-commit](https://pre-commit.com/)
Add this to your [`.pre-commit-config.yaml`](https://pre-commit.com/#adding-pre-commit-plugins-to-your-project):
```yaml
- repo: https://github.com/zeek/zeekscript
rev: '' # Use the SHA/tag you want to point at.
hooks:
- id: zeek-format
```
Raw data
{
"_id": null,
"home_page": null,
"name": "zeekscript",
"maintainer": null,
"docs_url": null,
"requires_python": ">=3.9",
"maintainer_email": "The Zeek Project <info@zeek.org>",
"keywords": "zeek, scripts, language, formatter, formatting, indenter, indenting, parsing",
"author": null,
"author_email": null,
"download_url": "https://files.pythonhosted.org/packages/85/3e/2dbcc61da4603d7f84f5c8f81bb7c46a9491121c4b9eaefa55ddf07ae48d/zeekscript-1.3.0.tar.gz",
"platform": null,
"description": "# A toolchain to parse, analyze, and format Zeek scripts\n\n[![Build and test](https://github.com/zeek/zeekscript/actions/workflows/build_wheels.yml/badge.svg)](https://github.com/zeek/zeekscript/actions/workflows/build_wheels.yml)\n\n`zeekscript` is a Python package that provides tooling to operate on [Zeek](https://zeek.org)\nscripts. `zeekscript` comes with command line tools that make common tasks accessible,\nbut its functionality is just an `import zeekscript` away in your own Python tools.\n\n`zeekscript` is powered by [Tree-Sitter](https://tree-sitter.github.io/tree-sitter/),\nits [Python bindings](https://github.com/tree-sitter/py-tree-sitter), and our\n[tree-sitter-zeek](https://github.com/zeek/tree-sitter-zeek) grammar.\n\n## Supported platforms and Python versions\n\n`zeekscript` supports Python 3.7+ on Linux, MacOS, and Windows. We recommend\nCPython. PyPy looks prone to crashing on Windows and MacOS, and we're not\ncurrently building PyPy wheels on those platforms. (We've not investigated PyPy\nin depth and feedback is welcome.)\n\n## Installation\n\nTo install our ready-made Python wheels, say:\n\n```console\npip install zeekscript\n```\n\nFor a full list of available builds, you can check out the\n[PyPI downloads](https://pypi.org/project/zeekscript/#files) or take a look at our\n[CI build matrix](https://github.com/zeek/zeekscript/blob/main/.github/workflows/build_wheels.yml).\n\nThe `zeekscript` package includes native code (the compiled [tree-sitter Zeek\ngrammar](https://github.com/zeek/tree-sitter-zeek)). We strive to provide wheels\nfor popular platforms and Python versions. In case your setup isn't covered, the\ninstallation process will build the package locally on your system, for which\nsome dependencies need to be available. Read on for details, and feel free to\nfile a ticket detailing your setup.\n\n### Building from source\n\nIf our build matrix doesn't cover your platform and Python version, or if you'd\nsimply like to build and install the `zeekscript` package yourself, you need to\nprovide two dependencies:\n\n* The [tree-sitter Python bindings](https://pypi.org/project/tree-sitter/),\n available via\n\n ```console\n pip install tree_sitter\n ```\n\n* A C compiler, such as `gcc` or `clang`.\n\nTo obtain the sources, please clone this repository. **Note**: make sure to\nclone recursively (`git clone --recurse-submodules`), since this pulls in the\nneeded Zeek grammar. We don't provide source packages on Github, but all\nreleases are tagged in `git`.\n\nFor installation from local sources, say:\n\n```console\npip install .\n```\n\nThe `zeekscript` package doesn't implement the Zeek grammar compilation itself,\nit outsources it to the `tree-sitter` Python bindings, which provide this\nability directly from Python. `zeekscript` merely initiates compilation during\nthe package build. See our\n[setup.py](https://github.com/zeek/zeekscript/blob/main/setup.py) for details.\n\n### Testing\n\nThe package comes with a testsuite. To run it, say\n\n```console\nmake\n```\n\nfrom the toplevel. For details on the tests, take a look at the `tests`\ndirectory.\n\n## Usage\n\n### zeek-format\n\nMost significantly, the package includes `zeek-format`, a tool that formats Zeek\nscripts. Our philosophy is similar to `gofmt` and the opposite of\n`clang-format`: there is only one way to layout Zeek scripts, and this tool\nprovides it. Accordingly, it features zero options for tweaking the formatting:\n\n```console\n$ zeek-format --help\nusage: zeek-format [-h] [--version] [--inplace] [--recursive] [FILES ...]\n\nA Zeek script formatter\n\npositional arguments:\n FILES Zeek script(s) to process. Use \"-\" to specify stdin as a filename. Omitting filenames entirely implies\n reading from stdin.\n\noptions:\n -h, --help show this help message and exit\n --version, -v show version and exit\n --inplace, -i change provided files instead of writing to stdout\n --recursive, -r process *.zeek files recursively when provided directories instead of files. Requires --inplace.\n```\n\nParsing errors are not fatal, and `zeek-format` does its best to continue\nformatting in the presence of errors. When it encounters parser errors,\n`zeek-format` exits with a non-zero exit code and reports the trouble it\nencountered to stderr.\n\n```console\n$ echo 'event foo( a:count ) {print \"hi\" ; }' | zeek-format\nevent foo(a: count)\n {\n print \"hi\";\n }\n```\n\nTo format entire directory trees, combine `--inplace` and `--recursive`, and\npoint it at a directory:\n\n```console\n$ cd zeek\n$ zeek-format -ir scripts\n430 files processed successfully\n```\n\n### zeek-script\n\nThe `zeek-script` command is the Swiss army knife in the toolbox: it provides\naccess to a range of script-processing tools (including formatting) via\nsubcommands. (Okay, so far \"range\" == two, but expect that to grow in the future.)\n\n```console\n$ zeek-script --help\nusage: zeek-script [-h] [--version] {format,parse} ...\n\nA Zeek script analyzer\n\noptions:\n -h, --help show this help message and exit\n --version, -v show version and exit\n\ncommands:\n {format,parse} See `zeek-script <command> -h` for per-command usage info.\n format Format/indent Zeek scripts\n parse Show Zeek script parse tree with parser metadata.\n```\n\nThe `parse` command renders its script input as a parse tree. It resembles\n`tree-sitter parse`, but shows more context about the relevant snippets of\ncontent, including parsing errors.\n\n```console\n$ echo 'event zeek_init() { }' | zeek-script parse\nsource_file (0.0,1.0) 'event zeek_init() { }\\n'\n decl (0.0,0.21) 'event zeek_init() { }'\n func_decl (0.0,0.21) 'event zeek_init() { }'\n func_hdr (0.0,0.17) 'event zeek_init()'\n event (0.0,0.17) 'event zeek_init()'\n event (0.0,0.5)\n id (0.6,0.15) 'zeek_init'\n func_params (0.15,0.17) '()'\n ( (0.15,0.16)\n ) (0.16,0.17)\n func_body (0.18,0.21) '{ }'\n { (0.18,0.19)\n } (0.20,0.21)\n```\n\nHere's a syntax error:\n\n```console\n$ echo 'event zeek_init)() { }' | zeek-script parse\nsource_file (0.0,1.0) [error] 'event zeek_init)() { }\\n'\n decl (0.0,0.22) [error] 'event zeek_init)() { }'\n func_decl (0.0,0.22) [error] 'event zeek_init)() { }'\n func_hdr (0.0,0.18) [error] 'event zeek_init)()'\n event (0.0,0.18) [error] 'event zeek_init)()'\n event (0.0,0.5)\n id (0.6,0.15) 'zeek_init'\n ERROR (0.15,0.16) [error] ')'\n ) (0.15,0.16)\n func_params (0.16,0.18) '()'\n ( (0.16,0.17)\n ) (0.17,0.18)\n func_body (0.19,0.22) '{ }'\n { (0.19,0.20)\n } (0.21,0.22)\nparse tree has problems: cannot parse line 0, col 15: \")\"\n```\n\nSee `zeek-script parse --help` for more information.\n\n## Autocomplete\n\n`zeekscript` features command-line auto-completion for users of\n[argcomplete](https://github.com/kislyuk/argcomplete).\n\n## Integration into text editors\n\nYou can integrate `zeekscript` into any editor that supports the execution of\nshell commands on the currently edited files. The relevant `zeekscript` commands\nsupport reading from stdin or filename.\n\n### Emacs\n\nWe offer an [Emacs mode](https://github.com/zeek/emacs-zeek-mode) with support\nfor script formatting and parse tree inspection via keyboard shortcuts.\n\n### vim\n\nThe following snippet hooks up `zeek-format` to format the current script:\n\n```vim\nfunction RunZeekScript()\n \" Create a new undo block for reverting formatting without changing cursor\n \" position. https://github.com/rhysd/vim-clang-format/pull/55\n silent execute \"noautocmd normal! ii\\<esc>\\\"_x\"\n let l:save = winsaveview()\n execute \"%!zeek-format\"\n call winrestview(l:save)\nendfunction\n\nnnoremap <silent><buffer> <leader>cf :call RunZeekScript()<CR>\n```\n\n## Using `zeek-format` with [pre-commit](https://pre-commit.com/)\n\nAdd this to your [`.pre-commit-config.yaml`](https://pre-commit.com/#adding-pre-commit-plugins-to-your-project):\n\n```yaml\n- repo: https://github.com/zeek/zeekscript\n rev: '' # Use the SHA/tag you want to point at.\n hooks:\n - id: zeek-format\n```\n",
"bugtrack_url": null,
"license": null,
"summary": "A Zeek script formatter and analyzer",
"version": "1.3.0",
"project_urls": {
"Repository": "https://github.com/zeek/zeekscript"
},
"split_keywords": [
"zeek",
" scripts",
" language",
" formatter",
" formatting",
" indenter",
" indenting",
" parsing"
],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "853e2dbcc61da4603d7f84f5c8f81bb7c46a9491121c4b9eaefa55ddf07ae48d",
"md5": "f712bc4bc69cb09c89baba251050db11",
"sha256": "45b09ca7f863af95d8bf10dda7d09399dcb25fa8e6fc3788ba594e5df9767263"
},
"downloads": -1,
"filename": "zeekscript-1.3.0.tar.gz",
"has_sig": false,
"md5_digest": "f712bc4bc69cb09c89baba251050db11",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.9",
"size": 38840,
"upload_time": "2024-12-16T14:26:03",
"upload_time_iso_8601": "2024-12-16T14:26:03.164245Z",
"url": "https://files.pythonhosted.org/packages/85/3e/2dbcc61da4603d7f84f5c8f81bb7c46a9491121c4b9eaefa55ddf07ae48d/zeekscript-1.3.0.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2024-12-16 14:26:03",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "zeek",
"github_project": "zeekscript",
"travis_ci": false,
"coveralls": false,
"github_actions": true,
"lcname": "zeekscript"
}