Compare commits
10 Commits
7cb09c11da
...
c3ae848f54
| Author | SHA1 | Date | |
|---|---|---|---|
| c3ae848f54 | |||
| 1d5a04088b | |||
| a330412732 | |||
| 43015a41d8 | |||
| 29f922aaca | |||
| ee6970fed0 | |||
| 880c471ff6 | |||
| e166049bae | |||
| 2c05b64d51 | |||
| 86ac30c11d |
@@ -0,0 +1,44 @@
|
||||
name: Claude Code Review
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
types: [opened, synchronize, ready_for_review, reopened]
|
||||
# Optional: Only run on specific file changes
|
||||
# paths:
|
||||
# - "src/**/*.ts"
|
||||
# - "src/**/*.tsx"
|
||||
# - "src/**/*.js"
|
||||
# - "src/**/*.jsx"
|
||||
|
||||
jobs:
|
||||
claude-review:
|
||||
# Optional: Filter by PR author
|
||||
# if: |
|
||||
# github.event.pull_request.user.login == 'external-contributor' ||
|
||||
# github.event.pull_request.user.login == 'new-developer' ||
|
||||
# github.event.pull_request.author_association == 'FIRST_TIME_CONTRIBUTOR'
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read
|
||||
pull-requests: read
|
||||
issues: read
|
||||
id-token: write
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 1
|
||||
|
||||
- name: Run Claude Code Review
|
||||
id: claude-review
|
||||
uses: anthropics/claude-code-action@v1
|
||||
with:
|
||||
claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
|
||||
plugin_marketplaces: 'https://github.com/anthropics/claude-code.git'
|
||||
plugins: 'code-review@claude-code-plugins'
|
||||
prompt: '/code-review:code-review ${{ github.repository }}/pull/${{ github.event.pull_request.number }}'
|
||||
# See https://github.com/anthropics/claude-code-action/blob/main/docs/usage.md
|
||||
# or https://code.claude.com/docs/en/cli-reference for available options
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
name: Claude Code
|
||||
|
||||
on:
|
||||
issue_comment:
|
||||
types: [created]
|
||||
pull_request_review_comment:
|
||||
types: [created]
|
||||
issues:
|
||||
types: [opened, assigned]
|
||||
pull_request_review:
|
||||
types: [submitted]
|
||||
|
||||
jobs:
|
||||
claude:
|
||||
if: |
|
||||
(github.event_name == 'issue_comment' && contains(github.event.comment.body, '@claude')) ||
|
||||
(github.event_name == 'pull_request_review_comment' && contains(github.event.comment.body, '@claude')) ||
|
||||
(github.event_name == 'pull_request_review' && contains(github.event.review.body, '@claude')) ||
|
||||
(github.event_name == 'issues' && (contains(github.event.issue.body, '@claude') || contains(github.event.issue.title, '@claude')))
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read
|
||||
pull-requests: read
|
||||
issues: read
|
||||
id-token: write
|
||||
actions: read # Required for Claude to read CI results on PRs
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 1
|
||||
|
||||
- name: Run Claude Code
|
||||
id: claude
|
||||
uses: anthropics/claude-code-action@v1
|
||||
with:
|
||||
claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
|
||||
|
||||
# This is an optional setting that allows Claude to read CI results on PRs
|
||||
additional_permissions: |
|
||||
actions: read
|
||||
|
||||
# Optional: Give a custom prompt to Claude. If this is not specified, Claude will perform the instructions specified in the comment that tagged it.
|
||||
# prompt: 'Update the pull request description to include a summary of changes.'
|
||||
|
||||
# Optional: Add claude_args to customize behavior and configuration
|
||||
# See https://github.com/anthropics/claude-code-action/blob/main/docs/usage.md
|
||||
# or https://code.claude.com/docs/en/cli-reference for available options
|
||||
# claude_args: '--allowed-tools Bash(gh pr:*)'
|
||||
|
||||
+382
-366
File diff suppressed because it is too large
Load Diff
+33
-4
@@ -72,6 +72,8 @@ pub enum Binding {
|
||||
},
|
||||
/// A prefix sub-keymap (Emacs-style).
|
||||
Prefix(Arc<Keymap>),
|
||||
/// A sequence of commands executed in order, concatenating their effects.
|
||||
Sequence(Vec<(&'static str, Vec<String>)>),
|
||||
}
|
||||
|
||||
/// A keymap maps key patterns to bindings (command names or prefix sub-keymaps).
|
||||
@@ -121,6 +123,17 @@ impl Keymap {
|
||||
.insert(KeyPattern::Key(key, mods), Binding::Prefix(sub));
|
||||
}
|
||||
|
||||
/// Bind a key to a sequence of commands (executed in order).
|
||||
pub fn bind_seq(
|
||||
&mut self,
|
||||
key: KeyCode,
|
||||
mods: KeyModifiers,
|
||||
steps: Vec<(&'static str, Vec<String>)>,
|
||||
) {
|
||||
self.bindings
|
||||
.insert(KeyPattern::Key(key, mods), Binding::Sequence(steps));
|
||||
}
|
||||
|
||||
/// Bind a catch-all for any Char key.
|
||||
pub fn bind_any_char(&mut self, name: &'static str, args: Vec<String>) {
|
||||
self.bindings
|
||||
@@ -173,6 +186,14 @@ impl Keymap {
|
||||
Some(cmd.execute(ctx))
|
||||
}
|
||||
Binding::Prefix(sub) => Some(vec![Box::new(SetTransientKeymap(sub.clone()))]),
|
||||
Binding::Sequence(steps) => {
|
||||
let mut effects: Vec<Box<dyn Effect>> = Vec::new();
|
||||
for (name, args) in steps {
|
||||
let cmd = registry.interactive(name, args, ctx).ok()?;
|
||||
effects.extend(cmd.execute(ctx));
|
||||
}
|
||||
Some(effects)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -360,7 +381,11 @@ impl KeymapSet {
|
||||
// Drill into aggregated cell / view history / add row
|
||||
normal.bind(KeyCode::Char('>'), none, "drill-into-cell");
|
||||
normal.bind(KeyCode::Char('<'), none, "view-back");
|
||||
normal.bind(KeyCode::Char('o'), none, "open-record-row");
|
||||
normal.bind_seq(
|
||||
KeyCode::Char('o'),
|
||||
none,
|
||||
vec![("add-record-row", vec![]), ("enter-edit-at-cursor", vec![])],
|
||||
);
|
||||
|
||||
// Records mode toggle and prune toggle
|
||||
normal.bind(KeyCode::Char('R'), none, "toggle-records-mode");
|
||||
@@ -384,7 +409,11 @@ impl KeymapSet {
|
||||
normal.bind_prefix(KeyCode::Char('y'), none, Arc::new(y_map));
|
||||
|
||||
let mut z_map = Keymap::new();
|
||||
z_map.bind(KeyCode::Char('Z'), none, "save-and-quit");
|
||||
z_map.bind_seq(
|
||||
KeyCode::Char('Z'),
|
||||
none,
|
||||
vec![("save", vec![]), ("force-quit", vec![])],
|
||||
);
|
||||
normal.bind_prefix(KeyCode::Char('Z'), none, Arc::new(z_map));
|
||||
|
||||
set.insert(ModeKey::Normal, Arc::new(normal));
|
||||
@@ -664,8 +693,8 @@ impl KeymapSet {
|
||||
let mut sm = Keymap::new();
|
||||
sm.bind(KeyCode::Esc, none, "exit-search-mode");
|
||||
sm.bind(KeyCode::Enter, none, "exit-search-mode");
|
||||
sm.bind(KeyCode::Backspace, none, "search-pop-char");
|
||||
sm.bind_any_char("search-append-char", vec![]);
|
||||
sm.bind_args(KeyCode::Backspace, none, "pop-char", vec!["search".into()]);
|
||||
sm.bind_any_char("append-char", vec!["search".into()]);
|
||||
set.insert(ModeKey::SearchMode, Arc::new(sm));
|
||||
|
||||
// ── Import wizard ────────────────────────────────────────────────
|
||||
|
||||
+4
-1
@@ -506,7 +506,10 @@ mod tests {
|
||||
let mut app = two_col_model();
|
||||
// Total rows: A, B, C + R0..R9 = 13 rows. Last row = 12.
|
||||
for i in 0..10 {
|
||||
app.model.category_mut("Row").unwrap().add_item(&format!("R{i}"));
|
||||
app.model
|
||||
.category_mut("Row")
|
||||
.unwrap()
|
||||
.add_item(&format!("R{i}"));
|
||||
}
|
||||
app.term_height = 13; // ~5 visible rows
|
||||
app.model.active_view_mut().selected = (0, 0);
|
||||
|
||||
+9
-4
@@ -96,7 +96,11 @@ impl Effect for RemoveFormula {
|
||||
pub struct EnterEditAtCursor;
|
||||
impl Effect for EnterEditAtCursor {
|
||||
fn apply(&self, app: &mut App) {
|
||||
let ctx = app.cmd_context(crossterm::event::KeyCode::Null, crossterm::event::KeyModifiers::NONE);
|
||||
app.rebuild_layout();
|
||||
let ctx = app.cmd_context(
|
||||
crossterm::event::KeyCode::Null,
|
||||
crossterm::event::KeyModifiers::NONE,
|
||||
);
|
||||
let value = ctx.display_value.clone();
|
||||
drop(ctx);
|
||||
app.buffers.insert("edit".to_string(), value);
|
||||
@@ -472,9 +476,10 @@ pub struct SetDrillPendingEdit {
|
||||
impl Effect for SetDrillPendingEdit {
|
||||
fn apply(&self, app: &mut App) {
|
||||
if let Some(drill) = &mut app.drill_state {
|
||||
drill
|
||||
.pending_edits
|
||||
.insert((self.record_idx, self.col_name.clone()), self.new_value.clone());
|
||||
drill.pending_edits.insert(
|
||||
(self.record_idx, self.col_name.clone()),
|
||||
self.new_value.clone(),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -59,7 +59,7 @@ impl<'a> GridWidget<'a> {
|
||||
let n_col_levels = layout.col_cats.len().max(1);
|
||||
let n_row_levels = layout.row_cats.len().max(1);
|
||||
|
||||
let col_widths = compute_col_widths(self.model, &layout, fmt_comma, fmt_decimals);
|
||||
let col_widths = compute_col_widths(self.model, layout, fmt_comma, fmt_decimals);
|
||||
|
||||
// ── Adaptive row header widths ───────────────────────────────
|
||||
let data_row_items: Vec<&Vec<String>> = layout
|
||||
|
||||
+1
-9
@@ -4,20 +4,12 @@ use ratatui::{
|
||||
style::{Color, Modifier, Style},
|
||||
widgets::Widget,
|
||||
};
|
||||
use unicode_width::UnicodeWidthStr;
|
||||
|
||||
use crate::model::Model;
|
||||
use crate::ui::app::AppMode;
|
||||
use crate::view::Axis;
|
||||
|
||||
fn axis_display(axis: Axis) -> (&'static str, Color) {
|
||||
match axis {
|
||||
Axis::Row => ("↕", Color::Green),
|
||||
Axis::Column => ("↔", Color::Blue),
|
||||
Axis::Page => ("☰", Color::Magenta),
|
||||
Axis::None => ("∅", Color::DarkGray),
|
||||
}
|
||||
}
|
||||
|
||||
pub struct TileBar<'a> {
|
||||
pub model: &'a Model,
|
||||
pub mode: &'a AppMode,
|
||||
|
||||
+4
-1
@@ -676,7 +676,10 @@ mod tests {
|
||||
let region_col = cols.iter().position(|c| c == "Region").unwrap();
|
||||
let key = layout.cell_key(0, region_col).unwrap();
|
||||
let display = layout.resolve_display(&key).unwrap();
|
||||
assert!(!display.is_empty(), "Region column should resolve to a value");
|
||||
assert!(
|
||||
!display.is_empty(),
|
||||
"Region column should resolve to a value"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
Reference in New Issue
Block a user