docs: update README with new features
This commit is contained in:
parent
3e1003ba94
commit
92735f3eee
1 changed files with 366 additions and 8 deletions
374
README.md
374
README.md
|
@ -30,26 +30,68 @@ supported, I cannot guarantee that _everything_ is supported just yet.
|
|||
- **Validation** - Syntax checking with precise error locations
|
||||
- **Optimization** - Configurable empty line reduction and whitespace control
|
||||
|
||||
### Diagnostics & Analysis
|
||||
|
||||
- **Comprehensive diagnostics** - Syntax, semantic, style, and best practice
|
||||
analysis
|
||||
- **Modular analysis** - Run specific diagnostic modules (`lexical`, `syntax`,
|
||||
`style`, `semantic`)
|
||||
- **LSP-compatible output** - JSON format for editor integration
|
||||
- **Human-readable reports** - Detailed error messages with context and location
|
||||
information
|
||||
- **Configurable severity** - Control which diagnostic categories to
|
||||
enable/disable
|
||||
|
||||
## Usage
|
||||
|
||||
### Formatting
|
||||
|
||||
```bash
|
||||
# Basic formatting
|
||||
nff -f /etc/nftables.conf
|
||||
# Format a specific file (in place)
|
||||
nff format /etc/nftables.conf
|
||||
|
||||
# Format all .nft files in current directory (in place)
|
||||
nff format
|
||||
|
||||
# Custom indentation (4 spaces)
|
||||
nff -f config.nft --indent spaces --spaces 4
|
||||
nff format config.nft --indent spaces --spaces 4
|
||||
|
||||
# Optimize formatting (reduce empty lines)
|
||||
nff -f config.nft --optimize
|
||||
nff format config.nft --optimize
|
||||
|
||||
# Output to file
|
||||
nff -f config.nft -o formatted.nft
|
||||
# Output to stdout instead of modifying files
|
||||
nff format config.nft --stdout
|
||||
|
||||
# Syntax validation only
|
||||
nff -f config.nft --check
|
||||
nff format config.nft --check
|
||||
|
||||
# Debug output for development (or debugging)
|
||||
nff -f config.nft --debug
|
||||
nff format config.nft --debug
|
||||
```
|
||||
|
||||
### Linting and Diagnostics
|
||||
|
||||
```bash
|
||||
# Run comprehensive diagnostics on a file
|
||||
nff lint /etc/nftables.conf
|
||||
|
||||
# Lint all .nft files in current directory
|
||||
nff lint
|
||||
|
||||
# JSON output for editor integration
|
||||
nff lint config.nft --json
|
||||
|
||||
# Run specific diagnostic modules
|
||||
nff lint config.nft --modules syntax,style
|
||||
|
||||
# Available modules: lexical, syntax, style, semantic
|
||||
nff lint config.nft --modules semantic
|
||||
|
||||
# Configure diagnostic settings (note: flags are enabled by default)
|
||||
nff lint config.nft --style-warnings=false --best-practices=false
|
||||
|
||||
# Debug output with diagnostics
|
||||
nff lint config.nft --debug
|
||||
```
|
||||
|
||||
## Architecture
|
||||
|
@ -69,12 +111,235 @@ graph TD
|
|||
AST --> Formatter
|
||||
Formatter --> Output
|
||||
CST --> Formatter
|
||||
|
||||
Input --> Diagnostics[Diagnostic System]
|
||||
Diagnostics --> LexAnalyzer[Lexical Analyzer]
|
||||
Diagnostics --> SyntaxAnalyzer[Syntax Analyzer]
|
||||
Diagnostics --> StyleAnalyzer[Style Analyzer]
|
||||
Diagnostics --> SemanticAnalyzer[Semantic Analyzer]
|
||||
|
||||
LexAnalyzer --> DiagOutput[JSON/Human Output]
|
||||
SyntaxAnalyzer --> DiagOutput
|
||||
StyleAnalyzer --> DiagOutput
|
||||
SemanticAnalyzer --> DiagOutput
|
||||
```
|
||||
|
||||
## Installation
|
||||
|
||||
Recommended way of installing nff is to use Nix.
|
||||
|
||||
### Editor Integration
|
||||
|
||||
#### Neovim Setup
|
||||
|
||||
nff can be integrated into Neovim as a diagnostics source for nftables files.
|
||||
Here are several setup approaches:
|
||||
|
||||
##### Option 2: Using none-ls
|
||||
|
||||
```lua
|
||||
local null_ls = require("null-ls")
|
||||
|
||||
null_ls.setup({
|
||||
sources = {
|
||||
-- nftables diagnostics
|
||||
null_ls.builtins.diagnostics.nff.with({
|
||||
command = "nff",
|
||||
args = { "lint", "$FILENAME", "--json" },
|
||||
format = "json",
|
||||
check_exit_code = false,
|
||||
filetypes = { "nftables" },
|
||||
}),
|
||||
|
||||
-- nftables formatting
|
||||
null_ls.builtins.formatting.nff.with({
|
||||
command = "nff",
|
||||
args = { "format", "$FILENAME", "--stdout" },
|
||||
filetypes = { "nftables" },
|
||||
}),
|
||||
},
|
||||
})
|
||||
```
|
||||
|
||||
##### Option 2: Using nvim-lint (recommended)
|
||||
|
||||
```lua
|
||||
-- ~/.config/nvim/lua/config/lint.lua
|
||||
require('lint').linters.nff = {
|
||||
cmd = 'nff',
|
||||
stdin = false,
|
||||
args = { 'lint', '%s', '--json' },
|
||||
stream = 'stdout',
|
||||
ignore_exitcode = true,
|
||||
parser = function(output)
|
||||
local diagnostics = {}
|
||||
local ok, decoded = pcall(vim.fn.json_decode, output)
|
||||
|
||||
if not ok or not decoded.diagnostics then
|
||||
return diagnostics
|
||||
end
|
||||
|
||||
for _, diagnostic in ipairs(decoded.diagnostics) do
|
||||
table.insert(diagnostics, {
|
||||
lnum = diagnostic.range.start.line,
|
||||
col = diagnostic.range.start.character,
|
||||
severity = diagnostic.severity == "Error" and vim.diagnostic.severity.ERROR or vim.diagnostic.severity.WARN,
|
||||
message = diagnostic.message,
|
||||
source = "nff",
|
||||
code = diagnostic.code,
|
||||
})
|
||||
end
|
||||
|
||||
return diagnostics
|
||||
end,
|
||||
}
|
||||
|
||||
-- Setup linting for nftables files
|
||||
vim.api.nvim_create_autocmd({ "BufEnter", "BufWritePost" }, {
|
||||
pattern = "*.nft",
|
||||
callback = function()
|
||||
require("lint").try_lint("nff")
|
||||
end,
|
||||
})
|
||||
```
|
||||
|
||||
##### Option 3: Custom Lua Function
|
||||
|
||||
For a simple custom solution:
|
||||
|
||||
```lua
|
||||
-- ~/.config/nvim/lua/nff.lua
|
||||
local M = {}
|
||||
|
||||
function M.lint_nftables()
|
||||
local filename = vim.fn.expand('%:p')
|
||||
if vim.bo.filetype ~= 'nftables' then
|
||||
return
|
||||
end
|
||||
|
||||
local cmd = { 'nff', 'lint', filename, '--json' }
|
||||
|
||||
vim.fn.jobstart(cmd, {
|
||||
stdout_buffered = true,
|
||||
on_stdout = function(_, data)
|
||||
if data then
|
||||
local output = table.concat(data, '\n')
|
||||
local ok, result = pcall(vim.fn.json_decode, output)
|
||||
|
||||
if ok and result.diagnostics then
|
||||
local diagnostics = {}
|
||||
for _, diag in ipairs(result.diagnostics) do
|
||||
table.insert(diagnostics, {
|
||||
lnum = diag.range.start.line,
|
||||
col = diag.range.start.character,
|
||||
severity = diag.severity == "Error" and vim.diagnostic.severity.ERROR or vim.diagnostic.severity.WARN,
|
||||
message = diag.message,
|
||||
source = "nff",
|
||||
})
|
||||
end
|
||||
|
||||
vim.diagnostic.set(vim.api.nvim_create_namespace('nff'), 0, diagnostics)
|
||||
end
|
||||
end
|
||||
end,
|
||||
})
|
||||
end
|
||||
|
||||
-- Auto-run on save
|
||||
vim.api.nvim_create_autocmd("BufWritePost", {
|
||||
pattern = "*.nft",
|
||||
callback = M.lint_nftables,
|
||||
})
|
||||
|
||||
return M
|
||||
```
|
||||
|
||||
## Diagnostic Categories
|
||||
|
||||
nff provides comprehensive analysis across multiple categories:
|
||||
|
||||
### Syntax Errors
|
||||
|
||||
- Parse errors with precise location information
|
||||
- Missing tokens (semicolons, braces, etc.)
|
||||
- Unexpected tokens
|
||||
- Unterminated strings
|
||||
- Invalid numbers
|
||||
|
||||
### Semantic Validation
|
||||
|
||||
- Unknown table families (`inet`, `ip`, `ip6`, etc.)
|
||||
- Invalid chain types and hooks
|
||||
- Incorrect priority values
|
||||
- Missing chain policies
|
||||
- Duplicate table/chain names
|
||||
- Invalid CIDR notation
|
||||
- Invalid port ranges
|
||||
|
||||
### Style Warnings
|
||||
|
||||
- Missing shebang line
|
||||
- Inconsistent indentation (mixed tabs/spaces)
|
||||
- Trailing whitespace
|
||||
- Lines exceeding maximum length (configurable)
|
||||
- Excessive empty lines
|
||||
- Preferred syntax alternatives
|
||||
|
||||
### Best Practices
|
||||
|
||||
- Chains without explicit policies
|
||||
- Rules without actions
|
||||
- Overly permissive rules
|
||||
- Duplicate or conflicting rules
|
||||
- Unused variables or sets
|
||||
- Deprecated syntax usage
|
||||
- Missing documentation
|
||||
- Security risks
|
||||
|
||||
### Performance Hints
|
||||
|
||||
- Inefficient rule ordering
|
||||
- Large sets without timeouts
|
||||
- Missing counters where beneficial
|
||||
|
||||
## JSON Output Format
|
||||
|
||||
When using `--json`, nff outputs LSP-compatible diagnostics:
|
||||
|
||||
```json
|
||||
{
|
||||
"diagnostics": [
|
||||
{
|
||||
"range": {
|
||||
"start": { "line": 5, "character": 10 },
|
||||
"end": { "line": 5, "character": 20 }
|
||||
},
|
||||
"severity": "Error",
|
||||
"code": "NFT001",
|
||||
"source": "nff",
|
||||
"message": "Expected ';' after policy",
|
||||
"related_information": [],
|
||||
"code_actions": [],
|
||||
"tags": []
|
||||
}
|
||||
],
|
||||
"file_path": "config.nft",
|
||||
"source_text": "..."
|
||||
}
|
||||
```
|
||||
|
||||
### Diagnostic Codes
|
||||
|
||||
nff uses structured diagnostic codes for categorization:
|
||||
|
||||
- **NFT001-NFT099**: Syntax errors
|
||||
- **NFT101-NFT199**: Semantic errors
|
||||
- **NFT201-NFT299**: Style warnings
|
||||
- **NFT301-NFT399**: Best practice recommendations
|
||||
- **NFT401-NFT499**: Performance hints
|
||||
- **NFT501-NFT599**: Formatting issues
|
||||
- **NFT601-NFT699**: nftables-specific validations
|
||||
|
||||
## Development
|
||||
|
||||
### Testing
|
||||
|
@ -196,6 +461,88 @@ table inet protection {
|
|||
}
|
||||
```
|
||||
|
||||
## Diagnostics Examples
|
||||
|
||||
### Error Detection
|
||||
|
||||
Input file with issues:
|
||||
|
||||
```nftables
|
||||
table inet firewall {
|
||||
chain input {
|
||||
type filter hook input priority 100
|
||||
tcp dport 22 accept
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Human-readable output:
|
||||
|
||||
```
|
||||
Found 2 issues in config.nft:
|
||||
config.nft:3:37: error: Expected ';' after policy [NFT001]
|
||||
1: table inet firewall {
|
||||
2: chain input {
|
||||
→ 3: type filter hook input priority 100
|
||||
4: tcp dport 22 accept
|
||||
5: }
|
||||
|
||||
config.nft:3:1: warning: Filter chain should have an explicit policy [NFT301]
|
||||
1: table inet firewall {
|
||||
2: chain input {
|
||||
→ 3: type filter hook input priority 100
|
||||
4: tcp dport 22 accept
|
||||
5: }
|
||||
```
|
||||
|
||||
JSON output:
|
||||
|
||||
```json
|
||||
{
|
||||
"diagnostics": [
|
||||
{
|
||||
"range": {
|
||||
"start": { "line": 2, "character": 37 },
|
||||
"end": { "line": 2, "character": 37 }
|
||||
},
|
||||
"severity": "Error",
|
||||
"code": "NFT001",
|
||||
"source": "nff",
|
||||
"message": "Expected ';' after policy"
|
||||
},
|
||||
{
|
||||
"range": {
|
||||
"start": { "line": 2, "character": 0 },
|
||||
"end": { "line": 2, "character": 37 }
|
||||
},
|
||||
"severity": "Warning",
|
||||
"code": "NFT301",
|
||||
"source": "nff",
|
||||
"message": "Filter chain should have an explicit policy"
|
||||
}
|
||||
],
|
||||
"file_path": "config.nft",
|
||||
"source_text": "..."
|
||||
}
|
||||
```
|
||||
|
||||
### Style Analysis
|
||||
|
||||
Input with style issues:
|
||||
|
||||
```nftables
|
||||
table inet test{chain input{type filter hook input priority 0;policy drop;tcp dport 22 accept;}}
|
||||
```
|
||||
|
||||
Style warnings:
|
||||
|
||||
```
|
||||
Found 3 issues in style.nft:
|
||||
style.nft:1:1: warning: Consider adding a shebang line [NFT201]
|
||||
style.nft:1:121: warning: Line too long (98 > 80 characters) [NFT205]
|
||||
style.nft:1:16: warning: Missing space after '{' [NFT503]
|
||||
```
|
||||
|
||||
## Contributing
|
||||
|
||||
### Code Style
|
||||
|
@ -237,6 +584,17 @@ Below are the design goals of nff's architechture.
|
|||
- **Memory efficiency**: Streaming token processing where possible
|
||||
- **Grammar completeness**: Covers full nftables syntax specification
|
||||
|
||||
### Diagnostic Architecture
|
||||
|
||||
The diagnostic system uses a modular architecture with specialized analyzers:
|
||||
|
||||
- **Modular design**: Each analyzer focuses on specific concerns (lexical,
|
||||
syntax, style, semantic)
|
||||
- **Configurable analysis**: Enable/disable specific diagnostic categories
|
||||
- **LSP compatibility**: JSON output follows Language Server Protocol standards
|
||||
- **Performance optimized**: Concurrent analysis when possible
|
||||
- **Extensible**: Easy to add new diagnostic rules and categories
|
||||
|
||||
## License
|
||||
|
||||
nff is licensed under [MPL v2.0](LICENSE). See license file for more details on
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue