crates/forge/ents-forge/src/comment/cli.rs
| 1 | //! `git ents comment`'s argument grammar — `figue` derive definitions |
| 2 | //! only. |
| 3 | //! |
| 4 | //! Per this project's engineering conventions, this module carries no |
| 5 | //! logic: every doc comment here becomes `--help` text, and `git-ents`'s |
| 6 | //! own `exe` module is the only place a [`CommentAction`] variant is |
| 7 | //! interpreted. |
| 8 | |
| 9 | use std::path::PathBuf; |
| 10 | |
| 11 | use ents_attrs as ents; |
| 12 | use facet::Facet; |
| 13 | use figue as args; |
| 14 | |
| 15 | /// `git ents comment` actions. |
| 16 | #[derive(Facet)] |
| 17 | #[repr(u8)] |
| 18 | pub enum CommentAction { |
| 19 | /// List the comments recorded in this repository, each anchor |
| 20 | /// projected onto HEAD (or, with --worktree, onto the working tree). |
| 21 | /// |
| 22 | /// With --porcelain, emits a stable machine-readable form: |
| 23 | /// blank-line-separated records, each starting with the line |
| 24 | /// `<id> <state> <projection> <location>` — projection is current, |
| 25 | /// relocated, outdated, or deleted ("-" for a comment with no |
| 26 | /// anchor); location is `path:start-end`, `path` for a whole-file |
| 27 | /// anchor ("-" when there is no anchor or the file is gone) — |
| 28 | /// followed by optional `context <c>` and `parent <id>` lines, then |
| 29 | /// the body with every line prefixed by one tab. |
| 30 | List { |
| 31 | /// Project each anchor onto the working tree's on-disk bytes |
| 32 | /// instead of HEAD. |
| 33 | #[facet(args::named, default)] |
| 34 | worktree: bool, |
| 35 | /// Keep only comments in this state (e.g. open, resolved). |
| 36 | #[facet(args::named)] |
| 37 | state: Option<String>, |
| 38 | /// Shorthand for --state open. |
| 39 | #[facet(args::named, default)] |
| 40 | open: bool, |
| 41 | /// Keep only comments naming this context (a ref path below |
| 42 | /// refs/meta/, e.g. `issues/<id>`). |
| 43 | #[facet(args::named)] |
| 44 | context: Option<String>, |
| 45 | /// Emit the stable machine-readable form described above. |
| 46 | #[facet(args::named, default)] |
| 47 | porcelain: bool, |
| 48 | }, |
| 49 | /// Create a comment about something: anchor it to a file (at a |
| 50 | /// revision or in the working tree), name a context entity, reply to |
| 51 | /// a parent comment, or any combination. A comment about none of |
| 52 | /// these is refused. |
| 53 | Add { |
| 54 | /// Repository-relative path of the file the comment anchors to; |
| 55 | /// omit for a comment about a context or parent only. |
| 56 | #[facet(args::positional, default)] |
| 57 | path: Option<String>, |
| 58 | /// The comment's body text; omit to compose it in |
| 59 | /// $GIT_EDITOR/$EDITOR instead (lines starting with '#' are |
| 60 | /// stripped, and an empty body aborts the command). |
| 61 | #[facet(args::named, ents::compose)] |
| 62 | body: Option<String>, |
| 63 | /// Lines to anchor, as `<start>[:<end>]` (1-based, inclusive); |
| 64 | /// omit for a whole-file comment. |
| 65 | #[facet(args::named)] |
| 66 | lines: Option<String>, |
| 67 | /// Revision to anchor against. |
| 68 | #[facet(args::named, default = "HEAD")] |
| 69 | rev: String, |
| 70 | /// Anchor against the working tree's current on-disk bytes |
| 71 | /// instead of --rev. |
| 72 | #[facet(args::named, default)] |
| 73 | worktree: bool, |
| 74 | /// Canonical ref path below refs/meta/ of the entity this comment |
| 75 | /// belongs to, e.g. `issues/<id>` or `reviews/<target>/<member>`. |
| 76 | #[facet(args::named)] |
| 77 | context: Option<String>, |
| 78 | /// Id of the comment this one replies to. |
| 79 | #[facet(args::named)] |
| 80 | parent: Option<String>, |
| 81 | /// Key to sign with; defaults to `user.signingkey`. |
| 82 | #[facet(args::named)] |
| 83 | key: Option<PathBuf>, |
| 84 | }, |
| 85 | /// Reply to a comment: a new comment whose parent is the given id, |
| 86 | /// inheriting its aboutness from the thread — no anchor or context |
| 87 | /// required. |
| 88 | Reply { |
| 89 | /// The comment being replied to. |
| 90 | #[facet(args::positional)] |
| 91 | id: String, |
| 92 | /// The reply's body text. |
| 93 | #[facet(args::named)] |
| 94 | body: String, |
| 95 | /// Key to sign with; defaults to `user.signingkey`. |
| 96 | #[facet(args::named)] |
| 97 | key: Option<PathBuf>, |
| 98 | }, |
| 99 | /// Mark a comment resolved: an ordinary mutation commit on the |
| 100 | /// comment's own ref, never a deletion. |
| 101 | Resolve { |
| 102 | /// The comment to resolve. |
| 103 | #[facet(args::positional)] |
| 104 | id: String, |
| 105 | /// Key to sign with; defaults to `user.signingkey`. |
| 106 | #[facet(args::named)] |
| 107 | key: Option<PathBuf>, |
| 108 | }, |
| 109 | /// Reopen a resolved comment, the same way resolve marks it. |
| 110 | Reopen { |
| 111 | /// The comment to reopen. |
| 112 | #[facet(args::positional)] |
| 113 | id: String, |
| 114 | /// Key to sign with; defaults to `user.signingkey`. |
| 115 | #[facet(args::named)] |
| 116 | key: Option<PathBuf>, |
| 117 | }, |
| 118 | /// Show one comment: its state, context, parent, body, and — when |
| 119 | /// anchored — its anchor projected onto a revision or the working |
| 120 | /// tree. |
| 121 | Show { |
| 122 | /// The comment's id. |
| 123 | #[facet(args::positional)] |
| 124 | id: String, |
| 125 | /// Revision to project the comment's anchor onto. |
| 126 | #[facet(args::named, default = "HEAD")] |
| 127 | rev: String, |
| 128 | /// Project onto the working tree's on-disk bytes instead of |
| 129 | /// --rev. |
| 130 | #[facet(args::named, default)] |
| 131 | worktree: bool, |
| 132 | }, |
| 133 | } |