Skip to content

Commit ad3d79e

Browse files
committed
Add configurable ID mode with sequential IDs
1 parent 5bf5a09 commit ad3d79e

15 files changed

+463
-12
lines changed

.peas.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
#:schema ./schemas/peas.json
2+
13
[peas]
24
path = ".peas"
35
prefix = "peas-"
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
+++
2+
id = "peas-cf7ul"
3+
title = "Configurable sequential ticket ID generation"
4+
type = "feature"
5+
status = "todo"
6+
priority = "normal"
7+
created = "2026-02-02T19:03:01.460178900Z"
8+
updated = "2026-02-02T19:03:01.460178900Z"
9+
+++
10+
11+
Added configurable ID generation mode to support both random (default) and sequential IDs.
12+
13+
## Changes
14+
- Added id_mode configuration option: random (default) or sequential
15+
- Sequential mode generates IDs like peas-00001, peas-00002, etc.
16+
- Counter is persisted in .peas/.id file
17+
- id_length config now controls suffix length for both modes
18+
- Updated README documentation
19+
20+
## Usage
21+
Set in .peas.toml:
22+
23+
[peas]
24+
id_mode = "sequential"
25+
id_length = 5 # produces peas-00001
26+
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
+++
2+
id = "peas-lmkga"
3+
title = "JSON Schema for configuration files"
4+
type = "feature"
5+
status = "completed"
6+
priority = "normal"
7+
created = "2026-02-02T19:19:03.285041300Z"
8+
updated = "2026-02-02T19:20:44.621276900Z"
9+
+++
10+
11+
Added JSON Schema for peas configuration files to enable LSP support in editors.
12+
13+
## Changes
14+
- Created `schemas/peas.json` with JSON Schema draft-07
15+
- Schema covers all config options: peas settings and tui settings
16+
- Includes `x-taplo` extensions for enhanced Taplo support
17+
- Includes `x-tombi-table-keys-order` for Tombi key ordering
18+
- Added editor configuration examples to README
19+
20+
## Editor Support
21+
- Zed with Tombi extension
22+
- VS Code with Even Better TOML (Taplo)
23+
- VS Code with YAML extension
24+
- Neovim with taplo/yaml-language-server
25+
- Any editor supporting JSON Schema
26+
27+
## In-file directive
28+
Add `#:schema ./schemas/peas.json` at the top of .peas.toml (works with both Taplo and Tombi)
29+
30+
## Next Steps
31+
- Submit to SchemaStore for automatic editor discovery
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
+++
2+
id = "peas-mifvg"
3+
title = "Submit JSON Schema to SchemaStore"
4+
type = "chore"
5+
status = "todo"
6+
priority = "normal"
7+
created = "2026-02-02T19:19:10.880253300Z"
8+
updated = "2026-02-02T19:19:10.880253300Z"
9+
+++
10+
11+
Submit the peas configuration schema to SchemaStore for automatic editor discovery.
12+
13+
## Requirements
14+
- Fork SchemaStore/schemastore repository
15+
- Add schema to `src/schemas/json/peas.json`
16+
- Add catalog entry with fileMatch patterns:
17+
- `.peas.toml`
18+
- `.peas.yml`
19+
- `.peas.yaml`
20+
- `.peas.json`
21+
- Add test files in `src/test/peas/` and `src/negative_test/peas/`
22+
- Submit PR
23+
24+
## References
25+
- https://github.com/SchemaStore/schemastore/blob/master/CONTRIBUTING.md
26+
- https://www.schemastore.org/

README.md

Lines changed: 54 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -211,7 +211,8 @@ peas uses `.peas.toml` for configuration (also supports `.peas.yml`, `.peas.yaml
211211
[peas]
212212
path = ".peas" # Data directory
213213
prefix = "peas-" # ID prefix
214-
id_length = 5 # Random ID length
214+
id_length = 5 # ID suffix length
215+
id_mode = "random" # ID mode: "random" (default) or "sequential"
215216
default_status = "todo"
216217
default_type = "task"
217218
frontmatter = "toml" # Frontmatter format: toml, yaml, json (TOML preferred)
@@ -220,6 +221,58 @@ frontmatter = "toml" # Frontmatter format: toml, yaml, json (TOML preferred)
220221
use_type_emojis = false # Enable emoji icons for ticket types in TUI
221222
```
222223

224+
### ID Modes
225+
226+
- **random** (default): Generates IDs like `peas-a1b2c` using random alphanumeric characters
227+
- **sequential**: Generates IDs like `peas-00001`, `peas-00002`, etc. using an incrementing counter stored in `.peas/.id`
228+
229+
### Editor Support (JSON Schema)
230+
231+
A JSON Schema is available at `schemas/peas.json` for editor autocompletion and validation.
232+
233+
**In-file directive (works with Taplo and Tombi):**
234+
235+
Add this comment at the top of your `.peas.toml`:
236+
```toml
237+
#:schema ./schemas/peas.json
238+
239+
[peas]
240+
prefix = "peas-"
241+
```
242+
243+
**Zed with Tombi extension:**
244+
245+
Add to your `tombi.toml` (or project settings):
246+
```toml
247+
[[schemas]]
248+
path = "./schemas/peas.json"
249+
include = [".peas.toml"]
250+
```
251+
252+
**VS Code with Even Better TOML (Taplo):**
253+
254+
Add to your `.vscode/settings.json`:
255+
```json
256+
{
257+
"evenBetterToml.schema.associations": {
258+
".peas.toml": "./schemas/peas.json"
259+
}
260+
}
261+
```
262+
263+
**VS Code with YAML extension:**
264+
```json
265+
{
266+
"yaml.schemas": {
267+
"./schemas/peas.json": [".peas.yml", ".peas.yaml"]
268+
}
269+
}
270+
```
271+
272+
**Neovim with taplo/yaml-language-server:**
273+
274+
Configure your LSP to associate the schema with `.peas.*` files.
275+
223276
## File Format
224277

225278
Peas are stored as markdown files with TOML frontmatter (YAML and JSON also supported):

schemas/peas.json

Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
{
2+
"$schema": "http://json-schema.org/draft-07/schema#",
3+
"$id": "https://json.schemastore.org/peas.json",
4+
"title": "peas configuration",
5+
"description": "Configuration file for peas, a CLI-based flat-file issue tracker",
6+
"type": "object",
7+
"additionalProperties": false,
8+
"properties": {
9+
"peas": {
10+
"type": "object",
11+
"description": "Core peas settings",
12+
"additionalProperties": false,
13+
"x-tombi-table-keys-order": [
14+
"path",
15+
"prefix",
16+
"id_length",
17+
"id_mode",
18+
"default_status",
19+
"default_type",
20+
"frontmatter"
21+
],
22+
"properties": {
23+
"path": {
24+
"type": "string",
25+
"description": "Directory where pea files are stored",
26+
"default": ".peas",
27+
"examples": [
28+
".peas",
29+
"tickets",
30+
".issues"
31+
]
32+
},
33+
"prefix": {
34+
"type": "string",
35+
"description": "Prefix for ticket IDs",
36+
"default": "peas-",
37+
"examples": [
38+
"peas-",
39+
"ticket-",
40+
"issue-",
41+
""
42+
]
43+
},
44+
"id_length": {
45+
"type": "integer",
46+
"description": "Length of the ID suffix (random characters or zero-padded number)",
47+
"default": 5,
48+
"minimum": 1,
49+
"maximum": 20,
50+
"examples": [
51+
5,
52+
8,
53+
10
54+
]
55+
},
56+
"id_mode": {
57+
"type": "string",
58+
"description": "ID generation mode",
59+
"default": "random",
60+
"enum": [
61+
"random",
62+
"sequential"
63+
],
64+
"x-taplo": {
65+
"docs": {
66+
"enumValues": [
67+
"Generate random alphanumeric IDs (e.g., peas-a1b2c)",
68+
"Generate sequential numeric IDs (e.g., peas-00001, peas-00002)"
69+
]
70+
}
71+
}
72+
},
73+
"default_status": {
74+
"type": "string",
75+
"description": "Default status for new tickets",
76+
"default": "todo",
77+
"enum": [
78+
"draft",
79+
"todo",
80+
"in-progress",
81+
"completed",
82+
"scrapped"
83+
]
84+
},
85+
"default_type": {
86+
"type": "string",
87+
"description": "Default type for new tickets",
88+
"default": "task",
89+
"enum": [
90+
"milestone",
91+
"epic",
92+
"story",
93+
"feature",
94+
"bug",
95+
"chore",
96+
"research",
97+
"task"
98+
]
99+
},
100+
"frontmatter": {
101+
"type": "string",
102+
"description": "Frontmatter format for ticket markdown files",
103+
"default": "toml",
104+
"enum": [
105+
"toml",
106+
"yaml"
107+
],
108+
"x-taplo": {
109+
"docs": {
110+
"enumValues": [
111+
"TOML frontmatter with +++ delimiters (recommended)",
112+
"YAML frontmatter with --- delimiters"
113+
]
114+
}
115+
}
116+
}
117+
}
118+
},
119+
"tui": {
120+
"type": "object",
121+
"description": "Terminal UI settings",
122+
"additionalProperties": false,
123+
"properties": {
124+
"use_type_emojis": {
125+
"type": "boolean",
126+
"description": "Show emoji icons for ticket types in the TUI",
127+
"default": false
128+
}
129+
}
130+
}
131+
},
132+
"x-taplo": {
133+
"initKeys": [
134+
"peas"
135+
]
136+
}
137+
}

src/cli/handlers/bulk.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -321,7 +321,7 @@ fn handle_bulk_create(ctx: &CommandContext, params: BulkCreateParams) -> Result<
321321
if params.dry_run {
322322
let mut would_create = Vec::new();
323323
for title in &titles {
324-
let id = ctx.repo.generate_id();
324+
let id = ctx.repo.generate_id()?;
325325
let mut pea = Pea::new(id, title.to_string(), pea_type);
326326

327327
if let Some(ref p) = params.parent {
@@ -367,7 +367,7 @@ fn handle_bulk_create(ctx: &CommandContext, params: BulkCreateParams) -> Result<
367367
let mut errors_list: Vec<serde_json::Value> = Vec::new();
368368

369369
for title in titles {
370-
let id = ctx.repo.generate_id();
370+
let id = ctx.repo.generate_id()?;
371371
let mut pea = Pea::new(id, title.to_string(), pea_type);
372372

373373
if let Some(ref p) = params.parent {

src/cli/handlers/create.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ pub fn handle_create(
2323
dry_run: bool,
2424
) -> Result<()> {
2525
let body_content = resolve_body(body, body_file)?;
26-
let id = ctx.repo.generate_id();
26+
let id = ctx.repo.generate_id()?;
2727

2828
// Apply template settings if specified, then allow CLI args to override
2929
let (pea_type, default_priority, default_status, default_tags, body_template) =

src/cli/handlers/init.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use crate::config::{PeasConfig, PeasSettings};
1+
use crate::config::{IdMode, PeasConfig, PeasSettings};
22
use anyhow::Result;
33
use colored::Colorize;
44

@@ -17,6 +17,7 @@ pub fn handle_init(prefix: String, id_length: usize, peas_path: Option<String>)
1717
path: data_dir.clone(),
1818
prefix,
1919
id_length,
20+
id_mode: IdMode::Random,
2021
default_status: "todo".to_string(),
2122
default_type: "task".to_string(),
2223
frontmatter: "toml".to_string(),

src/config.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,17 @@ use crate::storage::FrontmatterFormat;
33
use serde::{Deserialize, Serialize};
44
use std::path::{Path, PathBuf};
55

6+
/// ID generation mode for tickets
7+
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default, Serialize, Deserialize)]
8+
#[serde(rename_all = "lowercase")]
9+
pub enum IdMode {
10+
/// Random alphanumeric ID using nanoid (default)
11+
#[default]
12+
Random,
13+
/// Sequential numeric ID (00001, 00002, etc.)
14+
Sequential,
15+
}
16+
617
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
718
pub struct PeasConfig {
819
#[serde(default)]
@@ -23,6 +34,9 @@ pub struct PeasSettings {
2334
#[serde(default = "default_id_length")]
2435
pub id_length: usize,
2536

37+
#[serde(default)]
38+
pub id_mode: IdMode,
39+
2640
#[serde(default = "default_status")]
2741
pub default_status: String,
2842

@@ -81,6 +95,7 @@ impl Default for PeasSettings {
8195
path: default_path(),
8296
prefix: default_prefix(),
8397
id_length: default_id_length(),
98+
id_mode: IdMode::default(),
8499
default_status: default_status(),
85100
default_type: default_type(),
86101
frontmatter: default_frontmatter(),

0 commit comments

Comments
 (0)