diffstalker 0.1.1 → 0.1.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/workflows/release.yml +13 -21
- package/dist/App.js +1 -1
- package/dist/components/BottomPane.js +1 -1
- package/dist/components/CompareView.js +1 -1
- package/dist/components/DiffView.js +1 -1
- package/dist/components/FileList.js +1 -1
- package/dist/components/HistoryDiffView.js +1 -1
- package/dist/components/ScrollableList.js +1 -1
- package/dist/components/TopPane.js +1 -1
- package/dist/hooks/useMouse.js +1 -1
- package/dist/utils/mouseCoordinates.js +1 -1
- package/package.json +2 -2
|
@@ -5,34 +5,26 @@ on:
|
|
|
5
5
|
tags:
|
|
6
6
|
- 'v*'
|
|
7
7
|
|
|
8
|
+
permissions:
|
|
9
|
+
id-token: write # Required for OIDC
|
|
10
|
+
contents: write # Required for GitHub release
|
|
11
|
+
|
|
8
12
|
jobs:
|
|
9
|
-
|
|
13
|
+
publish:
|
|
10
14
|
runs-on: ubuntu-latest
|
|
11
|
-
|
|
12
|
-
contents: write
|
|
13
|
-
id-token: write
|
|
14
|
-
|
|
15
|
+
environment: npm
|
|
15
16
|
steps:
|
|
16
|
-
-
|
|
17
|
-
uses: actions/checkout@v4
|
|
17
|
+
- uses: actions/checkout@v4
|
|
18
18
|
|
|
19
|
-
-
|
|
20
|
-
uses: actions/setup-node@v4
|
|
19
|
+
- uses: actions/setup-node@v4
|
|
21
20
|
with:
|
|
22
|
-
node-version: '
|
|
21
|
+
node-version: '24'
|
|
23
22
|
registry-url: 'https://registry.npmjs.org'
|
|
24
23
|
|
|
25
|
-
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
-
|
|
29
|
-
run: npm test
|
|
30
|
-
|
|
31
|
-
- name: Build
|
|
32
|
-
run: npm run build:prod
|
|
33
|
-
|
|
34
|
-
- name: Publish to npm
|
|
35
|
-
run: npm publish --provenance --access public
|
|
24
|
+
- run: npm ci
|
|
25
|
+
- run: npm run build:prod
|
|
26
|
+
- run: npm test
|
|
27
|
+
- run: npm publish --access public
|
|
36
28
|
|
|
37
29
|
- name: Create GitHub Release
|
|
38
30
|
uses: softprops/action-gh-release@v2
|
package/dist/App.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{jsx as i,jsxs as W}from"react/jsx-runtime";import{useState as u,useCallback as c,useMemo as vt,useEffect as M,useRef as _}from"react";import{Box as B,Text as A,useApp as Dt,useInput as Ht}from"ink";import{Header as Ft,getHeaderHeight as Lt}from"./components/Header.js";import{getFileAtIndex as Fe,getTotalFileCount as Mt}from"./components/FileList.js";import{getCommitIndexFromRow as At}from"./components/HistoryView.js";import{Footer as Et}from"./components/Footer.js";import{TopPane as Ot}from"./components/TopPane.js";import{BottomPane as Ut}from"./components/BottomPane.js";import{useWatcher as jt}from"./hooks/useWatcher.js";import{useGit as Nt}from"./hooks/useGit.js";import{useKeymap as Wt}from"./hooks/useKeymap.js";import{useMouse as _t}from"./hooks/useMouse.js";import{useTerminalSize as zt}from"./hooks/useTerminalSize.js";import{useLayout as Gt,SPLIT_RATIO_STEP as Le}from"./hooks/useLayout.js";import{useHistoryState as Kt}from"./hooks/useHistoryState.js";import{useCompareState as Qt}from"./hooks/useCompareState.js";import{getClickedFileIndex as
|
|
1
|
+
import{jsx as i,jsxs as W}from"react/jsx-runtime";import{useState as u,useCallback as c,useMemo as vt,useEffect as M,useRef as _}from"react";import{Box as B,Text as A,useApp as Dt,useInput as Ht}from"ink";import{Header as Ft,getHeaderHeight as Lt}from"./components/Header.js";import{getFileAtIndex as Fe,getTotalFileCount as Mt}from"./components/FileList.js";import{getCommitIndexFromRow as At}from"./components/HistoryView.js";import{Footer as Et}from"./components/Footer.js";import{TopPane as Ot}from"./components/TopPane.js";import{BottomPane as Ut}from"./components/BottomPane.js";import{useWatcher as jt}from"./hooks/useWatcher.js";import{useGit as Nt}from"./hooks/useGit.js";import{useKeymap as Wt}from"./hooks/useKeymap.js";import{useMouse as _t}from"./hooks/useMouse.js";import{useTerminalSize as zt}from"./hooks/useTerminalSize.js";import{useLayout as Gt,SPLIT_RATIO_STEP as Le}from"./hooks/useLayout.js";import{useHistoryState as Kt}from"./hooks/useHistoryState.js";import{useCompareState as Qt}from"./hooks/useCompareState.js";import{getClickedFileIndex as Xt,getClickedTab as Yt,getFooterLeftClick as qt,isButtonAreaClick as Jt,isInPane as oe}from"./utils/mouseCoordinates.js";import{saveConfig as Me}from"./config.js";import{ThemePicker as Vt}from"./components/ThemePicker.js";import{HotkeysModal as Zt}from"./components/HotkeysModal.js";import{BaseBranchPicker as $t}from"./components/BaseBranchPicker.js";export function App({config:p,initialPath:Ae}){const{exit:Ee}=Dt(),{rows:k,columns:r}=zt(),{state:z,setEnabled:Oe}=jt(p.watcherEnabled,p.targetFile,p.debug),R=Ae??z.path??process.cwd(),{status:v,diff:ie,selectedFile:Ue,isLoading:ne,error:re,selectFile:se,stage:g,unstage:y,discard:je,stageAll:Ne,unstageAll:We,commit:_e,refresh:ze,getHeadCommitMessage:Ge,compareDiff:w,compareLoading:Ke,compareError:Qe,refreshCompareDiff:Xe,getCandidateBaseBranches:Ye,setCompareBaseBranch:qe,historySelectedCommit:ae,historyCommitDiff:le,selectHistoryCommit:Je,compareSelectionDiff:Ve,selectCompareCommit:Ze}=Nt(R),m=v?.files??[],s=Mt(m),ce=m.filter(e=>e.staged).length,[l,f]=u("files"),[t,me]=u("diff"),[C,E]=u(0),[D,G]=u(null),[fe,$e]=u(!1),[de,et]=u(p.theme),[H,S]=u(null),[K,he]=u(!1),ue=Lt(R,v?.branch??null,z,r,re,ne),tt=ue-1,{topPaneHeight:Q,bottomPaneHeight:ot,paneBoundaries:pe,splitRatio:X,adjustSplitRatio:ge,fileListScrollOffset:Y,diffScrollOffset:it,historyScrollOffset:O,compareScrollOffset:U,setDiffScrollOffset:x,setHistoryScrollOffset:q,setCompareScrollOffset:nt,scrollDiff:P,scrollFileList:ye,scrollHistory:Ce,scrollCompare:Se}=Gt(k,r,m,C,ie,t,void 0,p.splitRatio,tt),{commits:j,historySelectedIndex:rt,setHistorySelectedIndex:F,historyDiffTotalRows:Te,navigateHistoryUp:be,navigateHistoryDown:we,historyTotalRows:xe}=Kt({repoPath:R,isActive:t==="history",selectHistoryCommit:Je,historyCommitDiff:le,historySelectedCommit:ae,terminalWidth:r,topPaneHeight:Q,historyScrollOffset:O,setHistoryScrollOffset:q,setDiffScrollOffset:x,status:v}),{includeUncommitted:st,compareListSelection:d,baseBranchCandidates:at,showBaseBranchPicker:J,compareTotalItems:V,compareDiffTotalRows:I,setCompareSelectedIndex:Pe,toggleIncludeUncommitted:lt,openBaseBranchPicker:ct,closeBaseBranchPicker:mt,selectBaseBranch:ft,navigateCompareUp:Ie,navigateCompareDown:Be,markSelectionInitialized:ke,getItemIndexFromRow:Re}=Qt({repoPath:R,isActive:t==="compare",compareDiff:w,refreshCompareDiff:Xe,getCandidateBaseBranches:Ye,setCompareBaseBranch:qe,selectCompareCommit:Ze,topPaneHeight:Q,compareScrollOffset:U,setCompareScrollOffset:nt,setDiffScrollOffset:x,status:v}),ve=_(pe);ve.current=pe;const dt=_(p.splitRatio);M(()=>{if(X!==dt.current){const e=setTimeout(()=>Me({splitRatio:X}),500);return()=>clearTimeout(e)}},[X]);const a=vt(()=>Fe(m,C),[m,C]);M(()=>{s>0&&C>=s&&E(Math.max(0,s-1))},[s,C]),M(()=>{se(a)},[a,se]),M(()=>{(t==="diff"||t==="commit")&&x(0)},[C,t,x]);const T=c(e=>{me(e),f({diff:"files",commit:"commit",history:"history",compare:"compare"}[e])},[]),De=_(()=>{}),ht=c(e=>{const{x:h,y:b,type:N,button:ee}=e,{stagingPaneStart:L,fileListEnd:te,diffPaneStart:It,diffPaneEnd:Bt,footerRow:kt}=ve.current;if(N==="click"){if(H!==null){S(null);return}if(b===kt&&ee==="left"){const n=Yt(h,r);if(n){T(n);return}const o=qt(h);if(o==="hotkeys"){S("hotkeys");return}else if(o==="mouse-mode"){De.current();return}else if(o==="auto-tab"){he(Rt=>!Rt);return}}if(oe(b,L+1,te)){if(t==="diff"||t==="commit"){const n=Xt(b,Y,m,L,te);if(n>=0&&n<s){E(n),f("files");const o=Fe(m,n);o&&(ee==="right"&&!o.staged&&o.status!=="untracked"?G(o):ee==="left"&&Jt(h)&&(o.staged?y(o):g(o)));return}}else if(t==="history"){const n=b-L-1,o=At(n,j,r,O);if(o>=0&&o<j.length){F(o),f("history"),x(0);return}}else if(t==="compare"&&w){const n=b-L-1+U,o=Re(n);if(o>=0&&o<V){ke(),Pe(o),f("compare");return}}}oe(b,It,Bt)&&f(t)}else if(N==="scroll-up"||N==="scroll-down"){const n=N==="scroll-up"?"up":"down";if(oe(b,L,te))t==="diff"||t==="commit"?ye(n):t==="history"?Ce(n,xe):t==="compare"&&Se(n,V);else{let o;t==="compare"&&d?.type!=="commit"?o=I:t==="history"&&(o=Te),P(n,3,o)}}},[r,Y,m,s,t,j,w,V,g,y,P,ye,Ce,Se,O,U,x,F,Pe,ke,Re,d?.type,I,Te,xe,H]),ut=fe||J,{mouseEnabled:pt,toggleMouse:He}=_t(ht,ut);De.current=He;const Z=_(s);M(()=>{if(!K){Z.current=s;return}const e=Z.current;e===0&&s>0?T("diff"):e>0&&s===0&&(F(0),q(0),T("history")),Z.current=s},[s,K,T,F,q]);const gt=c(()=>{if(l==="files")E(e=>Math.max(0,e-1));else if(l==="diff"){const e=t==="compare"&&d?.type!=="commit"?I:void 0;P("up",3,e)}else l==="history"?be():l==="compare"&&Ie()},[l,t,d?.type,I,P,be,Ie]),yt=c(()=>{if(l==="files")E(e=>Math.min(s-1,e+1));else if(l==="diff"){const e=t==="compare"&&d?.type!=="commit"?I:void 0;P("down",3,e)}else l==="history"?we():l==="compare"&&Be()},[l,t,d?.type,I,s,P,we,Be]),Ct=c(()=>{t==="diff"||t==="commit"?f(e=>e==="files"?"diff":"files"):t==="history"?f(e=>e==="history"?"diff":"history"):t==="compare"&&f(e=>e==="compare"?"diff":"compare")},[t]),St=c(async()=>{a&&!a.staged&&await g(a)},[a,g]),Tt=c(async()=>{a?.staged&&await y(a)},[a,y]),bt=c(async()=>{a&&(a.staged?await y(a):await g(a))},[a,g,y]),wt=c(()=>T("commit"),[T]),xt=c(()=>{me("diff"),f("files")},[]),Pt=c(e=>{et(e),S(null),Me({theme:e})},[]);Wt({onStage:St,onUnstage:Tt,onStageAll:Ne,onUnstageAll:We,onCommit:wt,onQuit:Ee,onRefresh:ze,onNavigateUp:gt,onNavigateDown:yt,onTogglePane:Ct,onSwitchTab:T,onSelect:bt,onToggleIncludeUncommitted:lt,onCycleBaseBranch:ct,onOpenThemePicker:()=>S("theme"),onShrinkTopPane:()=>ge(-Le),onGrowTopPane:()=>ge(Le),onOpenHotkeysModal:()=>S("hotkeys"),onToggleMouse:He,onToggleFollow:()=>Oe(e=>!e),onToggleAutoTab:()=>he(e=>!e)},l,fe||H!==null||J),Ht((e,h)=>{D&&(e==="y"||e==="Y"?(je(D),G(null)):(e==="n"||e==="N"||h.escape)&&G(null))},{isActive:!!D});const $=()=>i(A,{dimColor:!0,children:"\u2500".repeat(r)});return W(B,{flexDirection:"column",height:k,width:r,overflowX:"hidden",children:[i(B,{height:ue,width:r,children:i(Ft,{repoPath:R,branch:v?.branch??null,isLoading:ne,error:re,debug:p.debug,watcherState:z,width:r})}),i($,{}),i(Ot,{bottomTab:t,currentPane:l,terminalWidth:r,topPaneHeight:Q,files:m,selectedIndex:C,fileListScrollOffset:Y,stagedCount:ce,onStage:g,onUnstage:y,commits:j,historySelectedIndex:rt,historyScrollOffset:O,onSelectHistoryCommit:(e,h)=>F(h),compareDiff:w,compareListSelection:d,compareScrollOffset:U,includeUncommitted:st}),i($,{}),i(Ut,{bottomTab:t,currentPane:l,terminalWidth:r,bottomPaneHeight:ot,diffScrollOffset:it,currentTheme:de,diff:ie,selectedFile:Ue,stagedCount:ce,onCommit:_e,onCommitCancel:xt,getHeadCommitMessage:Ge,onCommitInputFocusChange:$e,historySelectedCommit:ae,historyCommitDiff:le,compareDiff:w,compareLoading:Ke,compareError:Qe,compareListSelection:d,compareSelectionDiff:Ve}),i($,{}),D?W(B,{children:[W(A,{color:"yellow",bold:!0,children:["Discard changes to"," "]}),i(A,{color:"cyan",children:D.path}),W(A,{color:"yellow",bold:!0,children:["?"," "]}),i(A,{dimColor:!0,children:"(y/n)"})]}):i(Et,{activeTab:t,mouseEnabled:pt,autoTabEnabled:K}),H==="theme"&&i(B,{position:"absolute",marginTop:0,marginLeft:0,children:i(Vt,{currentTheme:de,onSelect:Pt,onCancel:()=>S(null),width:r,height:k})}),H==="hotkeys"&&i(B,{position:"absolute",marginTop:0,marginLeft:0,children:i(Zt,{onClose:()=>S(null),width:r,height:k})}),J&&i(B,{position:"absolute",marginTop:0,marginLeft:0,children:i($t,{candidates:at,currentBranch:w?.baseBranch??null,onSelect:ft,onCancel:mt,width:r,height:k})})]})}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{jsx as r,jsxs as
|
|
1
|
+
import{jsx as r,jsxs as m}from"react/jsx-runtime";import{Box as x,Text as o}from"ink";import{DiffView as C}from"./DiffView.js";import{CommitPanel as O}from"./CommitPanel.js";import{HistoryDiffView as _}from"./HistoryDiffView.js";import{CompareView as A}from"./CompareView.js";import{shortenPath as g}from"../utils/formatPath.js";export function BottomPane({bottomTab:e,currentPane:n,terminalWidth:i,bottomPaneHeight:f,diffScrollOffset:d,currentTheme:h,diff:a,selectedFile:c,stagedCount:j,onCommit:y,onCommitCancel:H,getHeadCommitMessage:v,onCommitInputFocusChange:I,historySelectedCommit:t,historyCommitDiff:M,compareDiff:u,compareLoading:V,compareError:p,compareListSelection:s,compareSelectionDiff:w}){const B=n!=="files"&&n!=="history"&&n!=="compare",D=()=>{if(c&&e==="diff")return r(o,{dimColor:!0,children:g(c.path,i-10)});if(e==="history"&&t)return m(o,{dimColor:!0,children:[t.shortHash," - ",t.message.slice(0,50)]});if(e==="compare"&&s)if(s.type==="commit"){const l=u?.commits[s.index];return m(o,{dimColor:!0,children:[l?.shortHash??""," - ",l?.message.slice(0,40)??""]})}else{const l=u?.files[s.index]?.path??"";return r(o,{dimColor:!0,children:g(l,i-10)})}return null},F=()=>e==="diff"?r(C,{diff:a,filePath:c?.path,maxHeight:f-1,scrollOffset:d,theme:h,width:i}):e==="commit"?r(O,{isActive:n==="commit",stagedCount:j,onCommit:y,onCancel:H,getHeadMessage:v,onInputFocusChange:I}):e==="history"?r(_,{commit:t,diff:M,maxHeight:f-1,scrollOffset:d,theme:h,width:i}):V?r(o,{dimColor:!0,children:"Loading compare diff..."}):p?r(o,{color:"red",children:p}):s?.type==="commit"&&w?r(C,{diff:w,maxHeight:f-1,scrollOffset:d,theme:h,width:i}):u?r(A,{compareDiff:u,isLoading:!1,error:null,scrollOffset:d,maxHeight:f-1,theme:h,width:i}):r(o,{dimColor:!0,children:"No compare diff available"});return m(x,{flexDirection:"column",height:f,width:i,overflowX:"hidden",overflowY:"hidden",children:[m(x,{width:i,children:[r(o,{bold:!0,color:B?"cyan":void 0,children:e==="commit"?"COMMIT":"DIFF"}),r(x,{flexGrow:1,justifyContent:"flex-end",children:D()})]}),F()]})}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{jsx as r,jsxs as
|
|
1
|
+
import{jsx as r,jsxs as a}from"react/jsx-runtime";import{useMemo as h}from"react";import{Box as e,Text as o}from"ink";import{DiffView as c}from"./DiffView.js";import{buildCombinedCompareDiff as u}from"../utils/rowCalculations.js";export{buildCombinedCompareDiff,getCompareDiffTotalRows,getFileScrollOffset}from"../utils/rowCalculations.js";export function CompareView({compareDiff:i,isLoading:d,error:n,scrollOffset:t,maxHeight:f,theme:m="dark",width:l}){const s=h(()=>u(i),[i]);return d?r(e,{paddingX:1,children:r(o,{dimColor:!0,children:"Loading diff..."})}):n?r(e,{paddingX:1,children:r(o,{color:"red",children:n})}):i?i.files.length===0?r(e,{paddingX:1,children:a(o,{dimColor:!0,children:["No changes compared to ",i.baseBranch]})}):r(c,{diff:s,maxHeight:f,scrollOffset:t,theme:m,width:l}):r(e,{paddingX:1,children:r(o,{dimColor:!0,children:"No base branch found (no origin/main or origin/master)"})})}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{jsx as
|
|
1
|
+
import{jsx as a,jsxs as f}from"react/jsx-runtime";import{useMemo as I}from"react";import{Box as p,Text as u}from"ink";import{createEmphasize as R,common as z}from"emphasize";import L from"fast-diff";import{getTheme as G}from"../themes.js";import{ScrollableList as U}from"./ScrollableList.js";import{isDisplayableDiffLine as W}from"../utils/diffFilters.js";const X=R(z);function b(t,e){return e<=0||t.length<=e?t:e<=1?"\u2026":t.slice(0,e-1)+"\u2026"}const q={ts:"typescript",tsx:"typescript",js:"javascript",jsx:"javascript",mjs:"javascript",cjs:"javascript",py:"python",rb:"ruby",rs:"rust",go:"go",java:"java",c:"c",cpp:"cpp",h:"c",hpp:"cpp",cs:"csharp",php:"php",sh:"bash",bash:"bash",zsh:"bash",json:"json",yaml:"yaml",yml:"yaml",md:"markdown",html:"html",htm:"html",css:"css",scss:"scss",sass:"scss",less:"less",sql:"sql",xml:"xml",toml:"ini",ini:"ini",dockerfile:"dockerfile",makefile:"makefile",lua:"lua",vim:"vim",swift:"swift",kt:"kotlin",kts:"kotlin",scala:"scala",r:"r",pl:"perl",ex:"elixir",exs:"elixir",erl:"erlang",hs:"haskell",clj:"clojure",ml:"ocaml",fs:"fsharp",vue:"xml",svelte:"xml"};function O(t){if(!t)return;const e=t.split("/").pop()?.toLowerCase()??"";if(e==="dockerfile")return"dockerfile";if(e==="makefile"||e==="gnumakefile")return"makefile";const n=e.split(".").pop()?.toLowerCase();return n?q[n]||n:void 0}function P(t,e){if(!e||!t.trim())return t;try{return X.highlight(e,t).value}catch{return t}}function Q(t){let e=0;for(const n of t)n.oldLineNum&&n.oldLineNum>e&&(e=n.oldLineNum),n.newLineNum&&n.newLineNum>e&&(e=n.newLineNum);return Math.max(3,String(e).length)}function N(t){return t.type==="addition"||t.type==="deletion"||t.type==="context"&&t.content.startsWith(" ")?t.content.slice(1):t.content}const F=3;function $(t){if(t.length===0)return t;const e=[];for(let n=0;n<t.length;n++){const r=t[n];if(!r.isChange&&r.text.length<F){const o=n>0&&e[e.length-1]?.isChange,s=n<t.length-1&&t[n+1]?.isChange;if(o||s){o&&e.length>0?e[e.length-1].text+=r.text:e.push({text:r.text,isChange:!0});continue}}e.length>0&&e[e.length-1].isChange===r.isChange?e[e.length-1].text+=r.text:e.push({...r})}return e}function K(t,e){const n=L(t,e);let r=[],o=[];for(const[s,i]of n)s===L.EQUAL?(r.push({text:i,isChange:!1}),o.push({text:i,isChange:!1})):s===L.DELETE?r.push({text:i,isChange:!0}):s===L.INSERT&&o.push({text:i,isChange:!0});return r=$(r),o=$(o),{oldSegments:r,newSegments:o}}function V(t,e){if(t.length===0&&e.length===0)return 1;if(t.length===0||e.length===0)return 0;const n=L(t,e);let r=0,o=0;for(const[s,i]of n)s===L.EQUAL&&(r+=i.length),o+=i.length;return o>0?r/o:0}const Y=.35;function J(t){const e=new Map;for(let n=0;n<t.length-1;n++){const r=t[n],o=t[n+1];if(r.type==="deletion"&&o.type==="addition"){const s=N(r),i=N(o);if(V(s,i)>=Y){const d={deletion:r,addition:o,deletionIndex:n,additionIndex:n+1};e.set(n,d),e.set(n+1,d)}}}return e}function Z(t,e){const n=[];let r=e;for(const o of t){if(r<=0)break;if(o.text.length<=r)n.push(o),r-=o.text.length;else{const s=o.text.slice(0,r-1)+"\u2026";n.push({...o,text:s});break}}return n}function M({segments:t,isAddition:e,theme:n,maxWidth:r}){const{colors:o}=n,s=e?o.addBg:o.delBg,i=e?o.addHighlight:o.delHighlight,d=r?Z(t,r):t;return a(u,{backgroundColor:s,children:d.map((x,g)=>a(u,{color:o.text,backgroundColor:x.isChange?i:s,children:x.text||(g===d.length-1?" ":"")},g))})}function tt({line:t,lineNumWidth:e,language:n,wordDiffSegments:r,theme:o,maxWidth:s}){const{colors:i}=o,d=s?s-2:void 0;if(t.type==="header"){const c=t.content;if(c.startsWith("diff --git")){const m=c.match(/diff --git a\/.+ b\/(.+)$/);if(m){const C=d?d-6:void 0,y=C?b(m[1],C):m[1];return a(p,{children:f(u,{color:"cyan",bold:!0,children:["\u2500\u2500 ",y," \u2500\u2500"]})})}}const k=d?b(c,d):c;return a(p,{children:a(u,{dimColor:!0,children:k})})}if(t.type==="hunk"){const c=t.content.match(/^@@ -(\d+)(?:,(\d+))? \+(\d+)(?:,(\d+))? @@(.*)$/);if(c){const m=parseInt(c[1],10),C=c[2]?parseInt(c[2],10):1,y=parseInt(c[3],10),v=c[4]?parseInt(c[4],10):1,E=c[5].trim(),T=m+C-1,H=y+v-1,A=C===1?`${m}`:`${m}-${T}`,_=v===1?`${y}`:`${y}-${H}`,B=`Lines ${A} \u2192 ${_}`,S=d?d-B.length-1:void 0,D=E&&S&&S>3?b(E,S):"";return f(p,{children:[a(u,{color:"cyan",dimColor:!0,children:B}),D&&f(u,{color:"gray",children:[" ",D]})]})}const k=d?b(t.content,d):t.content;return a(u,{color:"cyan",dimColor:!0,children:k})}const x=t.type==="addition"?t.newLineNum:t.type==="deletion"?t.oldLineNum:t.oldLineNum??t.newLineNum,g=x!==void 0?String(x).padStart(e," "):" ".repeat(e),w=N(t),l=s?s-e-5:void 0,h=l?b(w,l):w;if(t.type==="addition")return f(p,{children:[f(u,{backgroundColor:i.addBg,color:i.addLineNum,children:[g," "]}),f(u,{backgroundColor:i.addBg,color:i.addSymbol,bold:!0,children:["+"," "]}),r?a(M,{segments:r,isAddition:!0,theme:o,maxWidth:l}):a(u,{backgroundColor:i.addBg,color:i.text,children:h||" "})]});if(t.type==="deletion")return f(p,{children:[f(u,{backgroundColor:i.delBg,color:i.delLineNum,children:[g," "]}),f(u,{backgroundColor:i.delBg,color:i.delSymbol,bold:!0,children:["-"," "]}),r?a(M,{segments:r,isAddition:!1,theme:o,maxWidth:l}):a(u,{backgroundColor:i.delBg,color:i.text,children:h||" "})]});const j=P(h,n);return f(p,{children:[f(u,{color:i.contextLineNum,children:[g," "]}),a(u,{children:j})]})}export function DiffView({diff:t,filePath:e,maxHeight:n=20,scrollOffset:r=0,theme:o="dark",width:s}){const i=I(()=>G(o),[o]),d=I(()=>O(e),[e]),x=I(()=>{if(!t)return new Map;const l=J(t.lines),h=new Map;for(const[j,c]of l)if(j===c.deletionIndex){const k=N(c.deletion),m=N(c.addition),{oldSegments:C,newSegments:y}=K(k,m);h.set(c.deletionIndex,C),h.set(c.additionIndex,y)}return h},[t]),g=I(()=>t?.lines.map((l,h)=>({line:l,originalIndex:h})).filter(({line:l})=>W(l))??[],[t]);if(!t||g.length===0)return a(p,{paddingX:1,children:a(u,{dimColor:!0,children:"No diff to display"})});const w=Q(g.map(l=>l.line));return a(p,{flexDirection:"column",paddingX:1,overflowX:"hidden",children:a(U,{items:g,maxHeight:n,scrollOffset:r,getKey:l=>`${l.originalIndex}`,renderItem:l=>{const h=x.get(l.originalIndex);return a(tt,{line:l.line,lineNumWidth:w,language:d,wordDiffSegments:h,theme:i,maxWidth:s})}})})}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{
|
|
1
|
+
import{jsx as d,jsxs as l}from"react/jsx-runtime";import{Box as x,Text as t}from"ink";import{shortenPath as C}from"../utils/formatPath.js";import{categorizeFiles as F}from"../utils/fileCategories.js";function P(e){switch(e){case"modified":return"M";case"added":return"A";case"deleted":return"D";case"untracked":return"?";case"renamed":return"R";case"copied":return"C";default:return" "}}function b(e){switch(e){case"modified":return"yellow";case"added":return"green";case"deleted":return"red";case"untracked":return"gray";case"renamed":return"blue";case"copied":return"cyan";default:return"white"}}function k(e,s){if(e===void 0&&s===void 0)return null;const i=e??0,o=s??0;if(i===0&&o===0)return null;const c=[];return i>0&&c.push(`+${i}`),o>0&&c.push(`-${o}`),c.join(" ")}function j({file:e,isSelected:s,isFocused:i,maxPathLength:o}){const c=P(e.status),f=b(e.status),g=e.staged?"[-]":"[+]",h=e.staged?"red":"green",u=k(e.insertions,e.deletions),a=s&&i,r=u?u.length+1:0,p=o-r,m=C(e.path,p);return l(x,{children:[d(t,{color:a?"cyan":void 0,bold:a,children:a?"\u25B8 ":" "}),l(t,{color:h,children:[g," "]}),l(t,{color:f,children:[c," "]}),d(t,{color:a?"cyan":void 0,inverse:a,children:m}),e.originalPath&&l(t,{dimColor:!0,children:[" \u2190 ",C(e.originalPath,30)]}),u&&l(t,{children:[d(t,{dimColor:!0,children:" "}),e.insertions!==void 0&&e.insertions>0&&l(t,{color:"green",children:["+",e.insertions]}),e.insertions!==void 0&&e.insertions>0&&e.deletions!==void 0&&e.deletions>0&&d(t,{dimColor:!0,children:" "}),e.deletions!==void 0&&e.deletions>0&&l(t,{color:"red",children:["-",e.deletions]})]})]})}export function FileList({files:e,selectedIndex:s,isFocused:i,scrollOffset:o=0,maxHeight:c,width:f=80}){const g=f-10,{modified:h,untracked:u,staged:a}=F(e);if(e.length===0)return d(x,{flexDirection:"column",children:d(t,{dimColor:!0,children:" No changes"})});const r=[];let p=0;h.length>0&&(r.push({type:"header",content:"Modified:",headerColor:"yellow"}),h.forEach(n=>{r.push({type:"file",file:n,fileIndex:p++})})),u.length>0&&(h.length>0&&r.push({type:"spacer"}),r.push({type:"header",content:"Untracked:",headerColor:"gray"}),u.forEach(n=>{r.push({type:"file",file:n,fileIndex:p++})})),a.length>0&&((h.length>0||u.length>0)&&r.push({type:"spacer"}),r.push({type:"header",content:"Staged:",headerColor:"green"}),a.forEach(n=>{r.push({type:"file",file:n,fileIndex:p++})}));const m=c?r.slice(o,o+c):r.slice(o);return d(x,{flexDirection:"column",children:m.map((n,I)=>{const y=`row-${o+I}`;return n.type==="header"?d(t,{bold:!0,color:n.headerColor,children:n.content},y):n.type==="spacer"?d(t,{children:" "},y):n.type==="file"&&n.file!==void 0&&n.fileIndex!==void 0?d(j,{file:n.file,isSelected:n.fileIndex===s,isFocused:i,maxPathLength:g},y):null})})}export function getFileAtIndex(e,s){const{ordered:i}=F(e);return i[s]??null}export function getTotalFileCount(e){return e.length}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{jsx as i,jsxs as
|
|
1
|
+
import{jsx as i,jsxs as w}from"react/jsx-runtime";import{useMemo as x}from"react";import{Box as r,Text as n}from"ink";import{DiffView as g}from"./DiffView.js";import{buildHistoryDiffRows as R}from"../utils/rowCalculations.js";import{isDisplayableDiffLine as b}from"../utils/diffFilters.js";export{buildHistoryDiffRows,getHistoryDiffTotalRows}from"../utils/rowCalculations.js";export function HistoryDiffView({commit:s,diff:t,scrollOffset:l,maxHeight:d,theme:m="dark",width:a}){const c=x(()=>R(s,t),[s,t]),u=x(()=>{for(let e=0;e<c.length;e++)if(c[e].type==="diff-line")return e;return c.length},[c]),f=c.slice(l,l+d);if(!s)return i(r,{paddingX:1,children:i(n,{dimColor:!0,children:"Select a commit to view its diff"})});if(!t||t.lines.length===0)return w(r,{flexDirection:"column",children:[f.map((e,h)=>{const o=`row-${l+h}`;return e.type==="commit-header"?i(r,{children:i(n,{color:"yellow",children:e.content})},o):e.type==="commit-message"?i(r,{children:i(n,{children:e.content})},o):e.type==="spacer"?i(r,{children:i(n,{children:" "})},o):null}),i(r,{children:i(n,{dimColor:!0,children:"No changes in this commit"})})]});const p=t.lines.filter(b);if(l>=u)return i(g,{diff:{raw:t.raw,lines:p},maxHeight:d,scrollOffset:l-u,theme:m,width:a});const D=f.filter(e=>e.type!=="diff-line"),y=d-D.length;return w(r,{flexDirection:"column",overflowX:"hidden",children:[f.map((e,h)=>{const o=`row-${l+h}`;return e.type==="commit-header"?i(r,{children:i(n,{color:"yellow",children:e.content})},o):e.type==="commit-message"?i(r,{children:i(n,{children:e.content})},o):e.type==="spacer"?i(r,{children:i(n,{children:" "})},o):null}),y>0&&i(g,{diff:{raw:t.raw,lines:p},maxHeight:y,scrollOffset:0,theme:m,width:a})]})}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{jsxs as
|
|
1
|
+
import{jsxs as m,jsx as j}from"react/jsx-runtime";import{Box as d,Text as M}from"ink";export function ScrollableList({items:n,renderItem:r,maxHeight:a,scrollOffset:e,getKey:i,header:t,showIndicators:u=!0}){let o=a;t&&o--;const l=e>0,h=n.length,g=h>e+o;u&&(l&&o--,g&&o--),o=Math.max(1,o);const b=n.slice(e,e+o),c=h>e+o,p=e,C=h-e-b.length;return m(d,{flexDirection:"column",overflowX:"hidden",children:[t,u&&l&&m(M,{dimColor:!0,children:["\u2191 ",p," more above"]}),b.map((v,x)=>j(d,{overflowX:"hidden",children:r(v,e+x)},`${e}-${x}-${i(v,e+x)}`)),u&&c&&m(M,{dimColor:!0,children:["\u2193 ",C," more below"]})]})}export function getMaxScrollOffset(n,r,a=!1,e=!0){let i=r;return a&&i--,e&&n>i&&(i-=2),i=Math.max(1,i),Math.max(0,n-i)}export function getVisibleItemCount(n,r,a,e=!1,i=!0){let t=r;return e&&t--,i&&(a>0&&t--,n>a+t&&t--),t=Math.max(1,t),Math.min(t,n-a)}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{jsx as o,jsxs as e,Fragment as s}from"react/jsx-runtime";import{Box as n,Text as i}from"ink";import{FileList as k}from"./FileList.js";import{HistoryView as p}from"./HistoryView.js";import{CompareListView as M}from"./CompareListView.js";import{categorizeFiles as _}from"../utils/fileCategories.js";export function TopPane({bottomTab:
|
|
1
|
+
import{jsx as o,jsxs as e,Fragment as s}from"react/jsx-runtime";import{Box as n,Text as i}from"ink";import{FileList as k}from"./FileList.js";import{HistoryView as p}from"./HistoryView.js";import{CompareListView as M}from"./CompareListView.js";import{categorizeFiles as _}from"../utils/fileCategories.js";export function TopPane({bottomTab:r,currentPane:d,terminalWidth:t,topPaneHeight:c,files:m,selectedIndex:f,fileListScrollOffset:x,stagedCount:g,onStage:C,onUnstage:w,commits:h,historySelectedIndex:y,historyScrollOffset:a,onSelectHistoryCommit:A,compareDiff:l,compareListSelection:v,compareScrollOffset:F,includeUncommitted:u}){const{modified:I,untracked:O}=_(m),j=I.length,S=O.length;return e(n,{flexDirection:"column",height:c,width:t,overflowX:"hidden",overflowY:"hidden",children:[(r==="diff"||r==="commit")&&e(s,{children:[e(n,{children:[o(i,{bold:!0,color:d==="files"?"cyan":void 0,children:"STAGING AREA"}),e(i,{dimColor:!0,children:[" ","(",j," modified, ",S," untracked, ",g," staged)"]})]}),o(k,{files:m,selectedIndex:f,isFocused:d==="files",scrollOffset:x,maxHeight:c-1,width:t,onStage:C,onUnstage:w})]}),r==="history"&&e(s,{children:[e(n,{children:[o(i,{bold:!0,color:d==="history"?"cyan":void 0,children:"COMMITS"}),e(i,{dimColor:!0,children:[" (",h.length," commits)"]})]}),o(p,{commits:h,selectedIndex:y,scrollOffset:a,maxHeight:c-1,isActive:d==="history",width:t,onSelectCommit:A})]}),r==="compare"&&e(s,{children:[e(n,{children:[o(i,{bold:!0,color:d==="compare"?"cyan":void 0,children:"COMPARE"}),o(i,{dimColor:!0,children:" (vs "}),o(i,{color:"cyan",children:l?.baseBranch??"..."}),e(i,{dimColor:!0,children:[": ",l?.commits.length??0," commits, ",l?.files.length??0," files) (b)"]}),l&&l.uncommittedCount>0&&e(s,{children:[o(i,{dimColor:!0,children:" | "}),e(i,{color:u?"magenta":"yellow",children:["[",u?"x":" ","] uncommitted"]}),o(i,{dimColor:!0,children:" (u)"})]})]}),o(M,{commits:l?.commits??[],files:l?.files??[],selectedItem:v,scrollOffset:F,maxHeight:c-1,isActive:d==="compare",width:t})]})]})}
|
package/dist/hooks/useMouse.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{useEffect as d,useState as y,useCallback as C,useRef as x}from"react";import{useStdin as R}from"ink";export function useMouse(p,b=!1){const{stdin:
|
|
1
|
+
import{useEffect as d,useState as y,useCallback as C,useRef as x}from"react";import{useStdin as R}from"ink";export function useMouse(p,b=!1){const{stdin:u,setRawMode:h}=R(),[e,w]=y(!0),o=x(p);d(()=>{o.current=p});const M=C(()=>{w(l=>!l)},[]),a=x(e);return d(()=>{a.current=e},[e]),d(()=>{!b&&e?(process.stdout.write("\x1B[?1000h"),process.stdout.write("\x1B[?1006h")):(process.stdout.write("\x1B[?1006l"),process.stdout.write("\x1B[?1000l"))},[b,e]),d(()=>{if(!u||!h)return;const l=g=>{const m=g.toString(),s=m.match(/\x1b\[<(\d+);(\d+);(\d+)([Mm])/);if(s){const t=parseInt(s[1],10),n=parseInt(s[2],10),r=parseInt(s[3],10),c=s[4]==="m";if(t>=64&&t<96){if(a.current){const f=t===64?"scroll-up":"scroll-down";o.current({x:n,y:r,type:f,button:"none"})}}else if(c&&t>=0&&t<3){const f=t===0?"left":t===1?"middle":"right";o.current({x:n,y:r,type:"click",button:f})}return}const i=m.match(/\x1b\[M(.)(.)(.)/);if(i){const t=i[1].charCodeAt(0)-32,n=i[2].charCodeAt(0)-32,r=i[3].charCodeAt(0)-32;if(t>=64){if(a.current){const c=t===64?"scroll-up":"scroll-down";o.current({x:n,y:r,type:c,button:"none"})}}else if(t>=0&&t<3){const c=t===0?"left":t===1?"middle":"right";o.current({x:n,y:r,type:"click",button:c})}}};return u.on("data",l),()=>{u.off("data",l),process.stdout.write("\x1B[?1006l"),process.stdout.write("\x1B[?1000l")}},[u,h]),{mouseEnabled:e,toggleMouse:M}}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{categorizeFiles as d}from"./fileCategories.js";export function calculatePaneBoundaries(t,e,r,
|
|
1
|
+
import{categorizeFiles as d}from"./fileCategories.js";export function calculatePaneBoundaries(t,e,r,a=1){const s=a+2,i=a+1+t,f=i+1,c=i+2,l=c+e-1;return{stagingPaneStart:s,fileListEnd:i,separatorRow:f,diffPaneStart:c,diffPaneEnd:l,footerRow:r}}export function getClickedFileIndex(t,e,r,a,s){if(t<a+1||t>s)return-1;const i=t-(a+1)+e,{modified:f,untracked:c,staged:l}=d(r);let n=0,u=0;if(f.length>0){n++;for(let o=0;o<f.length;o++){if(i===n)return u;n++,u++}}if(c.length>0){f.length>0&&n++,n++;for(let o=0;o<c.length;o++){if(i===n)return u;n++,u++}}if(l.length>0){(f.length>0||c.length>0)&&n++,n++;for(let o=0;o<l.length;o++){if(i===n)return u;n++,u++}}return-1}export function getTabBoundaries(t){const e=t-39;return{diffStart:e,diffEnd:e+6,commitStart:e+8,commitEnd:e+16,historyStart:e+18,historyEnd:e+27,compareStart:e+29,compareEnd:e+38}}export function getClickedTab(t,e){const r=getTabBoundaries(e);return t>=r.diffStart&&t<=r.diffEnd?"diff":t>=r.commitStart&&t<=r.commitEnd?"commit":t>=r.historyStart&&t<=r.historyEnd?"history":t>=r.compareStart&&t<=r.compareEnd?"compare":null}export function isButtonAreaClick(t){return t<=6}export function isInPane(t,e,r){return t>=e&&t<=r}export function getFooterLeftClick(t){return t>=1&&t<=9?"hotkeys":t>=13&&t<=20?"mouse-mode":t>=24&&t<=38?"auto-tab":null}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "diffstalker",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.5",
|
|
4
4
|
"description": "Terminal application that displays git diff/status for directories",
|
|
5
5
|
"author": "yogh-io",
|
|
6
6
|
"license": "MIT",
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
"dev": "tsx src/index.tsx",
|
|
22
22
|
"build": "tsc",
|
|
23
23
|
"build:prod": "tsc && node scripts/minify.js",
|
|
24
|
-
"bundle": "npm run build:prod && ncc build dist/index.js -o dist/bundle
|
|
24
|
+
"bundle": "npm run build:prod && ncc build dist/index.js -o dist/bundle && node scripts/minify.js ../dist/bundle",
|
|
25
25
|
"start": "node dist/index.js",
|
|
26
26
|
"start:bundle": "node dist/bundle/index.js",
|
|
27
27
|
"test": "vitest run",
|