diffstalker 0.2.0 → 0.2.2

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.
Files changed (46) hide show
  1. package/.dependency-cruiser.cjs +67 -0
  2. package/.githooks/pre-commit +2 -0
  3. package/.githooks/pre-push +15 -0
  4. package/.github/workflows/release.yml +8 -0
  5. package/README.md +43 -35
  6. package/bun.lock +82 -3
  7. package/dist/App.js +555 -552
  8. package/dist/FollowMode.js +85 -0
  9. package/dist/KeyBindings.js +228 -0
  10. package/dist/MouseHandlers.js +192 -0
  11. package/dist/core/ExplorerStateManager.js +423 -78
  12. package/dist/core/GitStateManager.js +260 -119
  13. package/dist/git/diff.js +102 -17
  14. package/dist/git/status.js +16 -54
  15. package/dist/git/test-helpers.js +67 -0
  16. package/dist/index.js +60 -53
  17. package/dist/ipc/CommandClient.js +6 -7
  18. package/dist/state/UIState.js +39 -4
  19. package/dist/ui/PaneRenderers.js +76 -0
  20. package/dist/ui/modals/FileFinder.js +193 -0
  21. package/dist/ui/modals/HotkeysModal.js +12 -3
  22. package/dist/ui/modals/ThemePicker.js +1 -2
  23. package/dist/ui/widgets/CommitPanel.js +1 -1
  24. package/dist/ui/widgets/CompareListView.js +123 -80
  25. package/dist/ui/widgets/DiffView.js +228 -180
  26. package/dist/ui/widgets/ExplorerContent.js +15 -28
  27. package/dist/ui/widgets/ExplorerView.js +148 -43
  28. package/dist/ui/widgets/FileList.js +62 -95
  29. package/dist/ui/widgets/FlatFileList.js +65 -0
  30. package/dist/ui/widgets/Footer.js +25 -11
  31. package/dist/ui/widgets/Header.js +17 -52
  32. package/dist/ui/widgets/fileRowFormatters.js +73 -0
  33. package/dist/utils/ansiTruncate.js +0 -1
  34. package/dist/utils/displayRows.js +101 -21
  35. package/dist/utils/fileCategories.js +37 -0
  36. package/dist/utils/fileTree.js +148 -0
  37. package/dist/utils/flatFileList.js +67 -0
  38. package/dist/utils/layoutCalculations.js +5 -3
  39. package/eslint.metrics.js +15 -0
  40. package/metrics/.gitkeep +0 -0
  41. package/metrics/v0.2.1.json +268 -0
  42. package/metrics/v0.2.2.json +229 -0
  43. package/package.json +9 -2
  44. package/dist/utils/ansiToBlessed.js +0 -125
  45. package/dist/utils/mouseCoordinates.js +0 -165
  46. package/dist/utils/rowCalculations.js +0 -246
package/dist/index.js CHANGED
@@ -1,59 +1,66 @@
1
1
  #!/usr/bin/env node
2
- import G8 from"neo-blessed";import o from"neo-blessed";var MK=0.05;function k8(K,$,J,X=1){let Z=X+4,Q=K-Z,q=Math.floor(Q*J),Y=Q-q;return{width:$,height:K,headerHeight:X,topPaneHeight:q,bottomPaneHeight:Y,footerRow:K-1}}function j8(K,$,J,X){let Z=$+1,Q=Z+J,q=Q+1,Y=q+X,V=K-1;return{stagingPaneStart:Z,fileListEnd:Q,diffPaneStart:q,diffPaneEnd:Y,footerRow:V}}class OK{screen;headerBox;topSeparator;topPane;middleSeparator;bottomPane;bottomSeparator;footerBox;_dimensions;_splitRatio;constructor(K,$=0.4){this.screen=K,this._splitRatio=$,this._dimensions=this.calculateDimensions(),this.headerBox=this.createHeaderBox(),this.topSeparator=this.createSeparator(this._dimensions.headerHeight),this.topPane=this.createTopPane(),this.middleSeparator=this.createSeparator(this._dimensions.headerHeight+1+this._dimensions.topPaneHeight),this.bottomPane=this.createBottomPane(),this.bottomSeparator=this.createSeparator(this._dimensions.headerHeight+2+this._dimensions.topPaneHeight+this._dimensions.bottomPaneHeight),this.footerBox=this.createFooterBox(),K.on("resize",()=>this.onResize())}get dimensions(){return this._dimensions}get splitRatio(){return this._splitRatio}setSplitRatio(K){this._splitRatio=Math.min(0.85,Math.max(0.15,K)),this.updateLayout()}adjustSplitRatio(K){this.setSplitRatio(this._splitRatio+K)}calculateDimensions(){let K=this.screen.height||24,$=this.screen.width||80;return k8(K,$,this._splitRatio)}createHeaderBox(){return o.box({parent:this.screen,top:0,left:0,width:"100%",height:this._dimensions.headerHeight,tags:!0})}createSeparator(K){let $=this.screen.width||80;return o.box({parent:this.screen,top:K,left:0,width:"100%",height:1,content:"─".repeat($),style:{fg:"gray"}})}createTopPane(){return o.box({parent:this.screen,top:this._dimensions.headerHeight+1,left:0,width:"100%",height:this._dimensions.topPaneHeight,tags:!0,scrollable:!0,alwaysScroll:!0,wrap:!1,scrollbar:{ch:" ",track:{bg:"gray"},style:{inverse:!0}}})}createBottomPane(){return o.box({parent:this.screen,top:this._dimensions.headerHeight+2+this._dimensions.topPaneHeight,left:0,width:"100%",height:this._dimensions.bottomPaneHeight,tags:!0,scrollable:!0,alwaysScroll:!0,wrap:!1,scrollbar:{ch:" ",track:{bg:"gray"},style:{inverse:!0}}})}createFooterBox(){return o.box({parent:this.screen,top:this._dimensions.footerRow,left:0,width:"100%",height:1,tags:!0})}onResize(){this._dimensions=this.calculateDimensions(),this.updateLayout()}updateLayout(){this._dimensions=this.calculateDimensions();let K=this.screen.width||80;this.headerBox.height=this._dimensions.headerHeight,this.headerBox.width=K,this.topSeparator.top=this._dimensions.headerHeight,this.topSeparator.width=K,this.topSeparator.setContent("─".repeat(K)),this.topPane.top=this._dimensions.headerHeight+1,this.topPane.height=this._dimensions.topPaneHeight,this.topPane.width=K,this.middleSeparator.top=this._dimensions.headerHeight+1+this._dimensions.topPaneHeight,this.middleSeparator.width=K,this.middleSeparator.setContent("─".repeat(K)),this.bottomPane.top=this._dimensions.headerHeight+2+this._dimensions.topPaneHeight,this.bottomPane.height=this._dimensions.bottomPaneHeight,this.bottomPane.width=K,this.bottomSeparator.top=this._dimensions.headerHeight+2+this._dimensions.topPaneHeight+this._dimensions.bottomPaneHeight,this.bottomSeparator.width=K,this.bottomSeparator.setContent("─".repeat(K)),this.footerBox.top=this._dimensions.footerRow,this.footerBox.width=K}getPaneBoundaries(){return j8(this._dimensions.height,this._dimensions.headerHeight,this._dimensions.topPaneHeight,this._dimensions.bottomPaneHeight)}screenYToTopPaneRow(K){let $=this._dimensions.headerHeight+1,J=$+this._dimensions.topPaneHeight;if(K<$||K>=J)return-1;return K-$}screenYToBottomPaneRow(K){let $=this._dimensions.headerHeight+2+this._dimensions.topPaneHeight,J=$+this._dimensions.bottomPaneHeight;if(K<$||K>=J)return-1;return K-$}get topPaneTop(){return this._dimensions.headerHeight+1}get bottomPaneTop(){return this._dimensions.headerHeight+2+this._dimensions.topPaneHeight}}import*as F from"node:fs";import*as c from"node:path";import*as t from"node:os";var M8={targetFile:c.join(t.homedir(),".cache","diffstalker","target"),watcherEnabled:!1,debug:!1,theme:"dark"},h=c.join(t.homedir(),".config","diffstalker","config.json"),O8=["dark","light","dark-colorblind","light-colorblind","dark-ansi","light-ansi"];function N8(K){return typeof K==="string"&&O8.includes(K)}function $7(){let K={...M8};if(process.env.DIFFSTALKER_PAGER)K.pager=process.env.DIFFSTALKER_PAGER;if(F.existsSync(h))try{let $=JSON.parse(F.readFileSync(h,"utf-8"));if($.pager)K.pager=$.pager;if($.targetFile)K.targetFile=$.targetFile;if(N8($.theme))K.theme=$.theme;if(typeof $.splitRatio==="number"&&$.splitRatio>=0.15&&$.splitRatio<=0.85)K.splitRatio=$.splitRatio}catch{}return K}function NK(K){let $=c.dirname(h);if(!F.existsSync($))F.mkdirSync($,{recursive:!0});let J={};if(F.existsSync(h))try{J=JSON.parse(F.readFileSync(h,"utf-8"))}catch{}Object.assign(J,K),F.writeFileSync(h,JSON.stringify(J,null,2)+`
3
- `)}function J7(K){let $=c.dirname(K);if(!F.existsSync($))F.mkdirSync($,{recursive:!0})}function e(K){let $=t.homedir();if(K.startsWith($))return"~"+K.slice($.length);return K}function H8(K){let $=`{bold}{green-fg}${K.current}{/green-fg}{/bold}`;if(K.tracking)$+=` {gray-fg}→{/gray-fg} {blue-fg}${K.tracking}{/blue-fg}`;if(K.ahead>0)$+=` {green-fg}↑${K.ahead}{/green-fg}`;if(K.behind>0)$+=` {red-fg}↓${K.behind}{/red-fg}`;return $}function X7(K,$,J,X,Z,Q){if(!K)return"{gray-fg}Waiting for target path...{/gray-fg}";let q=e(K),Y=X==="Not a git repository",V=`{bold}{cyan-fg}${q}{/cyan-fg}{/bold}`;if(J)V+=" {yellow-fg}⟳{/yellow-fg}";if(Y)V+=" {yellow-fg}(not a git repository){/yellow-fg}";else if(X)V+=` {red-fg}(${X}){/red-fg}`;if(Z?.enabled&&Z.sourceFile){let z=e(Z.sourceFile);V+=` {gray-fg}(follow: ${z}){/gray-fg}`}let _=$?H8($):"";if(_){let z=q.length;if(J)z+=2;if(Y)z+=24;else if(X)z+=X.length+3;if(Z?.enabled&&Z.sourceFile){let k=e(Z.sourceFile);z+=10+k.length}let U=$?$.current.length+($.tracking?3+$.tracking.length:0)+($.ahead>0?3+String($.ahead).length:0)+($.behind>0?3+String($.behind).length:0):0,B=Math.max(1,Q-z-U-2);return V+" ".repeat(B)+_}return V}function Z7(K){return K.replace(/\{[^}]+\}/g,"").length}function Q7(K,$,J,X,Z,Q){let q="{gray-fg}?{/gray-fg} ";if(q+=$?"{yellow-fg}[scroll]{/yellow-fg}":"{yellow-fg}m:[select]{/yellow-fg}",q+=" ",q+=J?"{blue-fg}[auto]{/blue-fg}":"{gray-fg}[auto]{/gray-fg}",q+=" ",q+=X?"{blue-fg}[wrap]{/blue-fg}":"{gray-fg}[wrap]{/gray-fg}",K==="explorer")q+=" ",q+=Z?"{blue-fg}[dots]{/blue-fg}":"{gray-fg}[dots]{/gray-fg}";let V=[{key:"1",label:"Diff",tab:"diff"},{key:"2",label:"Commit",tab:"commit"},{key:"3",label:"History",tab:"history"},{key:"4",label:"Compare",tab:"compare"},{key:"5",label:"Explorer",tab:"explorer"}].map(({key:B,label:k,tab:G})=>{if(K===G)return`{bold}{cyan-fg}[${B}]${k}{/cyan-fg}{/bold}`;return`[${B}]${k}`}).join(" "),_=Z7(q),z=Z7(V),U=Math.max(1,Q-_-z);return q+" ".repeat(U)+V}function HK(K){let $=K.filter((Z)=>!Z.staged&&Z.status!=="untracked"),J=K.filter((Z)=>!Z.staged&&Z.status==="untracked"),X=K.filter((Z)=>Z.staged);return{modified:$,untracked:J,staged:X,ordered:[...$,...J,...X]}}function r(K,$){if(K.length<=$)return K;let X=Math.max($,20);if(K.length<=X)return K;let Z=K.split("/");if(Z.length===1){let U=Math.floor((X-1)/2);return K.slice(0,U)+""+K.slice(-(X-U-1))}let Q=Z[Z.length-1],q=Z[0],Y="/…/";if(q.length+Y.length+Q.length>X){let U=X-2;if(Q.length>U){let B=Math.floor((U-1)/2);return"…/"+Q.slice(0,B)+""+Q.slice(-(U-B-1))}return"…/"+Q}let _=q,z=1;while(z<Z.length-1){let U=Z[z],B=_+"/"+U;if(B.length+Y.length+Q.length<=X)_=B,z++;else break}if(z===Z.length-1)return K;return _+Y+Q}function T8(K){switch(K){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 E8(K){switch(K){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 I8(K,$){if(K===void 0&&$===void 0)return"";let J=[];if(K!==void 0&&K>0)J.push(`{green-fg}+${K}{/green-fg}`);if($!==void 0&&$>0)J.push(`{red-fg}-${$}{/red-fg}`);return J.length>0?" "+J.join(" "):""}function KK(K){let{modified:$,untracked:J,staged:X}=HK(K),Z=[],Q=0;if($.length>0)Z.push({type:"header",content:"Modified:",headerColor:"yellow"}),$.forEach((q)=>{Z.push({type:"file",file:q,fileIndex:Q++})});if(J.length>0){if($.length>0)Z.push({type:"spacer"});Z.push({type:"header",content:"Untracked:",headerColor:"gray"}),J.forEach((q)=>{Z.push({type:"file",file:q,fileIndex:Q++})})}if(X.length>0){if($.length>0||J.length>0)Z.push({type:"spacer"});Z.push({type:"header",content:"Staged:",headerColor:"green"}),X.forEach((q)=>{Z.push({type:"file",file:q,fileIndex:Q++})})}return Z}function q7(K,$,J,X,Z=0,Q){if(K.length===0)return"{gray-fg} No changes{/gray-fg}";let q=KK(K),Y=X-12,V=Q?q.slice(Z,Z+Q):q.slice(Z),_=[];for(let z of V)if(z.type==="header")_.push(`{bold}{${z.headerColor}-fg}${z.content}{/${z.headerColor}-fg}{/bold}`);else if(z.type==="spacer")_.push("");else if(z.type==="file"&&z.file&&z.fileIndex!==void 0){let U=z.file,k=z.fileIndex===$&&J,G=T8(U.status),M=E8(U.status),T=U.staged?"[-]":"[+]",N=U.staged?"red":"green",H=I8(U.insertions,U.deletions),E=H.replace(/\{[^}]+\}/g,"").length,A=Y-E,j=r(U.path,A),O="";if(k)O+="{cyan-fg}{bold}▸ {/bold}{/cyan-fg}";else O+=" ";if(O+=`{${N}-fg}${T}{/${N}-fg} `,O+=`{${M}-fg}${G}{/${M}-fg} `,k)O+=`{cyan-fg}{inverse}${j}{/inverse}{/cyan-fg}`;else O+=j;if(U.originalPath)O+=` {gray-fg} ${r(U.originalPath,30)}{/gray-fg}`;O+=H,_.push(O)}return _.join(`
4
- `)}function Y7(K){return KK(K).length}function z7(K,$){let{ordered:J}=HK(K);return J[$]??null}function V7(K,$){let X=KK($)[K];if(X?.type==="file"&&X.fileIndex!==void 0)return X.fileIndex;return null}function TK(K,$){let J=KK($);for(let X=0;X<J.length;X++)if(J[X].type==="file"&&J[X].fileIndex===K)return X;return 0}var D8={name:"dark",displayName:"Dark",colors:{addBg:"#022800",delBg:"#3D0100",addHighlight:"#044700",delHighlight:"#5C0200",text:"white",addLineNum:"#368F35",delLineNum:"#A14040",contextLineNum:"gray",addSymbol:"greenBright",delSymbol:"redBright"}},R8={name:"light",displayName:"Light",colors:{addBg:"#69db7c",delBg:"#ffa8b4",addHighlight:"#2f9d44",delHighlight:"#d1454b",text:"black",addLineNum:"#2f9d44",delLineNum:"#d1454b",contextLineNum:"#6c757d",addSymbol:"green",delSymbol:"red"}},F8={name:"dark-colorblind",displayName:"Dark (colorblind)",colors:{addBg:"#004466",delBg:"#660000",addHighlight:"#0077b3",delHighlight:"#b30000",text:"white",addLineNum:"#0077b3",delLineNum:"#b30000",contextLineNum:"gray",addSymbol:"cyanBright",delSymbol:"redBright"}},v8={name:"light-colorblind",displayName:"Light (colorblind)",colors:{addBg:"#99ccff",delBg:"#ffcccc",addHighlight:"#3366cc",delHighlight:"#993333",text:"black",addLineNum:"#3366cc",delLineNum:"#993333",contextLineNum:"#6c757d",addSymbol:"blue",delSymbol:"red"}},L8={name:"dark-ansi",displayName:"Dark (ANSI)",colors:{addBg:"green",delBg:"red",addHighlight:"greenBright",delHighlight:"redBright",text:"white",addLineNum:"greenBright",delLineNum:"redBright",contextLineNum:"gray",addSymbol:"greenBright",delSymbol:"redBright"}},W8={name:"light-ansi",displayName:"Light (ANSI)",colors:{addBg:"green",delBg:"red",addHighlight:"greenBright",delHighlight:"redBright",text:"black",addLineNum:"green",delLineNum:"red",contextLineNum:"gray",addSymbol:"green",delSymbol:"red"}},$K={dark:D8,light:R8,"dark-colorblind":F8,"light-colorblind":v8,"dark-ansi":L8,"light-ansi":W8},C=["dark","light","dark-colorblind","light-colorblind","dark-ansi","light-ansi"];function s(K){return $K[K]??$K.dark}function JK(K){let J=new Date().getTime()-K.getTime(),X=Math.floor(J/3600000),Z=Math.floor(J/86400000);if(X<1)return`${Math.floor(J/60000)}m ago`;else if(X<48)return`${X}h ago`;else if(Z<=14)return`${Z}d ago`;else return K.toLocaleDateString("en-US",{month:"short",day:"numeric"})}function U7(K){return K.toLocaleString("en-US",{year:"numeric",month:"short",day:"numeric",hour:"2-digit",minute:"2-digit"})}function y8(K){return!(K.startsWith("index ")||K.startsWith("--- ")||K.startsWith("+++ ")||K.startsWith("similarity index"))}function _7(K){if(K.type!=="header")return!0;return y8(K.content)}function XK(K,$,J=!0){if($<=0)return[{text:K,isContinuation:!1}];if(K.length<=$)return[{text:K,isContinuation:!1}];let X=[],Z=K,Q=!0;while(Z.length>0){if(Z.length<=$){X.push({text:Z,isContinuation:!Q});break}X.push({text:Z.slice(0,$),isContinuation:!Q}),Z=Z.slice($),Q=!1}if(J)S8(K,$,X);return X}function S8(K,$,J){let X=J.map((Z)=>Z.text).join("");if(X!==K)throw Error(`[LineBreaking] Content was lost during breaking!
5
- Original (${K.length} chars): "${K.slice(0,50)}${K.length>50?"...":""}"
6
- Joined (${X.length} chars): "${X.slice(0,50)}${X.length>50?"...":""}"`);for(let Z=0;Z<J.length;Z++){let Q=J[Z];if(Q.text.length>$&&$>=1)throw Error(`[LineBreaking] Segment ${Z} exceeds maxWidth!
7
- Segment length: ${Q.text.length}, maxWidth: ${$}
8
- Segment: "${Q.text.slice(0,50)}${Q.text.length>50?"...":""}"`)}if(J.length>0&&J[0].isContinuation)throw Error("[LineBreaking] First segment incorrectly marked as continuation!");for(let Z=1;Z<J.length;Z++)if(!J[Z].isContinuation)throw Error(`[LineBreaking] Segment ${Z} should be marked as continuation but isn't!`)}function EK(K,$){if($<=0)return 1;if(K.length<=$)return 1;return Math.ceil(K.length/$)}import d from"fast-diff";function B7(K,$){if(!K||!$)return!1;let J=d(K,$),X=0,Z=0;for(let[q,Y]of J)if(Z+=Y.length,q===d.EQUAL)X+=Y.length;if(Z===0)return!1;return X/Z>=0.5}function G7(K,$){let J=d(K,$),X=[],Z=[];for(let[Q,q]of J)if(Q===d.EQUAL)X.push({text:q,type:"same"}),Z.push({text:q,type:"same"});else if(Q===d.DELETE)X.push({text:q,type:"changed"});else if(Q===d.INSERT)Z.push({text:q,type:"changed"});return{oldSegments:X,newSegments:Z}}import{createEmphasize as P8}from"emphasize";import{common as C8}from"lowlight";var DK=P8(C8),b8={ts:"typescript",tsx:"typescript",js:"javascript",jsx:"javascript",mjs:"javascript",cjs:"javascript",html:"xml",htm:"xml",xml:"xml",svg:"xml",css:"css",scss:"scss",sass:"scss",less:"less",json:"json",yaml:"yaml",yml:"yaml",toml:"ini",sh:"bash",bash:"bash",zsh:"bash",fish:"bash",ps1:"powershell",bat:"dos",cmd:"dos",c:"c",h:"c",cpp:"cpp",hpp:"cpp",cc:"cpp",cxx:"cpp",rs:"rust",go:"go",zig:"zig",java:"java",kt:"kotlin",kts:"kotlin",scala:"scala",groovy:"groovy",gradle:"groovy",py:"python",rb:"ruby",pl:"perl",lua:"lua",php:"php",r:"r",hs:"haskell",ml:"ocaml",fs:"fsharp",fsx:"fsharp",ex:"elixir",exs:"elixir",erl:"erlang",clj:"clojure",cljs:"clojure",cs:"csharp",vb:"vbnet",md:"markdown",markdown:"markdown",rst:"plaintext",txt:"plaintext",Makefile:"makefile",Dockerfile:"dockerfile",cmake:"cmake",ini:"ini",conf:"ini",cfg:"ini",sql:"sql",vim:"vim",diff:"diff",patch:"diff"},A7={Makefile:"makefile",makefile:"makefile",GNUmakefile:"makefile",Dockerfile:"dockerfile",dockerfile:"dockerfile",Jenkinsfile:"groovy",Vagrantfile:"ruby",Gemfile:"ruby",Rakefile:"ruby",".gitignore":"plaintext",".gitattributes":"plaintext",".editorconfig":"ini",".prettierrc":"json",".eslintrc":"json","tsconfig.json":"json","package.json":"json","package-lock.json":"json","bun.lockb":"plaintext","yarn.lock":"yaml","pnpm-lock.yaml":"yaml","Cargo.toml":"ini","Cargo.lock":"ini","go.mod":"go","go.sum":"plaintext"},IK=null;function k7(){if(!IK)IK=new Set(DK.listLanguages());return IK}function ZK(K){if(!K)return null;let $=K.split("/").pop()??"";if(A7[$]){let Z=A7[$];return k7().has(Z)?Z:null}let J=$.includes(".")?$.split(".").pop()?.toLowerCase():null;if(!J)return null;let X=b8[J];if(!X)return null;return k7().has(X)?X:null}function j7(K,$){if(!K||!$)return K;try{return DK.highlight($,K).value}catch{return K}}function RK(K,$){if(!$||K.length===0)return K;try{let J=K.join(`
9
- `);return DK.highlight($,J).value.replace(/\x1b\[0m/g,"\x1B[39m").split(`
10
- `)}catch{return K}}function b(K){let $;if(K.type==="addition"||K.type==="deletion")$=K.content.slice(1);else if(K.type==="context")$=K.content.startsWith(" ")?K.content.slice(1):K.content;else $=K.content;return $.replace(/[\x00-\x08\x0a-\x1f\x7f]/g,"").replace(/\t/g," ")}function M7(K){switch(K.type){case"header":return{type:"diff-header",content:K.content};case"hunk":return{type:"diff-hunk",content:K.content};case"addition":return{type:"diff-add",lineNum:K.newLineNum,content:b(K)};case"deletion":return{type:"diff-del",lineNum:K.oldLineNum,content:b(K)};case"context":return{type:"diff-context",lineNum:K.oldLineNum??K.newLineNum,content:b(K)}}}function x8(K){let $=K.match(/^diff --git a\/.+ b\/(.+)$/);return $?$[1]:null}function FK(K){if(!K)return[];let $=K.lines.filter(_7),J=[],X=[],Z=null,Q=0;while(Q<$.length){let q=$[Q];if(q.type==="header"){let B=x8(q.content);if(B){if(Z)X.push(Z),J.push({type:"spacer"});Z={language:ZK(B),startRowIndex:J.length,oldContent:[],oldRowIndices:[],newContent:[],newRowIndices:[]}}J.push(M7(q)),Q++;continue}if(q.type==="hunk"){J.push(M7(q)),Q++;continue}if(q.type==="context"){let B=b(q),k=J.length;if(J.push({type:"diff-context",lineNum:q.oldLineNum??q.newLineNum,content:B}),Z&&Z.language)Z.oldContent.push(B),Z.oldRowIndices.push(k),Z.newContent.push(B),Z.newRowIndices.push(k);Q++;continue}let Y=[];while(Q<$.length&&$[Q].type==="deletion")Y.push($[Q]),Q++;let V=[];while(Q<$.length&&$[Q].type==="addition")V.push($[Q]),Q++;let _=new Map,z=new Map,U=Math.min(Y.length,V.length);for(let B=0;B<U;B++){let k=b(Y[B]),G=b(V[B]);if(B7(k,G)){let{oldSegments:M,newSegments:T}=G7(k,G);_.set(B,M),z.set(B,T)}}for(let B=0;B<Y.length;B++){let k=Y[B],G=b(k),M=_.get(B),T=J.length;if(J.push({type:"diff-del",lineNum:k.oldLineNum,content:G,...M&&{wordDiffSegments:M}}),Z&&Z.language&&!M)Z.oldContent.push(G),Z.oldRowIndices.push(T)}for(let B=0;B<V.length;B++){let k=V[B],G=b(k),M=z.get(B),T=J.length;if(J.push({type:"diff-add",lineNum:k.newLineNum,content:G,...M&&{wordDiffSegments:M}}),Z&&Z.language&&!M)Z.newContent.push(G),Z.newRowIndices.push(T)}}if(Z)X.push(Z);for(let q of X){if(!q.language)continue;if(q.oldContent.length>0){let Y=RK(q.oldContent,q.language);for(let V=0;V<q.oldRowIndices.length;V++){let _=q.oldRowIndices[V],z=J[_],U=Y[V];if(U&&U!==z.content&&(z.type==="diff-del"||z.type==="diff-context"))z.highlighted=U}}if(q.newContent.length>0){let Y=RK(q.newContent,q.language);for(let V=0;V<q.newRowIndices.length;V++){let _=q.newRowIndices[V],z=J[_],U=Y[V];if(U&&U!==z.content&&(z.type==="diff-add"||z.type==="diff-context"))z.highlighted=U}}}return J}function O7(K,$){let J=[];if(K){J.push({type:"commit-header",content:`commit ${K.hash}`}),J.push({type:"commit-header",content:`Author: ${K.author}`}),J.push({type:"commit-header",content:`Date: ${U7(K.date)}`}),J.push({type:"spacer"});for(let X of K.message.split(`
11
- `))J.push({type:"commit-message",content:` ${X}`});J.push({type:"spacer"})}return J.push(...FK($)),J}function vK(K){let $=0;for(let J of K)if("lineNum"in J&&J.lineNum!==void 0)$=Math.max($,J.lineNum);return Math.max(3,String($).length)}function LK(K,$,J){if(!J)return K;let Z=Math.max(10,$),Q=[];for(let q of K)if(q.type==="diff-add"||q.type==="diff-del"||q.type==="diff-context"){let Y=q.content;if(!Y||Y.length<=Z){Q.push(q);continue}let V=XK(Y,Z);for(let _=0;_<V.length;_++){let z=V[_];Q.push({...q,content:z.text,lineNum:z.isContinuation?void 0:q.lineNum,isContinuation:z.isContinuation})}}else Q.push(q);return Q}var N7={30:"black",31:"red",32:"green",33:"yellow",34:"blue",35:"magenta",36:"cyan",37:"white",90:"gray",91:"red",92:"green",93:"yellow",94:"blue",95:"magenta",96:"cyan",97:"white"};function QK(K){if(!K)return"";let $=[],J="",X=0;while(X<K.length){if(K[X]==="\x1B"&&K[X+1]==="["){let Q=X+2;while(Q<K.length&&K[Q]!=="m")Q++;if(K[Q]==="m"){let q=K.slice(X+2,Q).split(";").map(Number);for(let Y of q)if(Y===0)while($.length>0){let V=$.pop();if(V)J+=`{/${V}}`}else if(Y===1)$.push("bold"),J+="{bold}";else if(Y===2)$.push("gray-fg"),J+="{gray-fg}";else if(Y===3);else if(Y===4)$.push("underline"),J+="{underline}";else if(Y>=30&&Y<=37){let V=N7[Y];if(V)$.push(`${V}-fg`),J+=`{${V}-fg}`}else if(Y>=90&&Y<=97){let V=N7[Y];if(V)$.push(`${V}-fg`),J+=`{${V}-fg}`}X=Q+1;continue}}let Z=K[X];if(Z==="{"||Z==="}")J+=Z+Z;else J+=Z;X++}while($.length>0){let Z=$.pop();if(Z)J+=`{/${Z}}`}return J}var H7=/\x1b\[[0-9;]*m/g;function qK(K,$,J=""){if($<=0)return J;if(!K.includes("\x1B")&&K.length<=$)return K;if(!K.includes("\x1B")){if(K.length<=$)return K;return K.slice(0,$-J.length)+J}let X=[],Z=0;H7.lastIndex=0;let Q;while((Q=H7.exec(K))!==null){if(Q.index>Z)X.push({type:"text",content:K.slice(Z,Q.index)});X.push({type:"ansi",content:Q[0]}),Z=Q.index+Q[0].length}if(Z<K.length)X.push({type:"text",content:K.slice(Z)});let q="",Y=0,V=$-J.length,_=!1,z=!1;for(let U of X)if(U.type==="ansi")q+=U.content,_=!0;else{let B=V-Y;if(B<=0){z=!0;break}if(U.content.length<=B)q+=U.content,Y+=U.content.length;else{q+=U.content.slice(0,B),Y+=B,z=!0;break}}if(z){if(_)q+="\x1B[0m";q+=J}return q}function R(K,$){if($<=0||K.length<=$)return K;if($<=1)return"";return K.slice(0,$-1)+""}function WK(K,$){if(K===void 0)return" ".repeat($);return String(K).padStart($," ")}function x(K){return K.replace(/\{/g,"{{").replace(/\}/g,"}}")}function YK(K){let $=parseInt(K.slice(1,3),16),J=parseInt(K.slice(3,5),16),X=parseInt(K.slice(5,7),16);return`\x1B[48;2;${$};${J};${X}m`}function T7(K){let $=parseInt(K.slice(1,3),16),J=parseInt(K.slice(3,5),16),X=parseInt(K.slice(5,7),16);return`\x1B[38;2;${$};${J};${X}m`}var v="\x1B[0m";function E7(K,$,J,X,Z,Q){let{colors:q}=Z;switch(K.type){case"diff-header":{let Y=K.content;if(Y.startsWith("diff --git")){let V=Y.match(/diff --git a\/.+ b\/(.+)$/);if(V){let _=X-6;return`{bold}{cyan-fg}── ${R(V[1],_)} ──{/cyan-fg}{/bold}`}}return`{gray-fg}${x(R(Y,X))}{/gray-fg}`}case"diff-hunk":{let Y=K.content.match(/^@@ -(\d+)(?:,(\d+))? \+(\d+)(?:,(\d+))? @@(.*)$/);if(Y){let V=parseInt(Y[1],10),_=Y[2]?parseInt(Y[2],10):1,z=parseInt(Y[3],10),U=Y[4]?parseInt(Y[4],10):1,B=Y[5].trim(),k=V+_-1,G=z+U-1,M=_===1?`${V}`:`${V}-${k}`,T=U===1?`${z}`:`${z}-${G}`,N=`Lines ${M} → ${T}`,H=X-N.length-1,E=B&&H>3?" "+R(B,H):"";return`{cyan-fg}${N}{/cyan-fg}{gray-fg}${E}{/gray-fg}`}return`{cyan-fg}${x(R(K.content,X))}{/cyan-fg}`}case"diff-add":{let Y=K.isContinuation,V=Y?"»":"+",z=`${WK(K.lineNum,$)} ${V} `;if(Z.name.includes("ansi")){let N=Q?K.content||"":R(K.content||"",J),E=`${z}${N}`.padEnd(X," ");return`{green-bg}{white-fg}${x(E)}{/white-fg}{/green-bg}`}let U=YK(q.addBg),B=YK(q.addHighlight),k=T7("#ffffff");if(K.wordDiffSegments&&!Y){let N=K.content||"";if(!Q&&N.length>J){let j=R(N,J),D=`${z}${j}`.padEnd(X," ");return`{escape}${U}${k}${D}${v}{/escape}`}let H="";for(let j of K.wordDiffSegments)if(j.type==="changed")H+=`${B}${j.text}${U}`;else H+=j.text;let E=z.length+N.length,A=" ".repeat(Math.max(0,X-E));return`{escape}${U}${k}${z}${H}${A}${v}{/escape}`}if(K.highlighted&&!Y){let N=K.content||"";if(!Q&&N.length>J){let A=R(N,J),O=`${z}${A}`.padEnd(X," ");return`{escape}${U}${k}${O}${v}{/escape}`}let H=z.length+N.length,E=" ".repeat(Math.max(0,X-H));return`{escape}${U}${k}${z}${K.highlighted}${E}${v}{/escape}`}let G=Q?K.content||"":R(K.content||"",J),T=`${z}${G}`.padEnd(X," ");return`{escape}${U}${k}${T}${v}{/escape}`}case"diff-del":{let Y=K.isContinuation,V=Y?"»":"-",z=`${WK(K.lineNum,$)} ${V} `;if(Z.name.includes("ansi")){let N=Q?K.content||"":R(K.content||"",J),E=`${z}${N}`.padEnd(X," ");return`{red-bg}{white-fg}${x(E)}{/white-fg}{/red-bg}`}let U=YK(q.delBg),B=YK(q.delHighlight),k=T7("#ffffff");if(K.wordDiffSegments&&!Y){let N=K.content||"";if(!Q&&N.length>J){let j=R(N,J),D=`${z}${j}`.padEnd(X," ");return`{escape}${U}${k}${D}${v}{/escape}`}let H="";for(let j of K.wordDiffSegments)if(j.type==="changed")H+=`${B}${j.text}${U}`;else H+=j.text;let E=z.length+N.length,A=" ".repeat(Math.max(0,X-E));return`{escape}${U}${k}${z}${H}${A}${v}{/escape}`}if(K.highlighted&&!Y){let N=K.content||"";if(!Q&&N.length>J){let A=R(N,J),O=`${z}${A}`.padEnd(X," ");return`{escape}${U}${k}${O}${v}{/escape}`}let H=z.length+N.length,E=" ".repeat(Math.max(0,X-H));return`{escape}${U}${k}${z}${K.highlighted}${E}${v}{/escape}`}let G=Q?K.content||"":R(K.content||"",J),T=`${z}${G}`.padEnd(X," ");return`{escape}${U}${k}${T}${v}{/escape}`}case"diff-context":{let Y=K.isContinuation,V=Y?"»":" ",z=`${WK(K.lineNum,$)} ${V} `,U=K.content||"";if(K.highlighted&&!Y){let k=Q?K.highlighted:qK(K.highlighted,J),G=QK(k);return`{gray-fg}${z}{/gray-fg}${G}`}let B=Q?x(U):x(R(U,J));return`{gray-fg}${z}{/gray-fg}${B}`}case"commit-header":return`{yellow-fg}${x(R(K.content,X))}{/yellow-fg}`;case"commit-message":return x(R(K.content,X));case"spacer":return""}}function yK(K,$,J=0,X,Z="dark",Q=!1){let q=FK(K);if(q.length===0)return{content:"{gray-fg}No diff to display{/gray-fg}",totalRows:0};let Y=s(Z),V=vK(q),_=$-V-5,z=$-2,U=LK(q,_,Q),B=U.length;return{content:(X?U.slice(J,J+X):U.slice(J)).map((M)=>E7(M,V,_,z,Y,Q)).join(`
12
- `),totalRows:B}}function I7(K,$,J,X=0,Z,Q="dark",q=!1){let Y=O7(K,$);if(Y.length===0)return{content:"{gray-fg}No commit selected{/gray-fg}",totalRows:0};let V=s(Q),_=vK(Y),z=J-_-5,U=J-2,B=LK(Y,z,q),k=B.length;return{content:(Z?B.slice(X,X+Z):B.slice(X)).map((T)=>E7(T,_,z,U,V,q)).join(`
13
- `),totalRows:k}}function D7(K,$,J){let X=[],Z="{bold}Commit Message{/bold}";if(K.amend)Z+=" {yellow-fg}(amending){/yellow-fg}";X.push(Z),X.push("");let Q=K.inputFocused?"":"",q=K.inputFocused?"cyan":"gray",Y=Math.max(20,J-6);X.push(`{${q}-fg}┌${"".repeat(Y+2)}┐{/${q}-fg}`);let V=K.message||(K.inputFocused?"":"Press i or Enter to edit..."),_=K.message?"":"{gray-fg}",z=K.message?"":"{/gray-fg}",U=V.length>Y?V.slice(0,Y-1)+"":V.padEnd(Y);X.push(`{${q}-fg}${Q}{/${q}-fg} ${_}${U}${z} {${q}-fg}${Q}{/${q}-fg}`),X.push(`{${q}-fg}└${"─".repeat(Y+2)}┘{/${q}-fg}`),X.push("");let B=K.amend?"[x]":"[ ]",k=K.amend?"green":"gray";if(X.push(`{${k}-fg}${B}{/${k}-fg} Amend {gray-fg}(a){/gray-fg}`),K.error)X.push(""),X.push(`{red-fg}${K.error}{/red-fg}`);if(K.isCommitting)X.push(""),X.push("{yellow-fg}Committing...{/yellow-fg}");X.push("");let G=K.inputFocused?"Enter: commit | Esc: unfocus":"i/Enter: edit | Esc: cancel | a: toggle amend";return X.push(`{gray-fg}Staged: ${$} file(s) | ${G}{/gray-fg}`),X.join(`
14
- `)}function w8(K,$){if(K.length<=$)return K;if($<=3)return K.slice(0,$);return K.slice(0,$-3)+"..."}function zK(K,$,J,X=20){let Z=$||"",Q=Math.max(0,J-X-1),q=Z;if(q.length>Q&&Q>3)q=q.slice(0,Q-3)+"...";else if(q.length>Q)q="";let Y=q?q.length+1:0,V=Math.max(X,J-Y);return{displayMessage:w8(K,V),displayRefs:q}}function R7(K,$,J,X,Z=0,Q){if(K.length===0)return"{gray-fg}No commits yet{/gray-fg}";let q=Q?K.slice(Z,Z+Q):K.slice(Z),Y=[];for(let V=0;V<q.length;V++){let _=q[V],B=Z+V===$&&J,k=JK(_.date),G=11+k.length+2+2,M=Math.max(10,X-G),{displayMessage:T,displayRefs:N}=zK(_.message,_.refs,M),H="";if(B)H+="{cyan-fg}{bold}{/bold}{/cyan-fg}";else H+=" ";if(H+=`{yellow-fg}${_.shortHash}{/yellow-fg} `,B)H+=`{cyan-fg}{inverse}${SK(T)}{/inverse}{/cyan-fg}`;else H+=SK(T);if(H+=` {gray-fg}(${k}){/gray-fg}`,N)H+=` {green-fg}${SK(N)}{/green-fg}`;Y.push(H)}return Y.join(`
15
- `)}function SK(K){return K.replace(/\{/g,"{{").replace(/\}/g,"}}")}function F7(K,$){return K[$]??null}function VK(K,$,J=!0,X=!0){let Z=[];if(K.length>0){if(Z.push({type:"section-header",sectionType:"commits"}),J)K.forEach((Q,q)=>{Z.push({type:"commit",commitIndex:q,commit:Q})})}if($.length>0){if(K.length>0)Z.push({type:"spacer"});if(Z.push({type:"section-header",sectionType:"files"}),X)$.forEach((Q,q)=>{Z.push({type:"file",fileIndex:q,file:Q})})}return Z}function l(K){return K.replace(/\{/g,"{{").replace(/\}/g,"}}")}function u8(K,$,J,X){let Z=$&&J,Q=JK(K.date),q=13+Q.length+2,Y=Math.max(10,X-q),{displayMessage:V,displayRefs:_}=zK(K.message,K.refs,Y),z=" ";if(z+=`{yellow-fg}${K.shortHash}{/yellow-fg} `,Z)z+=`{cyan-fg}{inverse}${l(V)}{/inverse}{/cyan-fg}`;else z+=l(V);if(z+=` {gray-fg}(${Q}){/gray-fg}`,_)z+=` {green-fg}${l(_)}{/green-fg}`;return z}function p8(K,$,J,X){let Z=$&&J,Q=K.isUncommitted??!1,q={added:"green",modified:"yellow",deleted:"red",renamed:"blue"},Y={added:"A",modified:"M",deleted:"D",renamed:"R"},V=5+String(K.additions).length+String(K.deletions).length,_=Q?14:0,z=Math.max(10,X-V-_),U=" ";if(Q)U+="{magenta-fg}{bold}*{/bold}{/magenta-fg}";let B=Q?"magenta":q[K.status];U+=`{${B}-fg}{bold}${Y[K.status]}{/bold}{/${B}-fg} `;let k=r(K.path,z);if(Z)U+=`{cyan-fg}{inverse}${l(k)}{/inverse}{/cyan-fg}`;else if(Q)U+=`{magenta-fg}${l(k)}{/magenta-fg}`;else U+=l(k);if(U+=` {gray-fg}({/gray-fg}{green-fg}+${K.additions}{/green-fg} {red-fg}-${K.deletions}{/red-fg}{gray-fg}){/gray-fg}`,Q)U+=" {magenta-fg}[uncommitted]{/magenta-fg}";return U}function v7(K,$,J,X,Z,Q=0,q){if(K.length===0&&$.length===0)return"{gray-fg}No changes compared to base branch{/gray-fg}";let Y=VK(K,$),V=q?Y.slice(Q,Q+q):Y.slice(Q),_=[];for(let z of V)if(z.type==="section-header"){let U=z.sectionType==="commits",B=U?K.length:$.length,k=U?"Commits":"Files";_.push(`{cyan-fg}{bold}▼ ${k}{/bold}{/cyan-fg} {gray-fg}(${B}){/gray-fg}`)}else if(z.type==="spacer")_.push("");else if(z.type==="commit"&&z.commit&&z.commitIndex!==void 0){let U=J?.type==="commit"&&J.index===z.commitIndex;_.push(u8(z.commit,U,X,Z))}else if(z.type==="file"&&z.file&&z.fileIndex!==void 0){let U=J?.type==="file"&&J.index===z.fileIndex;_.push(p8(z.file,U,X,Z-5))}return _.join(`
16
- `)}function L7(K,$,J=!0,X=!0){let Z=0;if(K.length>0){if(Z+=1,J)Z+=K.length}if($.length>0){if(K.length>0)Z+=1;if(Z+=1,X)Z+=$.length}return Z}function PK(K,$,J,X=!0,Z=!0){let q=VK($,J,X,Z)[K];if(!q)return null;if(q.type==="commit"&&q.commitIndex!==void 0)return{type:"commit",index:q.commitIndex};if(q.type==="file"&&q.fileIndex!==void 0)return{type:"file",index:q.fileIndex};return null}function UK(K,$,J,X=!0,Z=!0){let Q=VK($,J,X,Z);for(let q=0;q<Q.length;q++){let Y=Q[q];if(K.type==="commit"&&Y.type==="commit"&&Y.commitIndex===K.index)return q;if(K.type==="file"&&Y.type==="file"&&Y.fileIndex===K.index)return q}return 0}function CK(K,$,J,X){let Z=VK($,J),Q=0;if(K)Q=UK(K,$,J);let q=X==="down"?1:-1,Y=Q+q;while(Y>=0&&Y<Z.length){let V=PK(Y,$,J);if(V)return V;Y+=q}return K}function a(K){return K.replace(/\{/g,"{{").replace(/\}/g,"}}")}function W7(K,$,J,X,Z=0,Q,q=!1,Y=null){if(Y)return`{red-fg}Error: ${a(Y)}{/red-fg}`;if(q)return"{gray-fg}Loading...{/gray-fg}";if(K.length===0)return"{gray-fg}(empty directory){/gray-fg}";let V=Q?K.slice(Z,Z+Q):K.slice(Z),_=Math.min(Math.max(...K.map((U)=>U.name.length+(U.isDirectory?1:0))),X-10),z=[];for(let U=0;U<V.length;U++){let B=V[U],M=Z+U===$&&J,N=(B.isDirectory?`${B.name}/`:B.name).padEnd(_+1),H="";if(M)if(B.isDirectory)H=`{cyan-fg}{bold}{inverse}${a(N)}{/inverse}{/bold}{/cyan-fg}`;else H=`{cyan-fg}{bold}{inverse}${a(N)}{/inverse}{/bold}{/cyan-fg}`;else if(B.isDirectory)H=`{blue-fg}${a(N)}{/blue-fg}`;else H=a(N);z.push(H)}return z.join(`
17
- `)}function y7(K){return K.length}function bK(K,$,J){if(!K)return[];let X=K.split(`
18
- `),Z=[],Q=$?ZK($):null;for(let q=0;q<X.length;q++){let Y=X[q],V=Q?j7(Y,Q):void 0;Z.push({type:"code",lineNum:q+1,content:Y,highlighted:V})}if(J)Z.push({type:"truncation",content:"(file truncated)"});return Z}function S7(K,$,J){if(!J)return K;let Z=Math.max(10,$),Q=[];for(let q of K)if(q.type==="code"){let Y=q.content;if(!Y||Y.length<=Z){Q.push(q);continue}let V=XK(Y,Z);for(let _=0;_<V.length;_++){let z=V[_];Q.push({type:"code",lineNum:z.isContinuation?0:q.lineNum,content:z.text,highlighted:void 0,isContinuation:z.isContinuation})}}else Q.push(q);return Q}function P7(K,$,J){if(!J)return K.length;let Z=Math.max(10,$),Q=0;for(let q of K)if(q.type==="code"){let Y=q.content;if(!Y||Y.length<=Z)Q+=1;else Q+=EK(Y,Z)}else Q+=1;return Q}function xK(K){let $=0;for(let J of K)if(J.type==="code"&&J.lineNum>$)$=J.lineNum;return Math.max(3,String($).length)}function C7(K,$){if(!$||!K)return K;let J=0;for(let Q of K)if(Q===" ")J++;else if(Q==="\t")J+=2;else break;if(J===0)return K;let X="·".repeat(J),Z=K.slice(J);return X+Z}function b7(K){return K.replace(/\{/g,"{{").replace(/\}/g,"}}")}function x7(K,$,J,X=0,Z,Q=!1,q=!1,Y=!1){if(!K)return"{gray-fg}Select a file to view its contents{/gray-fg}";if(!$)return"{gray-fg}Loading...{/gray-fg}";let V=bK($,K,Q);if(V.length===0)return"{gray-fg}(empty file){/gray-fg}";let _=xK(V),z=J-_-2,U=S7(V,z,q),B=Z?U.slice(X,X+Z):U.slice(X),k=[];for(let G of B){if(G.type==="truncation"){k.push(`{yellow-fg}${b7(G.content)}{/yellow-fg}`);continue}let M=G.isContinuation??!1,T;if(M)T=">>".padStart(_," ");else T=String(G.lineNum).padStart(_," ");let N=G.content,H=!q&&N.length>z,E=G.highlighted&&!M&&!Y,A;if(E&&G.highlighted){let O=H?qK(G.highlighted,z):G.highlighted;A=QK(O)}else{let O=N;if(Y&&!M)O=C7(O,!0);if(H)O=O.slice(0,Math.max(0,z-1))+"...";A=b7(O)}let j="";if(M)j=`{cyan-fg}${T}{/cyan-fg} ${A||" "}`;else j=`{gray-fg}${T}{/gray-fg} ${A||" "}`;k.push(j)}return k.join(`
19
- `)}function w7(K,$,J,X,Z){if(!K)return 0;let Q=bK(K,$,J),q=xK(Q),Y=X-q-2;return P7(Q,Y,Z)}import*as BK from"node:fs";import*as L from"node:path";import{EventEmitter as m8}from"node:events";import{simpleGit as g8}from"simple-git";async function _K(K,$){if($.length===0)return new Set;let J=g8(K),X=new Set,Z=100;for(let Q=0;Q<$.length;Q+=Z){let q=$.slice(Q,Q+Z);try{let V=(await J.raw(["check-ignore",...q])).trim().split(`
20
- `).filter((_)=>_.length>0);for(let _ of V)X.add(_)}catch{}}return X}var f8=1048576,h8=102400;function c8(K){let $=Math.min(K.length,8192);for(let J=0;J<$;J++)if(K[J]===0)return!0;return!1}class wK extends m8{repoPath;options;_state={currentPath:"",items:[],selectedIndex:0,selectedFile:null,isLoading:!1,error:null};constructor(K,$){super();this.repoPath=K,this.options=$}get state(){return this._state}updateState(K){this._state={...this._state,...K},this.emit("state-change",this._state)}async setOptions(K){this.options={...this.options,...K},await this.loadDirectory(this._state.currentPath)}async loadDirectory(K){this.updateState({isLoading:!0,error:null,currentPath:K});try{let $=L.join(this.repoPath,K),J=await BK.promises.readdir($,{withFileTypes:!0}),X=J.map((q)=>K?L.join(K,q.name):q.name),Z=this.options.hideGitignored?await _K(this.repoPath,X):new Set,Q=J.filter((q)=>{if(this.options.hideHidden&&q.name.startsWith("."))return!1;if(this.options.hideGitignored){let Y=K?L.join(K,q.name):q.name;if(Z.has(Y))return!1}return!0}).map((q)=>({name:q.name,path:K?L.join(K,q.name):q.name,isDirectory:q.isDirectory()}));if(Q.sort((q,Y)=>{if(q.isDirectory&&!Y.isDirectory)return-1;if(!q.isDirectory&&Y.isDirectory)return 1;return q.name.localeCompare(Y.name)}),K)Q.unshift({name:"..",path:L.dirname(K)||"",isDirectory:!0});this.updateState({items:Q,selectedIndex:0,selectedFile:null,isLoading:!1})}catch($){this.updateState({error:$ instanceof Error?$.message:"Failed to read directory",items:[],isLoading:!1})}}async loadFile(K){try{let $=L.join(this.repoPath,K),J=await BK.promises.stat($);if(J.size>f8){this.updateState({selectedFile:{path:K,content:`File too large to display (${(J.size/1024/1024).toFixed(2)} MB).
21
- Maximum size: 1 MB`,truncated:!0}});return}let X=await BK.promises.readFile($);if(c8(X)){this.updateState({selectedFile:{path:K,content:"Binary file - cannot display"}});return}let Z=X.toString("utf-8"),Q=!1;if(J.size>h8)Z=`⚠ Large file (${(J.size/1024).toFixed(1)} KB)
22
-
23
- `+Z;let q=5000,Y=Z.split(`
24
- `);if(Y.length>q)Z=Y.slice(0,q).join(`
25
- `)+`
26
-
27
- ... (truncated, ${Y.length-q} more lines)`,Q=!0;this.updateState({selectedFile:{path:K,content:Z,truncated:Q}})}catch($){this.updateState({selectedFile:{path:K,content:$ instanceof Error?`Error: ${$.message}`:"Failed to read file"}})}}async selectIndex(K){if(K<0||K>=this._state.items.length)return;let $=this._state.items[K];if(this.updateState({selectedIndex:K}),$&&!$.isDirectory)await this.loadFile($.path);else this.updateState({selectedFile:null})}navigateUp(K){let $=Math.max(0,this._state.selectedIndex-1);if($===this._state.selectedIndex)return null;if(this.selectIndex($),$<K)return $;return null}navigateDown(K,$){let J=Math.min(this._state.items.length-1,this._state.selectedIndex+1);if(J===this._state.selectedIndex)return null;this.selectIndex(J);let Z=this._state.items.length>$?$-2:$,Q=K+Z;if(J>=Q)return K+1;return null}async enterDirectory(){let K=this._state.items[this._state.selectedIndex];if(!K)return;if(K.isDirectory)if(K.name===".."){let $=L.dirname(this._state.currentPath);await this.loadDirectory($==="."?"":$)}else await this.loadDirectory(K.path)}async goUp(){if(this._state.currentPath){let K=L.dirname(this._state.currentPath);await this.loadDirectory(K==="."?"":K)}}dispose(){this.removeAllListeners()}}import d8 from"neo-blessed";class uK{box;screen;selectedIndex;currentTheme;onSelect;onCancel;constructor(K,$,J,X){if(this.screen=K,this.currentTheme=$,this.onSelect=J,this.onCancel=X,this.selectedIndex=C.indexOf($),this.selectedIndex<0)this.selectedIndex=0;let Z=50,Q=C.length+12;this.box=d8.box({parent:K,top:"center",left:"center",width:Z,height:Q,border:{type:"line"},style:{border:{fg:"cyan"}},tags:!0,keys:!0}),this.setupKeyHandlers(),this.render()}setupKeyHandlers(){this.box.key(["escape","q"],()=>{this.close(),this.onCancel()}),this.box.key(["enter","space"],()=>{let K=C[this.selectedIndex];this.close(),this.onSelect(K)}),this.box.key(["up","k"],()=>{this.selectedIndex=Math.max(0,this.selectedIndex-1),this.render()}),this.box.key(["down","j"],()=>{this.selectedIndex=Math.min(C.length-1,this.selectedIndex+1),this.render()})}render(){let K=[];K.push("{bold}{cyan-fg} Select Theme{/cyan-fg}{/bold}"),K.push("");for(let J=0;J<C.length;J++){let X=C[J],Z=$K[X],Q=J===this.selectedIndex,q=X===this.currentTheme,Y=Q?"{cyan-fg}{bold}> ":" ";if(Y+=Z.displayName,Q)Y+="{/bold}{/cyan-fg}";if(q)Y+=" {gray-fg}(current){/gray-fg}";K.push(Y)}K.push(""),K.push("{gray-fg}Preview:{/gray-fg}");let $=s(C[this.selectedIndex]);K.push(" {green-fg}+ added line{/green-fg}"),K.push(" {red-fg}- deleted line{/red-fg}"),K.push(""),K.push("{gray-fg}j/k: navigate | Enter: select | Esc: cancel{/gray-fg}"),this.box.setContent(K.join(`
28
- `)),this.screen.render()}close(){this.box.destroy()}focus(){this.box.focus()}}import l8 from"neo-blessed";var w=[{title:"Navigation",entries:[{key:"j/k",description:"Move up/down"},{key:"Tab",description:"Toggle pane focus"}]},{title:"Staging",entries:[{key:"s",description:"Stage file"},{key:"U",description:"Unstage file"},{key:"A",description:"Stage all"},{key:"Z",description:"Unstage all"},{key:"Space",description:"Toggle stage"}]},{title:"Actions",entries:[{key:"c",description:"Commit panel"},{key:"r",description:"Refresh"},{key:"q",description:"Quit"}]},{title:"Resize",entries:[{key:"-",description:"Shrink top pane"},{key:"+",description:"Grow top pane"}]},{title:"Tabs",entries:[{key:"1",description:"Diff view"},{key:"2",description:"Commit panel"},{key:"3",description:"History view"},{key:"4",description:"Compare view"},{key:"5",description:"Explorer view"}]},{title:"Toggles",entries:[{key:"m",description:"Mouse mode"},{key:"w",description:"Wrap mode"},{key:"f",description:"Follow mode"},{key:"t",description:"Theme picker"},{key:"?",description:"This help"}]},{title:"Explorer",entries:[{key:"Enter",description:"Enter directory"},{key:"Backspace",description:"Go up"}]},{title:"Compare",entries:[{key:"b",description:"Base branch picker"},{key:"u",description:"Toggle uncommitted"}]},{title:"Diff",entries:[{key:"d",description:"Discard changes"}]}];class pK{box;screen;onClose;constructor(K,$){this.screen=K,this.onClose=$;let{width:J,height:X}=K,Z=J>=90,Q=Z?Math.min(80,J-4):Math.min(42,J-4),q=Math.min(this.calculateHeight(Z),X-4);this.box=l8.box({parent:K,top:"center",left:"center",width:Q,height:q,border:{type:"line"},style:{border:{fg:"cyan"}},tags:!0,keys:!0,scrollable:!0,alwaysScroll:!0}),this.setupKeyHandlers(),this.render(Z,Q)}calculateHeight(K){if(K){let $=Math.ceil(w.length/2),J=w.slice(0,$),X=w.slice($),Z=J.reduce((q,Y)=>q+Y.entries.length+2,0),Q=X.reduce((q,Y)=>q+Y.entries.length+2,0);return Math.max(Z,Q)+5}else return w.reduce(($,J)=>$+J.entries.length+2,0)+5}setupKeyHandlers(){this.box.key(["escape","enter","?","q"],()=>{this.close(),this.onClose()}),this.box.on("click",()=>{this.close(),this.onClose()})}visibleWidth(K){return K.replace(/\{[^}]+\}/g,"").length}padToVisible(K,$){let J=this.visibleWidth(K),X=Math.max(0,$-J);return K+" ".repeat(X)}render(K,$){let J=[];if(J.push("{bold}{cyan-fg} Keyboard Shortcuts{/cyan-fg}{/bold}"),J.push(""),K){let X=Math.ceil(w.length/2),Z=w.slice(0,X),Q=w.slice(X),q=Math.floor(($-6)/2),Y=this.renderGroups(Z,q),V=this.renderGroups(Q,q),_=Math.max(Y.length,V.length);for(let z=0;z<_;z++){let U=this.padToVisible(Y[z]||"",q),B=V[z]||"";J.push(U+" "+B)}}else for(let X of w){J.push(`{bold}{gray-fg}${X.title}{/gray-fg}{/bold}`);for(let Z of X.entries)J.push(` {cyan-fg}${Z.key.padEnd(10)}{/cyan-fg} ${Z.description}`);J.push("")}J.push(""),J.push("{gray-fg}Press Esc, Enter, or ? to close{/gray-fg}"),this.box.setContent(J.join(`
29
- `)),this.screen.render()}renderGroups(K,$){let J=[];for(let X of K){J.push(`{bold}{gray-fg}${X.title}{/gray-fg}{/bold}`);for(let Z of X.entries)J.push(` {cyan-fg}${Z.key.padEnd(10)}{/cyan-fg} ${Z.description}`);J.push("")}return J}close(){this.box.destroy()}focus(){this.box.focus()}}import o8 from"neo-blessed";class gK{box;screen;branches;selectedIndex;currentBranch;onSelect;onCancel;constructor(K,$,J,X,Z){if(this.screen=K,this.branches=$,this.currentBranch=J,this.onSelect=X,this.onCancel=Z,this.selectedIndex=J?$.indexOf(J):0,this.selectedIndex<0)this.selectedIndex=0;let Q=50,Y=Math.min($.length,15)+6;this.box=o8.box({parent:K,top:"center",left:"center",width:Q,height:Y,border:{type:"line"},style:{border:{fg:"cyan"}},tags:!0,keys:!0,scrollable:!0,alwaysScroll:!0}),this.setupKeyHandlers(),this.render()}setupKeyHandlers(){this.box.key(["escape","q"],()=>{this.close(),this.onCancel()}),this.box.key(["enter","space"],()=>{let K=this.branches[this.selectedIndex];if(K)this.close(),this.onSelect(K)}),this.box.key(["up","k"],()=>{this.selectedIndex=Math.max(0,this.selectedIndex-1),this.render()}),this.box.key(["down","j"],()=>{this.selectedIndex=Math.min(this.branches.length-1,this.selectedIndex+1),this.render()})}render(){let K=[];if(K.push("{bold}{cyan-fg} Select Base Branch{/cyan-fg}{/bold}"),K.push(""),this.branches.length===0)K.push("{gray-fg}No branches found{/gray-fg}");else for(let $=0;$<this.branches.length;$++){let J=this.branches[$],X=$===this.selectedIndex,Z=J===this.currentBranch,Q=X?"{cyan-fg}{bold}> ":" ";if(Q+=J,X)Q+="{/bold}{/cyan-fg}";if(Z)Q+=" {gray-fg}(current){/gray-fg}";K.push(Q)}K.push(""),K.push("{gray-fg}j/k: navigate | Enter: select | Esc: cancel{/gray-fg}"),this.box.setContent(K.join(`
30
- `)),this.screen.render()}close(){this.box.destroy()}focus(){this.box.focus()}}import r8 from"neo-blessed";class mK{box;screen;filePath;onConfirm;onCancel;constructor(K,$,J,X){this.screen=K,this.filePath=$,this.onConfirm=J,this.onCancel=X;let Z=Math.min(60,Math.max(40,$.length+20)),Q=7;this.box=r8.box({parent:K,top:"center",left:"center",width:Z,height:Q,border:{type:"line"},style:{border:{fg:"yellow"}},tags:!0,keys:!0}),this.setupKeyHandlers(),this.render()}setupKeyHandlers(){this.box.key(["y","Y"],()=>{this.close(),this.onConfirm()}),this.box.key(["n","N","escape","q"],()=>{this.close(),this.onCancel()})}render(){let K=[];K.push("{bold}{yellow-fg} Discard Changes?{/yellow-fg}{/bold}"),K.push("");let $=this.box.width-6,J=this.filePath.length>$?"..."+this.filePath.slice(-($-3)):this.filePath;K.push(`{white-fg}${J}{/white-fg}`),K.push(""),K.push("{gray-fg}Press {/gray-fg}{green-fg}y{/green-fg}{gray-fg} to confirm, {/gray-fg}{red-fg}n{/red-fg}{gray-fg} or Esc to cancel{/gray-fg}"),this.box.setContent(K.join(`
31
- `)),this.screen.render()}close(){this.box.destroy()}focus(){this.box.focus()}}import{EventEmitter as s8}from"node:events";function u7(K,$,J){if(!K.trim())return{valid:!1,error:"Commit message cannot be empty"};if($===0&&!J)return{valid:!1,error:"No changes staged for commit"};return{valid:!0,error:null}}function p7(K){return K.trim()}var g7={message:"",amend:!1,isCommitting:!1,error:null,inputFocused:!1};class fK extends s8{_state={...g7};getHeadMessage;onCommit;onSuccess;stagedCount=0;constructor(K){super();this.getHeadMessage=K.getHeadMessage,this.onCommit=K.onCommit,this.onSuccess=K.onSuccess}get state(){return this._state}update(K){this._state={...this._state,...K},this.emit("change",this._state)}setStagedCount(K){this.stagedCount=K}setMessage(K){this.update({message:K,error:null})}setInputFocused(K){this.update({inputFocused:K}),this.emit("focus-change",K)}async toggleAmend(){let K=!this._state.amend;if(this.update({amend:K}),K&&!this._state.message)try{let $=await this.getHeadMessage();if($)this.update({message:$})}catch{}}async submit(){let K=u7(this._state.message,this.stagedCount,this._state.amend);if(!K.valid){this.update({error:K.error});return}this.update({isCommitting:!0,error:null});try{await this.onCommit(p7(this._state.message),this._state.amend),this.update({message:"",amend:!1,isCommitting:!1,inputFocused:!1}),this.onSuccess()}catch($){this.update({isCommitting:!1,error:$ instanceof Error?$.message:"Commit failed"})}}reset(){this._state={...g7},this.emit("change",this._state)}}import{EventEmitter as a8}from"node:events";var n8={currentPane:"files",bottomTab:"diff",selectedIndex:0,fileListScrollOffset:0,diffScrollOffset:0,historyScrollOffset:0,compareScrollOffset:0,explorerScrollOffset:0,explorerFileScrollOffset:0,historySelectedIndex:0,compareSelectedIndex:0,includeUncommitted:!1,explorerSelectedIndex:0,wrapMode:!1,autoTabEnabled:!1,mouseEnabled:!0,showMiddleDots:!1,hideHiddenFiles:!0,hideGitignored:!0,splitRatio:0.4,activeModal:null,pendingDiscard:null,commitInputFocused:!1};class hK extends a8{_state;constructor(K={}){super();this._state={...n8,...K}}get state(){return this._state}update(K){this._state={...this._state,...K},this.emit("change",this._state)}setPane(K){if(this._state.currentPane!==K)this.update({currentPane:K}),this.emit("pane-change",K)}setTab(K){if(this._state.bottomTab!==K){let $={diff:"files",commit:"commit",history:"history",compare:"compare",explorer:"explorer"};this.update({bottomTab:K,currentPane:$[K]}),this.emit("tab-change",K)}}setSelectedIndex(K){if(this._state.selectedIndex!==K)this.update({selectedIndex:K}),this.emit("selection-change",K)}setFileListScrollOffset(K){this.update({fileListScrollOffset:Math.max(0,K)}),this.emit("scroll-change",{type:"fileList",offset:K})}setDiffScrollOffset(K){this.update({diffScrollOffset:Math.max(0,K)}),this.emit("scroll-change",{type:"diff",offset:K})}setHistoryScrollOffset(K){this.update({historyScrollOffset:Math.max(0,K)}),this.emit("scroll-change",{type:"history",offset:K})}setCompareScrollOffset(K){this.update({compareScrollOffset:Math.max(0,K)}),this.emit("scroll-change",{type:"compare",offset:K})}setExplorerScrollOffset(K){this.update({explorerScrollOffset:Math.max(0,K)}),this.emit("scroll-change",{type:"explorer",offset:K})}setExplorerFileScrollOffset(K){this.update({explorerFileScrollOffset:Math.max(0,K)}),this.emit("scroll-change",{type:"explorerFile",offset:K})}setHistorySelectedIndex(K){this.update({historySelectedIndex:Math.max(0,K)})}setCompareSelectedIndex(K){this.update({compareSelectedIndex:Math.max(0,K)})}toggleIncludeUncommitted(){this.update({includeUncommitted:!this._state.includeUncommitted})}setExplorerSelectedIndex(K){this.update({explorerSelectedIndex:Math.max(0,K)})}toggleWrapMode(){this.update({wrapMode:!this._state.wrapMode,diffScrollOffset:0})}toggleAutoTab(){this.update({autoTabEnabled:!this._state.autoTabEnabled})}toggleMouse(){this.update({mouseEnabled:!this._state.mouseEnabled})}toggleMiddleDots(){this.update({showMiddleDots:!this._state.showMiddleDots})}toggleHideHiddenFiles(){this.update({hideHiddenFiles:!this._state.hideHiddenFiles})}toggleHideGitignored(){this.update({hideGitignored:!this._state.hideGitignored})}adjustSplitRatio(K){let $=Math.min(0.85,Math.max(0.15,this._state.splitRatio+K));this.update({splitRatio:$})}setSplitRatio(K){this.update({splitRatio:Math.min(0.85,Math.max(0.15,K))})}openModal(K){this.update({activeModal:K}),this.emit("modal-change",K)}closeModal(){this.update({activeModal:null}),this.emit("modal-change",null)}toggleModal(K){if(this._state.activeModal===K)this.closeModal();else this.openModal(K)}setPendingDiscard(K){this.update({pendingDiscard:K})}setCommitInputFocused(K){this.update({commitInputFocused:K})}togglePane(){let{bottomTab:K,currentPane:$}=this._state;if(K==="diff"||K==="commit")this.setPane($==="files"?"diff":"files");else if(K==="history")this.setPane($==="history"?"diff":"history");else if(K==="compare")this.setPane($==="compare"?"diff":"compare");else if(K==="explorer")this.setPane($==="explorer"?"diff":"explorer")}}import*as W from"node:path";import*as g from"node:fs";import{watch as z8}from"chokidar";import{EventEmitter as J9}from"node:events";import X9 from"ignore";class m7{queue=[];isProcessing=!1;pendingMutations=0;refreshScheduled=!1;enqueue(K){return new Promise(($,J)=>{this.queue.push({execute:K,resolve:$,reject:J}),this.processNext()})}enqueueMutation(K){return this.pendingMutations++,this.enqueue(K).finally(()=>{this.pendingMutations--})}hasPendingMutations(){return this.pendingMutations>0}scheduleRefresh(K){if(this.pendingMutations>0)return;if(this.refreshScheduled)return;this.refreshScheduled=!0,this.enqueue(async()=>{this.refreshScheduled=!1,await K()}).catch(()=>{this.refreshScheduled=!1})}isBusy(){return this.isProcessing||this.queue.length>0}async processNext(){if(this.isProcessing||this.queue.length===0)return;this.isProcessing=!0;let K=this.queue.shift();try{let $=await K.execute();K.resolve($)}catch($){K.reject($ instanceof Error?$:Error(String($)))}finally{this.isProcessing=!1,this.processNext()}}}var cK=new Map;function f7(K){let $=cK.get(K);if(!$)$=new m7,cK.set(K,$);return $}function h7(K){cK.delete(K)}import{simpleGit as y}from"simple-git";import*as l7 from"node:fs";import*as o7 from"node:path";function c7(K){let $=new Map;for(let J of K.trim().split(`
32
- `)){if(!J)continue;let X=J.split("\t");if(X.length>=3){let Z=X[0]==="-"?0:parseInt(X[0],10),Q=X[1]==="-"?0:parseInt(X[1],10),q=X.slice(2).join("\t");$.set(q,{insertions:Z,deletions:Q})}}return $}async function i8(K,$){try{let J=o7.join(K,$);return(await l7.promises.readFile(J,"utf-8")).split(`
33
- `).filter((Z)=>Z.length>0).length}catch{return 0}}function d7(K){switch(K){case"M":return"modified";case"A":return"added";case"D":return"deleted";case"?":return"untracked";case"R":return"renamed";case"C":return"copied";default:return"modified"}}async function r7(K){let $=y(K);try{if(!await $.checkIsRepo())return{files:[],branch:{current:"",ahead:0,behind:0},isRepo:!1};let X=await $.status(),Z=[];for(let G of X.staged)Z.push({path:G,status:"added",staged:!0});for(let G of X.modified)if(!Z.find((T)=>T.path===G&&T.staged))Z.push({path:G,status:"modified",staged:!1});for(let G of X.deleted)Z.push({path:G,status:"deleted",staged:!1});for(let G of X.not_added)Z.push({path:G,status:"untracked",staged:!1});for(let G of X.renamed)Z.push({path:G.to,originalPath:G.from,status:"renamed",staged:!0});let Q=[],q=new Set,Y=X.files.filter((G)=>G.working_dir==="?").map((G)=>G.path),V=await _K(K,Y);for(let G of X.files){if(G.index==="!"||G.working_dir==="!"||V.has(G.path))continue;let M=`${G.path}-${G.index!==" "&&G.index!=="?"}`;if(q.has(M))continue;if(q.add(M),G.index&&G.index!==" "&&G.index!=="?")Q.push({path:G.path,status:d7(G.index),staged:!0});if(G.working_dir&&G.working_dir!==" ")Q.push({path:G.path,status:G.working_dir==="?"?"untracked":d7(G.working_dir),staged:!1})}let[_,z]=await Promise.all([$.diff(["--cached","--numstat"]).catch(()=>""),$.diff(["--numstat"]).catch(()=>"")]),U=c7(_),B=c7(z);for(let G of Q){let M=G.staged?U.get(G.path):B.get(G.path);if(M)G.insertions=M.insertions,G.deletions=M.deletions}let k=Q.filter((G)=>G.status==="untracked");if(k.length>0){let G=await Promise.all(k.map((M)=>i8(K,M.path)));for(let M=0;M<k.length;M++)k[M].insertions=G[M],k[M].deletions=0}return{files:Q,branch:{current:X.current||"HEAD",tracking:X.tracking||void 0,ahead:X.ahead,behind:X.behind},isRepo:!0}}catch{return{files:[],branch:{current:"",ahead:0,behind:0},isRepo:!1}}}async function s7(K,$){await y(K).add($)}async function a7(K,$){await y(K).reset(["HEAD","--",$])}async function n7(K){await y(K).add("-A")}async function i7(K){await y(K).reset(["HEAD"])}async function t7(K,$){await y(K).checkout(["--",$])}async function e7(K,$,J=!1){await y(K).commit($,void 0,J?{"--amend":null}:void 0)}async function K8(K){let $=y(K);try{return(await $.log({n:1})).latest?.message||""}catch{return""}}async function $8(K,$=50){let J=y(K);try{return(await J.log({n:$})).all.map((Z)=>({hash:Z.hash,shortHash:Z.hash.slice(0,7),message:Z.message.split(`
34
- `)[0],author:Z.author_name,date:new Date(Z.date),refs:Z.refs||""}))}catch{return[]}}import{execSync as t8}from"node:child_process";import{simpleGit as n}from"simple-git";function e8(K){let $=K.match(/^@@ -(\d+)(?:,\d+)? \+(\d+)(?:,\d+)? @@/);if($)return{oldStart:parseInt($[1],10),newStart:parseInt($[2],10)};return null}function GK(K){let $=K.split(`
35
- `),J=[],X=0,Z=0;for(let Q of $)if(Q.startsWith("diff --git")||Q.startsWith("index ")||Q.startsWith("---")||Q.startsWith("+++")||Q.startsWith("new file")||Q.startsWith("deleted file")||Q.startsWith("Binary files")||Q.startsWith("similarity index")||Q.startsWith("rename from")||Q.startsWith("rename to"))J.push({type:"header",content:Q});else if(Q.startsWith("@@")){let q=e8(Q);if(q)X=q.oldStart,Z=q.newStart;J.push({type:"hunk",content:Q})}else if(Q.startsWith("+"))J.push({type:"addition",content:Q,newLineNum:Z++});else if(Q.startsWith("-"))J.push({type:"deletion",content:Q,oldLineNum:X++});else J.push({type:"context",content:Q,oldLineNum:X++,newLineNum:Z++});return J}async function i(K,$,J=!1){let X=n(K);try{let Z=[];if(J)Z.push("--cached");if($)Z.push("--",$);let Q=await X.diff(Z),q=GK(Q);return{raw:Q,lines:q}}catch{return{raw:"",lines:[]}}}async function dK(K,$){try{let J=t8(`cat "${$}"`,{cwd:K,encoding:"utf-8"}),X=[{type:"header",content:`diff --git a/${$} b/${$}`},{type:"header",content:"new file mode 100644"},{type:"header",content:"--- /dev/null"},{type:"header",content:`+++ b/${$}`}],Z=J.split(`
36
- `);X.push({type:"hunk",content:`@@ -0,0 +1,${Z.length} @@`});let Q=1;for(let Y of Z)X.push({type:"addition",content:"+"+Y,newLineNum:Q++});return{raw:X.map((Y)=>Y.content).join(`
37
- `),lines:X}}catch{return{raw:"",lines:[]}}}async function lK(K){return i(K,void 0,!0)}async function oK(K){let $=n(K),J=new Set,X=[];try{let Z=await $.raw(["log","--oneline","--decorate=short","--all","-n","200"]),Q=/\(([^)]+)\)/g;for(let q of Z.split(`
38
- `)){let Y=Q.exec(q);if(Y){let V=Y[1].split(",").map((_)=>_.trim());for(let _ of V){if(_.startsWith("HEAD")||_.startsWith("tag:")||!_.includes("/"))continue;let z=_.replace(/^.*-> /,"");if(z.includes("/")&&!J.has(z))J.add(z),X.push(z)}}Q.lastIndex=0}if(X.length>0)X.sort((q,Y)=>{let V=q.split("/").slice(1).join("/"),_=Y.split("/").slice(1).join("/"),z=V==="main"||V==="master",U=_==="main"||_==="master";if(z&&!U)return-1;if(!z&&U)return 1;if(z&&U){let B=q.startsWith("origin/"),k=Y.startsWith("origin/");if(B&&!k)return 1;if(!B&&k)return-1}return 0})}catch{}return[...new Set(X)]}async function J8(K){return(await oK(K))[0]??null}async function rK(K,$){let J=n(K),Z=(await J.raw(["merge-base",$,"HEAD"])).trim(),Q=await J.raw(["diff","--numstat",`${Z}...HEAD`]),q=await J.raw(["diff","--name-status",`${Z}...HEAD`]),Y=await J.raw(["diff",`${Z}...HEAD`]),V=Q.trim().split(`
39
- `).filter((A)=>A),_=new Map;for(let A of V){let j=A.split("\t");if(j.length>=3){let O=j[0]==="-"?0:parseInt(j[0],10),D=j[1]==="-"?0:parseInt(j[1],10),I=j.slice(2).join("\t");_.set(I,{additions:O,deletions:D})}}let z=q.trim().split(`
40
- `).filter((A)=>A),U=new Map;for(let A of z){let j=A.split("\t");if(j.length>=2){let O=j[0][0],D=j[j.length-1],I;switch(O){case"A":I="added";break;case"D":I="deleted";break;case"R":I="renamed";break;default:I="modified"}U.set(D,I)}}let B=[],k=Y.split(/(?=^diff --git )/m).filter((A)=>A.trim());for(let A of k){let j=A.match(/^diff --git a\/.+ b\/(.+)$/m);if(!j)continue;let O=j[1],D=GK(A),I=_.get(O)||{additions:0,deletions:0},P=U.get(O)||"modified";B.push({path:O,status:P,additions:I.additions,deletions:I.deletions,diff:{raw:A,lines:D}})}let G=0,M=0;for(let A of B)G+=A.additions,M+=A.deletions;let N=(await J.status()).files.length,E=(await J.log({from:Z,to:"HEAD"})).all.map((A)=>({hash:A.hash,shortHash:A.hash.slice(0,7),message:A.message.split(`
41
- `)[0],author:A.author_name,date:new Date(A.date),refs:A.refs||""}));return{baseBranch:$,stats:{filesChanged:B.length,additions:G,deletions:M},files:B,commits:E,uncommittedCount:N}}async function sK(K,$){let J=n(K);try{let X=await J.raw(["show",$,"--format="]),Z=GK(X);return{raw:X,lines:Z}}catch{return{raw:"",lines:[]}}}async function X8(K,$){let J=n(K),X=await rK(K,$),Z=await J.diff(["--cached","--numstat"]),Q=await J.diff(["--numstat"]),q=await J.diff(["--cached"]),Y=await J.diff([]),V=new Map;for(let A of Z.trim().split(`
42
- `).filter((j)=>j)){let j=A.split("\t");if(j.length>=3){let O=j[0]==="-"?0:parseInt(j[0],10),D=j[1]==="-"?0:parseInt(j[1],10),I=j.slice(2).join("\t");V.set(I,{additions:O,deletions:D,staged:!0,unstaged:!1})}}for(let A of Q.trim().split(`
43
- `).filter((j)=>j)){let j=A.split("\t");if(j.length>=3){let O=j[0]==="-"?0:parseInt(j[0],10),D=j[1]==="-"?0:parseInt(j[1],10),I=j.slice(2).join("\t"),P=V.get(I);if(P)P.additions+=O,P.deletions+=D,P.unstaged=!0;else V.set(I,{additions:O,deletions:D,staged:!1,unstaged:!0})}}let _=await J.status(),z=new Map;for(let A of _.files)if(A.index==="A"||A.working_dir==="?")z.set(A.path,"added");else if(A.index==="D"||A.working_dir==="D")z.set(A.path,"deleted");else if(A.index==="R")z.set(A.path,"renamed");else z.set(A.path,"modified");let U=[],k=(q+Y).split(/(?=^diff --git )/m).filter((A)=>A.trim()),G=new Set;for(let A of k){let j=A.match(/^diff --git a\/.+ b\/(.+)$/m);if(!j)continue;let O=j[1];if(G.has(O))continue;G.add(O);let D=GK(A),I=V.get(O)||{additions:0,deletions:0},P=z.get(O)||"modified";U.push({path:O,status:P,additions:I.additions,deletions:I.deletions,diff:{raw:A,lines:D},isUncommitted:!0})}let M=new Set(X.files.map((A)=>A.path)),T=[];for(let A of X.files){let j=U.find((O)=>O.path===A.path);if(j)T.push(A),T.push(j);else T.push(A)}for(let A of U)if(!M.has(A.path))T.push(A);let N=0,H=0,E=new Set;for(let A of T){if(!E.has(A.path))E.add(A.path);N+=A.additions,H+=A.deletions}return{baseBranch:X.baseBranch,stats:{filesChanged:E.size,additions:N,deletions:H},files:T,commits:X.commits,uncommittedCount:X.uncommittedCount}}import*as S from"node:fs";import*as p from"node:path";import*as Z8 from"node:os";var AK=p.join(Z8.homedir(),".cache","diffstalker","base-branches.json");function K9(){let K=p.dirname(AK);if(!S.existsSync(K))S.mkdirSync(K,{recursive:!0})}function Q8(){try{if(S.existsSync(AK))return JSON.parse(S.readFileSync(AK,"utf-8"))}catch{}return{}}function $9(K){K9(),S.writeFileSync(AK,JSON.stringify(K,null,2)+`
44
- `)}function q8(K){let $=Q8(),J=p.resolve(K);return $[J]}function Y8(K,$){let J=Q8(),X=p.resolve(K);J[X]=$,$9(J)}class V8 extends J9{repoPath;queue;gitWatcher=null;workingDirWatcher=null;ignorer=null;_state={status:null,diff:null,stagedDiff:"",selectedFile:null,isLoading:!1,error:null};_compareState={compareDiff:null,compareBaseBranch:null,compareLoading:!1,compareError:null};_historyState={commits:[],selectedCommit:null,commitDiff:null,isLoading:!1};_compareSelectionState={type:null,index:0,diff:null};constructor(K){super();this.repoPath=K,this.queue=f7(K)}get state(){return this._state}get compareState(){return this._compareState}get historyState(){return this._historyState}get compareSelectionState(){return this._compareSelectionState}updateState(K){this._state={...this._state,...K},this.emit("state-change",this._state)}updateCompareState(K){this._compareState={...this._compareState,...K},this.emit("compare-state-change",this._compareState)}updateHistoryState(K){this._historyState={...this._historyState,...K},this.emit("history-state-change",this._historyState)}updateCompareSelectionState(K){this._compareSelectionState={...this._compareSelectionState,...K},this.emit("compare-selection-change",this._compareSelectionState)}loadGitignore(){let K=X9();K.add(".git");let $=W.join(this.repoPath,".gitignore");if(g.existsSync($))K.add(g.readFileSync($,"utf-8"));let J=W.join(this.repoPath,".git","info","exclude");if(g.existsSync(J))K.add(g.readFileSync(J,"utf-8"));return K}startWatching(){let K=W.join(this.repoPath,".git");if(!g.existsSync(K))return;let $=W.join(K,"index"),J=W.join(K,"HEAD"),X=W.join(K,"refs"),Z=W.join(this.repoPath,".gitignore");this.gitWatcher=z8([$,J,X,Z],{persistent:!0,ignoreInitial:!0,usePolling:!0,interval:100}),this.ignorer=this.loadGitignore(),this.workingDirWatcher=z8(this.repoPath,{persistent:!0,ignoreInitial:!0,ignored:(q)=>{let Y=W.relative(this.repoPath,q);if(!Y)return!1;return this.ignorer?.ignores(Y)??!1},awaitWriteFinish:{stabilityThreshold:100,pollInterval:50}});let Q=()=>this.scheduleRefresh();this.gitWatcher.on("change",(q)=>{if(q===Z)this.ignorer=this.loadGitignore();Q()}),this.gitWatcher.on("add",Q),this.gitWatcher.on("unlink",Q),this.gitWatcher.on("error",(q)=>{let Y=q instanceof Error?q.message:String(q);this.emit("error",`Git watcher error: ${Y}`)}),this.workingDirWatcher.on("change",Q),this.workingDirWatcher.on("add",Q),this.workingDirWatcher.on("unlink",Q),this.workingDirWatcher.on("error",(q)=>{let Y=q instanceof Error?q.message:String(q);this.emit("error",`Working dir watcher error: ${Y}`)})}dispose(){this.gitWatcher?.close(),this.workingDirWatcher?.close(),h7(this.repoPath)}scheduleRefresh(){this.queue.scheduleRefresh(()=>this.doRefresh())}async refresh(){await this.queue.enqueue(()=>this.doRefresh())}async doRefresh(){this.updateState({isLoading:!0,error:null});try{let K=await r7(this.repoPath);if(!K.isRepo){this.updateState({status:K,diff:null,stagedDiff:"",isLoading:!1,error:"Not a git repository"});return}let[$,J]=await Promise.all([lK(this.repoPath),i(this.repoPath,void 0,!1)]),X,Z=this._state.selectedFile;if(Z){let Q=K.files.find((q)=>q.path===Z.path&&q.staged===Z.staged);if(Q)if(Q.status==="untracked")X=await dK(this.repoPath,Q.path);else X=await i(this.repoPath,Q.path,Q.staged);else X=J.raw?J:$,this.updateState({selectedFile:null})}else if(J.raw)X=J;else if($.raw)X=$;else X={raw:"",lines:[]};this.updateState({status:K,diff:X,stagedDiff:$.raw,isLoading:!1})}catch(K){this.updateState({isLoading:!1,error:K instanceof Error?K.message:"Unknown error"})}}async selectFile(K){if(this.updateState({selectedFile:K}),!this._state.status?.isRepo)return;await this.queue.enqueue(async()=>{if(K){let $;if(K.status==="untracked")$=await dK(this.repoPath,K.path);else $=await i(this.repoPath,K.path,K.staged);this.updateState({diff:$})}else{let $=await lK(this.repoPath);this.updateState({diff:$})}})}async stage(K){let $=this._state.status;if($)this.updateState({status:{...$,files:$.files.map((J)=>J.path===K.path&&!J.staged?{...J,staged:!0}:J)}});try{await this.queue.enqueueMutation(()=>s7(this.repoPath,K.path)),this.scheduleRefresh()}catch(J){await this.refresh(),this.updateState({error:`Failed to stage ${K.path}: ${J instanceof Error?J.message:String(J)}`})}}async unstage(K){let $=this._state.status;if($)this.updateState({status:{...$,files:$.files.map((J)=>J.path===K.path&&J.staged?{...J,staged:!1}:J)}});try{await this.queue.enqueueMutation(()=>a7(this.repoPath,K.path)),this.scheduleRefresh()}catch(J){await this.refresh(),this.updateState({error:`Failed to unstage ${K.path}: ${J instanceof Error?J.message:String(J)}`})}}async discard(K){if(K.staged||K.status==="untracked")return;try{await this.queue.enqueueMutation(()=>t7(this.repoPath,K.path)),await this.refresh()}catch($){this.updateState({error:`Failed to discard ${K.path}: ${$ instanceof Error?$.message:String($)}`})}}async stageAll(){try{await this.queue.enqueueMutation(()=>n7(this.repoPath)),await this.refresh()}catch(K){this.updateState({error:`Failed to stage all: ${K instanceof Error?K.message:String(K)}`})}}async unstageAll(){try{await this.queue.enqueueMutation(()=>i7(this.repoPath)),await this.refresh()}catch(K){this.updateState({error:`Failed to unstage all: ${K instanceof Error?K.message:String(K)}`})}}async commit(K,$=!1){try{await this.queue.enqueue(()=>e7(this.repoPath,K,$)),await this.refresh()}catch(J){this.updateState({error:`Failed to commit: ${J instanceof Error?J.message:String(J)}`})}}async getHeadCommitMessage(){return this.queue.enqueue(()=>K8(this.repoPath))}async refreshCompareDiff(K=!1){this.updateCompareState({compareLoading:!0,compareError:null});try{await this.queue.enqueue(async()=>{let $=this._compareState.compareBaseBranch;if(!$)$=q8(this.repoPath)??await J8(this.repoPath),this.updateCompareState({compareBaseBranch:$});if($){let J=K?await X8(this.repoPath,$):await rK(this.repoPath,$);this.updateCompareState({compareDiff:J,compareLoading:!1})}else this.updateCompareState({compareDiff:null,compareLoading:!1,compareError:"No base branch found"})})}catch($){this.updateCompareState({compareLoading:!1,compareError:`Failed to load compare diff: ${$ instanceof Error?$.message:String($)}`})}}async getCandidateBaseBranches(){return oK(this.repoPath)}async setCompareBaseBranch(K,$=!1){this.updateCompareState({compareBaseBranch:K}),Y8(this.repoPath,K),await this.refreshCompareDiff($)}async loadHistory(K=100){this.updateHistoryState({isLoading:!0});try{let $=await this.queue.enqueue(()=>$8(this.repoPath,K));this.updateHistoryState({commits:$,isLoading:!1})}catch($){this.updateHistoryState({isLoading:!1}),this.updateState({error:`Failed to load history: ${$ instanceof Error?$.message:String($)}`})}}async selectHistoryCommit(K){if(this.updateHistoryState({selectedCommit:K,commitDiff:null}),!K)return;try{await this.queue.enqueue(async()=>{let $=await sK(this.repoPath,K.hash);this.updateHistoryState({commitDiff:$})})}catch($){this.updateState({error:`Failed to load commit diff: ${$ instanceof Error?$.message:String($)}`})}}async selectCompareCommit(K){let $=this._compareState.compareDiff;if(!$||K<0||K>=$.commits.length){this.updateCompareSelectionState({type:null,index:0,diff:null});return}let J=$.commits[K];this.updateCompareSelectionState({type:"commit",index:K,diff:null});try{await this.queue.enqueue(async()=>{let X=await sK(this.repoPath,J.hash);this.updateCompareSelectionState({diff:X})})}catch(X){this.updateState({error:`Failed to load commit diff: ${X instanceof Error?X.message:String(X)}`})}}selectCompareFile(K){let $=this._compareState.compareDiff;if(!$||K<0||K>=$.files.length){this.updateCompareSelectionState({type:null,index:0,diff:null});return}let J=$.files[K];this.updateCompareSelectionState({type:"file",index:K,diff:J.diff})}}var kK=new Map;function U8(K){let $=kK.get(K);if(!$)$=new V8(K),kK.set(K,$);return $}function aK(K){let $=kK.get(K);if($)$.dispose(),kK.delete(K)}import*as m from"node:fs";import*as jK from"node:path";import{watch as Z9}from"chokidar";import{EventEmitter as Q9}from"node:events";import*as _8 from"node:path";import*as nK from"node:os";function B8(K){if(K.startsWith("~/"))return _8.join(nK.homedir(),K.slice(2));if(K==="~")return nK.homedir();return K}function iK(K){let $=K.split(`
45
- `);for(let J=$.length-1;J>=0;J--){let X=$[J].trim();if(X)return X}return""}class tK extends Q9{targetFile;debug;watcher=null;debounceTimer=null;lastReadPath=null;_state={path:null,lastUpdate:null,rawContent:null,sourceFile:null};constructor(K,$=!1){super();this.targetFile=K,this.debug=$,this._state.sourceFile=K}get state(){return this._state}updateState(K){this._state={...this._state,...K},this.emit("path-change",this._state)}processContent(K){if(!K)return null;let $=B8(K);return jK.isAbsolute($)?$:jK.resolve($)}readTargetDebounced(){if(this.debounceTimer)clearTimeout(this.debounceTimer);this.debounceTimer=setTimeout(()=>{this.readTarget()},100)}readTarget(){try{let K=m.readFileSync(this.targetFile,"utf-8"),$=iK(K);if($&&$!==this.lastReadPath){let J=this.processContent($),X=new Date;if(this.debug&&J)process.stderr.write(`[diffstalker ${X.toISOString()}] Path change detected
2
+ import O5 from"neo-blessed";import J$ from"neo-blessed";var x$=0.05;function A5($,J,Z,K=1){let X=K+4,Q=$-X,q=Math.floor(Q*Z),z=Q-q;return{width:J,height:$,headerHeight:K,topPaneHeight:q,bottomPaneHeight:z,footerRow:$-1}}function D5($,J,Z,K){let X=J+1,Q=X+Z,q=Q+1,z=q+K,V=$-1;return{stagingPaneStart:X,fileListEnd:Q,diffPaneStart:q,diffPaneEnd:z,footerRow:V}}class p${screen;headerBox;topSeparator;topPane;middleSeparator;bottomPane;bottomSeparator;footerBox;_dimensions;_splitRatio;constructor($,J=0.4){this.screen=$,this._splitRatio=J,this._dimensions=this.calculateDimensions(),this.headerBox=this.createHeaderBox(),this.topSeparator=this.createSeparator(this._dimensions.headerHeight),this.topPane=this.createTopPane(),this.middleSeparator=this.createSeparator(this._dimensions.headerHeight+1+this._dimensions.topPaneHeight),this.bottomPane=this.createBottomPane(),this.bottomSeparator=this.createSeparator(this._dimensions.headerHeight+2+this._dimensions.topPaneHeight+this._dimensions.bottomPaneHeight),this.footerBox=this.createFooterBox(),$.on("resize",()=>this.onResize())}get dimensions(){return this._dimensions}get splitRatio(){return this._splitRatio}setSplitRatio($){this._splitRatio=Math.min(0.85,Math.max(0.15,$)),this.updateLayout()}adjustSplitRatio($){this.setSplitRatio(this._splitRatio+$)}calculateDimensions(){let $=this.screen.height||24,J=this.screen.width||80;return A5($,J,this._splitRatio)}createHeaderBox(){return J$.box({parent:this.screen,top:0,left:0,width:"100%",height:this._dimensions.headerHeight,tags:!0})}createSeparator($){let J=this.screen.width||80;return J$.box({parent:this.screen,top:$,left:0,width:"100%",height:1,content:"─".repeat(J),style:{fg:"gray"}})}createTopPane(){return J$.box({parent:this.screen,top:this._dimensions.headerHeight+1,left:0,width:"100%",height:this._dimensions.topPaneHeight,tags:!0,scrollable:!0,alwaysScroll:!0,wrap:!1,scrollbar:{ch:" ",track:{bg:"gray"},style:{inverse:!0}}})}createBottomPane(){return J$.box({parent:this.screen,top:this._dimensions.headerHeight+2+this._dimensions.topPaneHeight,left:0,width:"100%",height:this._dimensions.bottomPaneHeight,tags:!0,scrollable:!0,alwaysScroll:!0,wrap:!1,scrollbar:{ch:" ",track:{bg:"gray"},style:{inverse:!0}}})}createFooterBox(){return J$.box({parent:this.screen,top:this._dimensions.footerRow,left:0,width:"100%",height:1,tags:!0})}onResize(){this._dimensions=this.calculateDimensions(),this.updateLayout()}updateLayout(){this._dimensions=this.calculateDimensions();let $=this.screen.width||80;this.headerBox.height=this._dimensions.headerHeight,this.headerBox.width=$,this.topSeparator.top=this._dimensions.headerHeight,this.topSeparator.width=$,this.topSeparator.setContent("─".repeat($)),this.topPane.top=this._dimensions.headerHeight+1,this.topPane.height=this._dimensions.topPaneHeight,this.topPane.width=$,this.middleSeparator.top=this._dimensions.headerHeight+1+this._dimensions.topPaneHeight,this.middleSeparator.width=$,this.middleSeparator.setContent("─".repeat($)),this.bottomPane.top=this._dimensions.headerHeight+2+this._dimensions.topPaneHeight,this.bottomPane.height=this._dimensions.bottomPaneHeight,this.bottomPane.width=$,this.bottomSeparator.top=this._dimensions.headerHeight+2+this._dimensions.topPaneHeight+this._dimensions.bottomPaneHeight,this.bottomSeparator.width=$,this.bottomSeparator.setContent("─".repeat($)),this.footerBox.top=this._dimensions.footerRow,this.footerBox.width=$}getPaneBoundaries(){return D5(this._dimensions.height,this._dimensions.headerHeight,this._dimensions.topPaneHeight,this._dimensions.bottomPaneHeight)}screenYToTopPaneRow($){let J=this._dimensions.headerHeight+1,Z=J+this._dimensions.topPaneHeight;if($<J||$>=Z)return-1;return $-J}screenYToBottomPaneRow($){let J=this._dimensions.headerHeight+2+this._dimensions.topPaneHeight,Z=J+this._dimensions.bottomPaneHeight;if($<J||$>=Z)return-1;return $-J}get topPaneTop(){return this._dimensions.headerHeight+1}get bottomPaneTop(){return this._dimensions.headerHeight+2+this._dimensions.topPaneHeight}}function Z$($){let J=$.filter((X)=>!X.staged&&X.status!=="untracked"),Z=$.filter((X)=>!X.staged&&X.status==="untracked"),K=$.filter((X)=>X.staged);return{modified:J,untracked:Z,staged:K,ordered:[...J,...Z,...K]}}function s($,J){let{modified:Z,untracked:K}=Z$($),X=Z.length,Q=K.length;if(J<X)return{category:"modified",categoryIndex:J};if(J<X+Q)return{category:"untracked",categoryIndex:J-X};return{category:"staged",categoryIndex:J-X-Q}}function L8($,J,Z){let{modified:K,untracked:X,staged:Q,ordered:q}=Z$($);if(q.length===0)return 0;let V={modified:K,untracked:X,staged:Q}[J];if(V.length===0)return q.length-1;let Y=Math.min(Z,V.length-1);return{modified:0,untracked:K.length,staged:K.length+X.length}[J]+Y}function g$($,J){if($.length<=J)return $;let K=Math.max(J,20);if($.length<=K)return $;let X=$.split("/");if(X.length===1){let j=Math.floor((K-1)/2);return $.slice(0,j)+""+$.slice(-(K-j-1))}let Q=X[X.length-1],q=X[0],z="/…/";if(q.length+z.length+Q.length>K){let j=K-2;if(Q.length>j){let G=Math.floor((j-1)/2);return"…/"+Q.slice(0,G)+"…"+Q.slice(-(j-G-1))}return"…/"+Q}let Y=q,U=1;while(U<X.length-1){let j=X[U],G=Y+"/"+j;if(G.length+z.length+Q.length<=K)Y=G,U++;else break}if(U===X.length-1)return $;return Y+z+Q}function V$($){switch($){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 Y$($){switch($){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 U$($,J){if($===void 0&&J===void 0)return"";let Z=[];if($!==void 0&&$>0)Z.push(`{green-fg}+${$}{/green-fg}`);if(J!==void 0&&J>0)Z.push(`{red-fg}-${J}{/red-fg}`);return Z.length>0?" "+Z.join(" "):""}function G$($,J){if($&&J)return"{cyan-fg}{bold}▸ {/bold}{/cyan-fg}";else if($)return"{gray-fg}▸ {/gray-fg}";return" "}function B$($,J,Z,K){let X=g$($,K);if(J&&Z)return`{cyan-fg}{inverse}${X}{/inverse}{/cyan-fg}`;else if(J)return`{cyan-fg}${X}{/cyan-fg}`;return X}function j$($){if(!$)return"";return` {gray-fg}← ${g$($,30)}{/gray-fg}`}function _$($){let{modified:J,untracked:Z,staged:K}=Z$($),X=[],Q=0;if(J.length>0)X.push({type:"header",content:"Modified:",headerColor:"yellow"}),J.forEach((q)=>{X.push({type:"file",file:q,fileIndex:Q++})});if(Z.length>0){if(J.length>0)X.push({type:"spacer"});X.push({type:"header",content:"Untracked:",headerColor:"gray"}),Z.forEach((q)=>{X.push({type:"file",file:q,fileIndex:Q++})})}if(K.length>0){if(J.length>0||Z.length>0)X.push({type:"spacer"});X.push({type:"header",content:"Staged:",headerColor:"green"}),K.forEach((q)=>{X.push({type:"file",file:q,fileIndex:Q++})})}return X}function T5($,J){if(!J)return"";let Z=J.staged.get($.path)??0,K=J.unstaged.get($.path)??0,X=Z+K;if(X===0)return"";let Q=$.staged?Z:K;if(Q===X)return` {cyan-fg}@${X}{/cyan-fg}`;return` {cyan-fg}@${Q}/${X}{/cyan-fg}`}function N5($,J,Z,K,X,Q){let q=J===Z,z=V$($.status),V=Y$($.status),Y=$.staged?"[-]":"[+]",U=$.staged?"red":"green",j=U$($.insertions,$.deletions),G=T5($,Q),B=j.replace(/\{[^}]+\}/g,"").length,_=G.replace(/\{[^}]+\}/g,"").length,v=X-B-_,W=G$(q,K);return W+=`{${U}-fg}${Y}{/${U}-fg} `,W+=`{${V}-fg}${z}{/${V}-fg} `,W+=B$($.path,q,K,v),W+=j$($.originalPath),W+=j,W+=G,W}function R8($,J,Z,K,X=0,Q,q){if($.length===0)return"{gray-fg} No changes{/gray-fg}";let z=_$($),V=K-12,Y=Q?z.slice(X,X+Q):z.slice(X),U=[],j=!1;for(let G of Y)switch(G.type){case"header":{let B=`{bold}{${G.headerColor}-fg}${G.content}{/${G.headerColor}-fg}{/bold}`;if(!j)j=!0,B+=" {gray-fg}(h:flat){/gray-fg}";U.push(B);break}case"spacer":U.push("");break;case"file":if(G.file&&G.fileIndex!==void 0)U.push(N5(G.file,G.fileIndex,J,Z,V,q??null));break}return U.join(`
3
+ `)}function F8($){return _$($).length}function b($,J){let{ordered:Z}=Z$($);return Z[J]??null}function I8($,J){let K=_$(J)[$];if(K?.type==="file"&&K.fileIndex!==void 0)return K.fileIndex;return null}function C8($,J){let Z=_$(J);for(let K=0;K<Z.length;K++)if(Z[K].type==="file"&&Z[K].fileIndex===$)return K;return 0}function M$($,J){let Z=new Map;for(let X of $){let Q=Z.get(X.path)??{staged:null,unstaged:null};if(X.staged)Q.staged=X;else Q.unstaged=X;Z.set(X.path,Q)}let K=[];for(let[X,{staged:Q,unstaged:q}]of Z){let z=J?.staged.get(X)??0,V=J?.unstaged.get(X)??0,Y=z+V,U;if(Q&&q)U="partial";else if(Q)U="staged";else U="unstaged";let j=q??Q,G,B;if(Q?.insertions!==void 0||q?.insertions!==void 0)G=(Q?.insertions??0)+(q?.insertions??0);if(Q?.deletions!==void 0||q?.deletions!==void 0)B=(Q?.deletions??0)+(q?.deletions??0);K.push({path:X,status:j.status,stagingState:U,stagedHunks:z,totalHunks:Y,insertions:G,deletions:B,originalPath:j.originalPath,stagedEntry:Q,unstagedEntry:q})}return K.sort((X,Q)=>X.path.localeCompare(Q.path)),K}function w($,J){return $[J]??null}function y8($,J){return $.findIndex((Z)=>Z.path===J)}function P8($,J,Z){$.key(["q","C-c"],()=>{J.exit()}),$.key(["j","down"],()=>{if(Z.hasActiveModal())return;J.navigateDown()}),$.key(["k","up"],()=>{if(Z.hasActiveModal())return;J.navigateUp()});let K=[["1","diff"],["2","commit"],["3","history"],["4","compare"],["5","explorer"]];for(let[X,Q]of K)$.key([X],()=>{if(Z.hasActiveModal())return;Z.uiState.setTab(Q)});$.key(["tab"],()=>{if(Z.hasActiveModal())return;Z.uiState.togglePane()}),$.key(["s"],()=>{if(Z.hasActiveModal())return;if(Z.getBottomTab()==="diff"&&Z.getCurrentPane()==="diff")J.toggleCurrentHunk();else J.stageSelected()}),$.key(["S-u"],()=>{if(Z.hasActiveModal())return;J.unstageSelected()}),$.key(["S-a"],()=>{if(Z.hasActiveModal())return;J.stageAll()}),$.key(["S-z"],()=>{if(Z.hasActiveModal())return;J.unstageAll()}),$.key(["enter","space"],()=>{if(Z.hasActiveModal())return;if(Z.getBottomTab()==="explorer"&&Z.getCurrentPane()==="explorer")J.enterExplorerDirectory();else J.toggleSelected()}),$.key(["backspace"],()=>{if(Z.hasActiveModal())return;if(Z.getBottomTab()==="explorer"&&Z.getCurrentPane()==="explorer")J.goExplorerUp()}),$.key(["g"],()=>{if(Z.hasActiveModal())return;if(Z.getBottomTab()==="explorer")Z.getExplorerManager()?.toggleShowOnlyChanges()}),$.key(["/"],()=>{if(Z.hasActiveModal())return;if(Z.getBottomTab()==="explorer")J.openFileFinder()}),$.key(["C-p"],()=>{if(Z.hasActiveModal())return;J.openFileFinder()}),$.key(["c"],()=>{if(Z.hasActiveModal())return;Z.uiState.setTab("commit")}),$.key(["i"],()=>{if(Z.getBottomTab()==="commit"&&!Z.isCommitInputFocused())J.focusCommitInput()}),$.key(["a"],()=>{if(Z.getBottomTab()==="commit"&&!Z.isCommitInputFocused())Z.commitFlowState.toggleAmend(),J.render();else Z.uiState.toggleAutoTab()}),$.key(["escape"],()=>{if(Z.getBottomTab()==="commit")if(Z.isCommitInputFocused())J.unfocusCommitInput();else Z.uiState.setTab("diff")}),$.key(["r"],()=>J.refresh()),$.key(["w"],()=>Z.uiState.toggleWrapMode()),$.key(["m"],()=>J.toggleMouseMode()),$.key(["S-t"],()=>Z.uiState.toggleAutoTab()),$.key(["-","_","["],()=>{Z.uiState.adjustSplitRatio(-x$),Z.layout.setSplitRatio(Z.uiState.state.splitRatio),J.render()}),$.key(["=","+","]"],()=>{Z.uiState.adjustSplitRatio(x$),Z.layout.setSplitRatio(Z.uiState.state.splitRatio),J.render()}),$.key(["t"],()=>Z.uiState.openModal("theme")),$.key(["?"],()=>Z.uiState.toggleModal("hotkeys")),$.key(["f"],()=>J.toggleFollow()),$.key(["b"],()=>{if(Z.getBottomTab()==="compare")Z.uiState.openModal("baseBranch")}),$.key(["u"],()=>{if(Z.hasActiveModal())return;if(Z.getBottomTab()==="compare"){Z.uiState.toggleIncludeUncommitted();let X=Z.uiState.state.includeUncommitted;Z.getGitManager()?.refreshCompareDiff(X)}}),$.key(["h"],()=>{if(Z.hasActiveModal())return;let X=Z.getBottomTab();if(X==="diff"||X==="commit")Z.uiState.toggleFlatViewMode()}),$.key(["d"],()=>{if(Z.getBottomTab()==="diff")if(Z.uiState.state.flatViewMode){let X=w(Z.getCachedFlatFiles(),Z.getSelectedIndex());if(X?.unstagedEntry){let Q=X.unstagedEntry;if(Q.status!=="untracked")J.showDiscardConfirm(Q)}}else{let X=Z.getStatusFiles(),Q=b(X,Z.getSelectedIndex());if(Q&&!Q.staged&&Q.status!=="untracked")J.showDiscardConfirm(Q)}}),$.key(["n"],()=>{if(Z.hasActiveModal())return;if(Z.getBottomTab()==="diff"&&Z.getCurrentPane()==="diff")J.navigateNextHunk()}),$.key(["S-n"],()=>{if(Z.hasActiveModal())return;if(Z.getBottomTab()==="diff"&&Z.getCurrentPane()==="diff")J.navigatePrevHunk()})}function H5($){switch($){case"unstaged":return{text:"[+]",color:"green"};case"staged":return{text:"[-]",color:"red"};case"partial":return{text:"[~]",color:"yellow"}}}function E5($){if($.totalHunks===0)return"";return` {cyan-fg}@${$.stagedHunks}/${$.totalHunks}{/cyan-fg}`}function k5($,J,Z,K,X){let Q=J===Z,q=V$($.status),z=Y$($.status),V=H5($.stagingState),Y=U$($.insertions,$.deletions),U=E5($),j=Y.replace(/\{[^}]+\}/g,"").length,G=U.replace(/\{[^}]+\}/g,"").length,B=X-j-G,_=G$(Q,K);return _+=`{${V.color}-fg}${V.text}{/${V.color}-fg} `,_+=`{${z}-fg}${q}{/${z}-fg} `,_+=B$($.path,Q,K,B),_+=j$($.originalPath),_+=Y,_+=U,_}function S8($,J,Z,K,X=0,Q){if($.length===0)return"{gray-fg} No changes{/gray-fg}";let q=K-12,z=[];z.push("{bold}{gray-fg}All files (h):{/gray-fg}{/bold}");for(let Y=0;Y<$.length;Y++)z.push(k5($[Y],Y,J,Z,q));return(Q?z.slice(X,X+Q):z.slice(X)).join(`
4
+ `)}function b8($){if($.length===0)return 0;return $.length+1}function O$($){let Z=new Date().getTime()-$.getTime(),K=Math.floor(Z/3600000),X=Math.floor(Z/86400000);if(K<1)return`${Math.floor(Z/60000)}m ago`;else if(K<48)return`${K}h ago`;else if(X<=14)return`${X}d ago`;else return $.toLocaleDateString("en-US",{month:"short",day:"numeric"})}function w8($){return $.toLocaleString("en-US",{year:"numeric",month:"short",day:"numeric",hour:"2-digit",minute:"2-digit"})}function L5($,J){if($.length<=J)return $;if(J<=3)return $.slice(0,J);return $.slice(0,J-3)+"..."}function v$($,J,Z,K=20){let X=J||"",Q=Math.max(0,Z-K-1),q=X;if(q.length>Q&&Q>3)q=q.slice(0,Q-3)+"...";else if(q.length>Q)q="";let z=q?q.length+1:0,V=Math.max(K,Z-z);return{displayMessage:L5($,V),displayRefs:q}}function x8($,J,Z,K,X=0,Q){if($.length===0)return"{gray-fg}No commits yet{/gray-fg}";let q=Q?$.slice(X,X+Q):$.slice(X),z=[];for(let V=0;V<q.length;V++){let Y=q[V],G=X+V===J&&Z,B=O$(Y.date),_=11+B.length+2+2,v=Math.max(10,K-_),{displayMessage:W,displayRefs:A}=v$(Y.message,Y.refs,v),T="";if(G)T+="{cyan-fg}{bold}▸ {/bold}{/cyan-fg}";else T+=" ";if(T+=`{yellow-fg}${Y.shortHash}{/yellow-fg} `,G)T+=`{cyan-fg}{inverse}${u$(W)}{/inverse}{/cyan-fg}`;else T+=u$(W);if(T+=` {gray-fg}(${B}){/gray-fg}`,A)T+=` {green-fg}${u$(A)}{/green-fg}`;z.push(T)}return z.join(`
5
+ `)}function u$($){return $.replace(/\{/g,"{{").replace(/\}/g,"}}")}function p8($,J){return $[J]??null}function g8($){let J={name:"",fullPath:"",isDirectory:!0,children:[],depth:0};for(let Z=0;Z<$.length;Z++){let X=$[Z].path.split("/"),Q=J;for(let q=0;q<X.length;q++){let z=X[q],V=q===X.length-1,Y=X.slice(0,q+1).join("/"),U=Q.children.find((j)=>j.name===z&&j.isDirectory===!V);if(!U)U={name:z,fullPath:Y,isDirectory:!V,children:[],depth:Q.depth+1,fileIndex:V?Z:void 0},Q.children.push(U);Q=U}}return u8(J),f8(J),J}function u8($){for(let J of $.children)u8(J);for(let J=0;J<$.children.length;J++){let Z=$.children[J];while(Z.isDirectory&&Z.children.length===1&&Z.children[0].isDirectory){let K=Z.children[0];Z.name=`${Z.name}/${K.name}`,Z.fullPath=K.fullPath,Z.children=K.children,m8(Z,Z.depth)}}}function m8($,J){$.depth=J;for(let Z of $.children)m8(Z,J+1)}function f8($){$.children.sort((J,Z)=>{if(J.isDirectory&&!Z.isDirectory)return-1;if(!J.isDirectory&&Z.isDirectory)return 1;return J.name.localeCompare(Z.name)});for(let J of $.children)f8(J)}function h8($){let J=[];function Z(K,X){for(let Q=0;Q<K.children.length;Q++){let q=K.children[Q],z=Q===K.children.length-1;if(J.push({type:q.isDirectory?"directory":"file",name:q.name,fullPath:q.fullPath,depth:q.depth-1,fileIndex:q.fileIndex,isLast:z,parentIsLast:[...X]}),q.isDirectory)Z(q,[...X,z])}}return Z($,[]),J}function m$($){let J="";for(let Z=0;Z<$.depth;Z++)if($.parentIsLast[Z])J+=" ";else J+="│ ";if($.depth>=0)if($.isLast)J+="└ ";else J+="├ ";return J}var k="\x1B[0m",R5="\x1B[1m",n="\x1B[90m",c$="\x1B[36m",d8="\x1B[33m",h$="\x1B[32m",c8="\x1B[31m",l8="\x1B[34m",f$="\x1B[35m",o8="\x1B[7m";function K$($,J,Z=!0,K=!0){let X=[];if($.length>0){if(X.push({type:"section-header",sectionType:"commits"}),Z)$.forEach((Q,q)=>{X.push({type:"commit",commitIndex:q,commit:Q})})}if(J.length>0){if($.length>0)X.push({type:"spacer"});if(X.push({type:"section-header",sectionType:"files"}),K){let Q=g8(J),q=h8(Q);for(let z of q)if(z.type==="directory")X.push({type:"directory",treeRow:z});else{let V=J[z.fileIndex];X.push({type:"file",fileIndex:z.fileIndex,file:V,treeRow:z})}}}return X}function F5($,J,Z,K){let X=J&&Z,Q=O$($.date),q=13+Q.length+2,z=Math.max(10,K-q),{displayMessage:V,displayRefs:Y}=v$($.message,$.refs,z),U=` ${d8}${$.shortHash}${k} `;if(X)U+=`${c$}${o8}${V}${k}`;else U+=V;if(U+=` ${n}(${Q})${k}`,Y)U+=` ${h$}${Y}${k}`;return`{escape}${U}{/escape}`}function I5($,J){let Z=m$($),K="▸ ",X=J-Z.length-2-2,Q=$.name;if(Q.length>X)Q=Q.slice(0,X-1)+"…";return`{escape}${`${n}${Z}${k}${l8}${"▸ "}${Q}${k}`}{/escape}`}function C5($,J,Z,K,X){let Q=Z&&K,q=$.isUncommitted??!1,z=m$(J),V={added:h$,modified:d8,deleted:c8,renamed:l8},Y={added:"+",modified:"●",deleted:"−",renamed:"→"},U=q?f$:V[$.status],j=Y[$.status],G=`(+${$.additions} -${$.deletions})`,B=q?" [uncommitted]":"",_=z.length+2+G.length+B.length+2,v=Math.max(5,X-_),W=J.name;if(W.length>v)W=W.slice(0,v-1)+"…";let A=`${n}${z}${k}`;if(A+=`${U}${j}${k} `,Q)A+=`${c$}${o8}${W}${k}`;else if(q)A+=`${f$}${W}${k}`;else A+=W;if(A+=` ${n}(${h$}+${$.additions}${k} ${c8}-${$.deletions}${n})${k}`,q)A+=` ${f$}[uncommitted]${k}`;return`{escape}${A}{/escape}`}function y5($,J){if(!J)return!1;if($.type==="commit"&&$.commitIndex!==void 0)return J.type==="commit"&&J.index===$.commitIndex;if($.type==="file"&&$.fileIndex!==void 0)return J.type==="file"&&J.index===$.fileIndex;return!1}function P5($,J){return`{escape}${c$}${R5}▼ ${$}${k} ${n}(${J})${k}{/escape}`}function S5($,J,Z,K,X,Q){if($.type==="section-header"){let z=$.sectionType==="commits";return P5(z?"Commits":"Files",z?K.length:X.length)}if($.type==="spacer")return"";if($.type==="directory"&&$.treeRow)return I5($.treeRow,Q);let q=y5($,J);if($.type==="commit"&&$.commit&&$.commitIndex!==void 0)return F5($.commit,q,Z,Q);if($.type==="file"&&$.file&&$.fileIndex!==void 0&&$.treeRow)return C5($.file,$.treeRow,q,Z,Q);return null}function r8($,J,Z,K,X,Q=0,q){if($.length===0&&J.length===0)return"{gray-fg}No changes compared to base branch{/gray-fg}";let z=K$($,J);return(q?z.slice(Q,Q+q):z.slice(Q)).map((U)=>S5(U,Z,K,$,J,X)).filter((U)=>U!==null).join(`
6
+ `)}function a8($,J,Z=!0,K=!0){return K$($,J,Z,K).length}function d$($,J,Z,K=!0,X=!0){let q=K$(J,Z,K,X)[$];if(!q)return null;if(q.type==="commit"&&q.commitIndex!==void 0)return{type:"commit",index:q.commitIndex};if(q.type==="file"&&q.fileIndex!==void 0)return{type:"file",index:q.fileIndex};return null}function W$($,J,Z,K=!0,X=!0){let Q=K$(J,Z,K,X);for(let q=0;q<Q.length;q++){let z=Q[q];if($.type==="commit"&&z.type==="commit"&&z.commitIndex===$.index)return q;if($.type==="file"&&z.type==="file"&&z.fileIndex===$.index)return q}return 0}function l$($,J,Z,K){let X=K$(J,Z),Q=0;if($)Q=W$($,J,Z);let q=K==="down"?1:-1,z=Q+q;while(z>=0&&z<X.length){let V=d$(z,J,Z);if(V)return V;z+=q}return $}function b5($){let J="";for(let Z=0;Z<$.depth;Z++)if($.parentIsLast[Z])J+=" ";else J+="│ ";if($.depth>0||$.parentIsLast.length===0)if($.isLast)J+="└ ";else J+="├ ";return J}function w5($){if(!$)return"";switch($){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 x5($){if(!$)return"\x1B[0m";switch($){case"modified":return"\x1B[33m";case"added":return"\x1B[32m";case"deleted":return"\x1B[31m";case"untracked":return"\x1B[90m";case"renamed":return"\x1B[34m";case"copied":return"\x1B[35m";default:return"\x1B[0m"}}function p5($,J,Z,K){let X=J&&Z,Q=$.node,q=b5($),z="";if(Q.isDirectory)z=Q.expanded?"▾ ":"▸ ";let V=w5(Q.gitStatus),Y=x5(Q.gitStatus),U=V?`${Y}${V}\x1B[0m `:"",j=Q.isDirectory&&Q.hasChangedChildren?`${"\x1B[33m"}●${"\x1B[0m"} `:"",G=q.length+z.length+(V?2:0)+(Q.hasChangedChildren&&Q.isDirectory?2:0),B=Math.max(5,K-G-2),_=Q.isDirectory?`${Q.name}/`:Q.name;if(_.length>B)_=_.slice(0,B-1)+"…";let v=`\x1B[90m${q}\x1B[0m`;if(Q.isDirectory)if(v+=`\x1B[34m${z}\x1B[0m`,v+=j,X)v+=`\x1B[36m\x1B[1m\x1B[7m${_}\x1B[0m`;else v+=`\x1B[34m${_}\x1B[0m`;else if(v+=U,X)v+=`\x1B[36m\x1B[1m\x1B[7m${_}\x1B[0m`;else if(Q.gitStatus)v+=`${Y}${_}\x1B[0m`;else v+=_;return v}function s8($,J,Z,K,X=0,Q,q=!1,z=null){if(z)return`{red-fg}Error: ${g5(z)}{/red-fg}`;if(q)return"{gray-fg}Loading...{/gray-fg}";if($.length===0)return"{gray-fg}(empty directory){/gray-fg}";let V=Q?$.slice(X,X+Q):$.slice(X),Y=[];for(let U=0;U<V.length;U++){let j=X+U,G=p5(V[U],j===J,Z,K);Y.push(`{escape}${G}{/escape}`)}return Y.join(`
7
+ `)}function g5($){return $.replace(/\{/g,"{{").replace(/\}/g,"}}")}function n8($){return $.length}var u5={name:"dark",displayName:"Dark",colors:{addBg:"#022800",delBg:"#3D0100",addHighlight:"#044700",delHighlight:"#5C0200",text:"white",addLineNum:"#368F35",delLineNum:"#A14040",contextLineNum:"gray",addSymbol:"greenBright",delSymbol:"redBright"}},m5={name:"light",displayName:"Light",colors:{addBg:"#69db7c",delBg:"#ffa8b4",addHighlight:"#2f9d44",delHighlight:"#d1454b",text:"black",addLineNum:"#2f9d44",delLineNum:"#d1454b",contextLineNum:"#6c757d",addSymbol:"green",delSymbol:"red"}},f5={name:"dark-colorblind",displayName:"Dark (colorblind)",colors:{addBg:"#004466",delBg:"#660000",addHighlight:"#0077b3",delHighlight:"#b30000",text:"white",addLineNum:"#0077b3",delLineNum:"#b30000",contextLineNum:"gray",addSymbol:"cyanBright",delSymbol:"redBright"}},h5={name:"light-colorblind",displayName:"Light (colorblind)",colors:{addBg:"#99ccff",delBg:"#ffcccc",addHighlight:"#3366cc",delHighlight:"#993333",text:"black",addLineNum:"#3366cc",delLineNum:"#993333",contextLineNum:"#6c757d",addSymbol:"blue",delSymbol:"red"}},c5={name:"dark-ansi",displayName:"Dark (ANSI)",colors:{addBg:"green",delBg:"red",addHighlight:"greenBright",delHighlight:"redBright",text:"white",addLineNum:"greenBright",delLineNum:"redBright",contextLineNum:"gray",addSymbol:"greenBright",delSymbol:"redBright"}},d5={name:"light-ansi",displayName:"Light (ANSI)",colors:{addBg:"green",delBg:"red",addHighlight:"greenBright",delHighlight:"redBright",text:"black",addLineNum:"green",delLineNum:"red",contextLineNum:"gray",addSymbol:"green",delSymbol:"red"}},A$={dark:u5,light:m5,"dark-colorblind":f5,"light-colorblind":h5,"dark-ansi":c5,"light-ansi":d5},d=["dark","light","dark-colorblind","light-colorblind","dark-ansi","light-ansi"];function D$($){return A$[$]??A$.dark}function l5($){return!($.startsWith("index ")||$.startsWith("--- ")||$.startsWith("+++ ")||$.startsWith("similarity index"))}function i8($){if($.type!=="header")return!0;return l5($.content)}function T$($,J,Z=!0){if(J<=0)return[{text:$,isContinuation:!1}];if($.length<=J)return[{text:$,isContinuation:!1}];let K=[],X=$,Q=!0;while(X.length>0){if(X.length<=J){K.push({text:X,isContinuation:!Q});break}K.push({text:X.slice(0,J),isContinuation:!Q}),X=X.slice(J),Q=!1}if(Z)o5($,J,K);return K}function o5($,J,Z){let K=Z.map((X)=>X.text).join("");if(K!==$)throw Error(`[LineBreaking] Content was lost during breaking!
8
+ Original (${$.length} chars): "${$.slice(0,50)}${$.length>50?"...":""}"
9
+ Joined (${K.length} chars): "${K.slice(0,50)}${K.length>50?"...":""}"`);for(let X=0;X<Z.length;X++){let Q=Z[X];if(Q.text.length>J&&J>=1)throw Error(`[LineBreaking] Segment ${X} exceeds maxWidth!
10
+ Segment length: ${Q.text.length}, maxWidth: ${J}
11
+ Segment: "${Q.text.slice(0,50)}${Q.text.length>50?"...":""}"`)}if(Z.length>0&&Z[0].isContinuation)throw Error("[LineBreaking] First segment incorrectly marked as continuation!");for(let X=1;X<Z.length;X++)if(!Z[X].isContinuation)throw Error(`[LineBreaking] Segment ${X} should be marked as continuation but isn't!`)}function o$($,J){if(J<=0)return 1;if($.length<=J)return 1;return Math.ceil($.length/J)}import i from"fast-diff";function t8($,J){if(!$||!J)return!1;let Z=i($,J),K=0,X=0;for(let[q,z]of Z)if(X+=z.length,q===i.EQUAL)K+=z.length;if(X===0)return!1;return K/X>=0.5}function e8($,J){let Z=i($,J),K=[],X=[];for(let[Q,q]of Z)if(Q===i.EQUAL)K.push({text:q,type:"same"}),X.push({text:q,type:"same"});else if(Q===i.DELETE)K.push({text:q,type:"changed"});else if(Q===i.INSERT)X.push({text:q,type:"changed"});return{oldSegments:K,newSegments:X}}import{createEmphasize as r5}from"emphasize";import{common as a5}from"lowlight";var a$=r5(a5),s5={ts:"typescript",tsx:"typescript",js:"javascript",jsx:"javascript",mjs:"javascript",cjs:"javascript",html:"xml",htm:"xml",xml:"xml",svg:"xml",css:"css",scss:"scss",sass:"scss",less:"less",json:"json",yaml:"yaml",yml:"yaml",toml:"ini",sh:"bash",bash:"bash",zsh:"bash",fish:"bash",ps1:"powershell",bat:"dos",cmd:"dos",c:"c",h:"c",cpp:"cpp",hpp:"cpp",cc:"cpp",cxx:"cpp",rs:"rust",go:"go",zig:"zig",java:"java",kt:"kotlin",kts:"kotlin",scala:"scala",groovy:"groovy",gradle:"groovy",py:"python",rb:"ruby",pl:"perl",lua:"lua",php:"php",r:"r",hs:"haskell",ml:"ocaml",fs:"fsharp",fsx:"fsharp",ex:"elixir",exs:"elixir",erl:"erlang",clj:"clojure",cljs:"clojure",cs:"csharp",vb:"vbnet",md:"markdown",markdown:"markdown",rst:"plaintext",txt:"plaintext",Makefile:"makefile",Dockerfile:"dockerfile",cmake:"cmake",ini:"ini",conf:"ini",cfg:"ini",sql:"sql",vim:"vim",diff:"diff",patch:"diff"},$0={Makefile:"makefile",makefile:"makefile",GNUmakefile:"makefile",Dockerfile:"dockerfile",dockerfile:"dockerfile",Jenkinsfile:"groovy",Vagrantfile:"ruby",Gemfile:"ruby",Rakefile:"ruby",".gitignore":"plaintext",".gitattributes":"plaintext",".editorconfig":"ini",".prettierrc":"json",".eslintrc":"json","tsconfig.json":"json","package.json":"json","package-lock.json":"json","bun.lockb":"plaintext","yarn.lock":"yaml","pnpm-lock.yaml":"yaml","Cargo.toml":"ini","Cargo.lock":"ini","go.mod":"go","go.sum":"plaintext"},r$=null;function J0(){if(!r$)r$=new Set(a$.listLanguages());return r$}function N$($){if(!$)return null;let J=$.split("/").pop()??"";if($0[J]){let X=$0[J];return J0().has(X)?X:null}let Z=J.includes(".")?J.split(".").pop()?.toLowerCase():null;if(!Z)return null;let K=s5[Z];if(!K)return null;return J0().has(K)?K:null}function Z0($,J){if(!$||!J)return $;try{return a$.highlight(J,$).value}catch{return $}}function s$($,J){if(!J||$.length===0)return $;try{let Z=$.join(`
12
+ `);return a$.highlight(J,Z).value.replace(/\x1b\[0m/g,"\x1B[39m").split(`
13
+ `)}catch{return $}}function x($){let J;if($.type==="addition"||$.type==="deletion")J=$.content.slice(1);else if($.type==="context")J=$.content.startsWith(" ")?$.content.slice(1):$.content;else J=$.content;return J.replace(/[\x00-\x08\x0a-\x1f\x7f]/g,"").replace(/\t/g," ")}function K0($){switch($.type){case"header":return{type:"diff-header",content:$.content};case"hunk":return{type:"diff-hunk",content:$.content};case"addition":return{type:"diff-add",lineNum:$.newLineNum,content:x($)};case"deletion":return{type:"diff-del",lineNum:$.oldLineNum,content:x($)};case"context":return{type:"diff-context",lineNum:$.oldLineNum??$.newLineNum,content:x($)}}}function n5($){let J=$.match(/^diff --git a\/.+ b\/(.+)$/);return J?J[1]:null}function H$($){if(!$)return[];let J=$.lines.filter(i8),Z=[],K=[],X=null,Q=0;while(Q<J.length){let q=J[Q];if(q.type==="header"){let G=n5(q.content);if(G){if(X)K.push(X),Z.push({type:"spacer"});X={language:N$(G),startRowIndex:Z.length,oldContent:[],oldRowIndices:[],newContent:[],newRowIndices:[]}}Z.push(K0(q)),Q++;continue}if(q.type==="hunk"){Z.push(K0(q)),Q++;continue}if(q.type==="context"){let G=x(q),B=Z.length;if(Z.push({type:"diff-context",lineNum:q.oldLineNum??q.newLineNum,content:G}),X&&X.language)X.oldContent.push(G),X.oldRowIndices.push(B),X.newContent.push(G),X.newRowIndices.push(B);Q++;continue}let z=[];while(Q<J.length&&J[Q].type==="deletion")z.push(J[Q]),Q++;let V=[];while(Q<J.length&&J[Q].type==="addition")V.push(J[Q]),Q++;let Y=new Map,U=new Map,j=Math.min(z.length,V.length);for(let G=0;G<j;G++){let B=x(z[G]),_=x(V[G]);if(t8(B,_)){let{oldSegments:v,newSegments:W}=e8(B,_);Y.set(G,v),U.set(G,W)}}for(let G=0;G<z.length;G++){let B=z[G],_=x(B),v=Y.get(G),W=Z.length;if(Z.push({type:"diff-del",lineNum:B.oldLineNum,content:_,...v&&{wordDiffSegments:v}}),X&&X.language&&!v)X.oldContent.push(_),X.oldRowIndices.push(W)}for(let G=0;G<V.length;G++){let B=V[G],_=x(B),v=U.get(G),W=Z.length;if(Z.push({type:"diff-add",lineNum:B.newLineNum,content:_,...v&&{wordDiffSegments:v}}),X&&X.language&&!v)X.newContent.push(_),X.newRowIndices.push(W)}}if(X)K.push(X);for(let q of K){if(!q.language)continue;if(q.oldContent.length>0){let z=s$(q.oldContent,q.language);for(let V=0;V<q.oldRowIndices.length;V++){let Y=q.oldRowIndices[V],U=Z[Y],j=z[V];if(j&&j!==U.content&&(U.type==="diff-del"||U.type==="diff-context"))U.highlighted=j}}if(q.newContent.length>0){let z=s$(q.newContent,q.language);for(let V=0;V<q.newRowIndices.length;V++){let Y=q.newRowIndices[V],U=Z[Y],j=z[V];if(j&&j!==U.content&&(U.type==="diff-add"||U.type==="diff-context"))U.highlighted=j}}}return Z}function Q0($,J){let Z=[];if($){Z.push({type:"commit-header",content:`commit ${$.hash}`}),Z.push({type:"commit-header",content:`Author: ${$.author}`}),Z.push({type:"commit-header",content:`Date: ${w8($.date)}`}),Z.push({type:"spacer"});for(let K of $.message.split(`
14
+ `))Z.push({type:"commit-message",content:` ${K}`});Z.push({type:"spacer"})}return Z.push(...H$(J)),Z}function E$($){let J=0;for(let Z of $)if("lineNum"in Z&&Z.lineNum!==void 0)J=Math.max(J,Z.lineNum);return Math.max(3,String(J).length)}function k$($,J,Z){if(!Z)return $;let X=Math.max(10,J),Q=[];for(let q of $)if(q.type==="diff-add"||q.type==="diff-del"||q.type==="diff-context"){let z=q.content;if(!z||z.length<=X){Q.push(q);continue}let V=T$(z,X);for(let Y=0;Y<V.length;Y++){let U=V[Y];Q.push({...q,content:U.text,lineNum:U.isContinuation?void 0:q.lineNum,isContinuation:U.isContinuation})}}else Q.push(q);return Q}function n$($){let J=[],Z=-1;for(let K=0;K<$.length;K++){let X=$[K].type;if(X==="diff-hunk"){if(Z!==-1)J.push({startRow:Z,endRow:K});Z=K}else if(X==="diff-header"||X==="spacer"){if(Z!==-1)J.push({startRow:Z,endRow:K}),Z=-1}}if(Z!==-1)J.push({startRow:Z,endRow:$.length});return J}function i5($,J){let Z=$.match(/@@ -(\d+)(?:,\d+)? \+(\d+)/);if(!Z)return 0;return J==="staged"?parseInt(Z[2],10):parseInt(Z[1],10)}function X0($,J){if(!$||$.lines.length===0)return{fileHeaders:[],hunks:[]};let Z=[],K=[],X=null,Q=0;for(let q of $.lines)if(q.type==="header"){if(X)K.push(X),X=null;Z.push(q)}else if(q.type==="hunk"){if(X)K.push(X);X={headerLine:q,bodyLines:[],sortKey:i5(q.content,J),source:J,hunkIndex:Q++}}else if(X)X.bodyLines.push(q);if(X)K.push(X);return{fileHeaders:Z,hunks:K}}function q0($,J){let Z=X0($,"unstaged"),K=X0(J,"staged"),X=[...Z.hunks,...K.hunks];X.sort((Y,U)=>Y.sortKey-U.sortKey);let q=[...Z.fileHeaders.length>0?Z.fileHeaders:K.fileHeaders],z=[];for(let Y of X)q.push(Y.headerLine,...Y.bodyLines),z.push({source:Y.source,hunkIndex:Y.hunkIndex});return{rows:H$({raw:"",lines:q}),hunkMapping:z}}var z0=/\x1b\[[0-9;]*m/g;function L$($,J,Z="…"){if(J<=0)return Z;if(!$.includes("\x1B")&&$.length<=J)return $;if(!$.includes("\x1B")){if($.length<=J)return $;return $.slice(0,J-Z.length)+Z}let K=[],X=0;z0.lastIndex=0;let Q;while((Q=z0.exec($))!==null){if(Q.index>X)K.push({type:"text",content:$.slice(X,Q.index)});K.push({type:"ansi",content:Q[0]}),X=Q.index+Q[0].length}if(X<$.length)K.push({type:"text",content:$.slice(X)});let q="",z=0,V=J-Z.length,Y=!1,U=!1;for(let j of K)if(j.type==="ansi")q+=j.content,Y=!0;else{let G=V-z;if(G<=0){U=!0;break}if(j.content.length<=G)q+=j.content,z+=j.content.length;else{q+=j.content.slice(0,G),U=!0;break}}if(U){if(Y)q+="\x1B[0m";q+=Z}return q}var C="\x1B[0m",U0="\x1B[1m",G0="\x1B[90m",X$="\x1B[36m",B0="\x1B[32m",t5="\x1B[33m",j0="\x1B[7m";function p($,J){if(J<=0||$.length<=J)return $;if(J<=1)return"…";return $.slice(0,J-1)+"…"}function _0($,J){if($===void 0)return" ".repeat(J);return String($).padStart(J," ")}function e5($){return $.replace(/\{/g,"{{").replace(/\}/g,"}}")}function V0($){let J=parseInt($.slice(1,3),16),Z=parseInt($.slice(3,5),16),K=parseInt($.slice(5,7),16);return`\x1B[48;2;${J};${Z};${K}m`}function $9($){let J=parseInt($.slice(1,3),16),Z=parseInt($.slice(3,5),16),K=parseInt($.slice(5,7),16);return`\x1B[38;2;${J};${Z};${K}m`}function J9($,J){if($.startsWith("diff --git")){let Z=$.match(/diff --git a\/.+ b\/(.+)$/);if(Z){let K=J-6,X=p(Z[1],K);return`{escape}${U0}${X$}── ${X} ──${C}{/escape}`}}return`{escape}${G0}${p($,J)}${C}{/escape}`}function Z9($,J){let Z=$.match(/^@@ -(\d+)(?:,(\d+))? \+(\d+)(?:,(\d+))? @@(.*)$/);if(Z){let K=parseInt(Z[1],10),X=Z[2]?parseInt(Z[2],10):1,Q=parseInt(Z[3],10),q=Z[4]?parseInt(Z[4],10):1,z=Z[5].trim(),V=K+X-1,Y=Q+q-1,U=X===1?`${K}`:`${K}-${V}`,j=q===1?`${Q}`:`${Q}-${Y}`,G=`Lines ${U} → ${j}`,B=J-G.length-1,_=z&&B>3?" "+p(z,B):"";return`{escape}${X$}${G}${G0}${_}${C}{/escape}`}return`{escape}${X$}${p($,J)}${C}{/escape}`}function M0($,J,Z){let K=Z?$:p($,J);return{display:K,visibleLength:K.length}}function i$($,J,Z,K,X,Q){let q=" ".repeat(Math.max(0,K-$.length-Z));return`{escape}${X}${Q}${$}${J}${q}${C}{/escape}`}function K9($,J,Z,K,X,Q){let{display:q}=M0(J,Z,X),z=`${$}${q}`.padEnd(K," "),V=Q==="add"?"green":"red";return`{${V}-bg}{white-fg}${e5(z)}{/white-fg}{/${V}-bg}`}function X9($,J,Z){let K="";for(let X of $)K+=X.type==="changed"?`${J}${X.text}${Z}`:X.text;return K}function Y0($,J,Z,K,X,Q,q){let z=q==="add"?"+":"-",V=$.isContinuation?"»":z,U=`${_0($.lineNum,J)} ${V} `,j=$.content||"";if(X.name.includes("ansi"))return K9(U,j,Z,K,Q,q);let{colors:G}=X,B=V0(q==="add"?G.addBg:G.delBg),_=$9("#ffffff"),{display:v,visibleLength:W}=M0(j,Z,Q),A=!$.isContinuation&&(Q||j.length<=Z);if($.wordDiffSegments&&A){let T=V0(q==="add"?G.addHighlight:G.delHighlight),H=X9($.wordDiffSegments,T,B);return i$(U,H,j.length,K,B,_)}if($.highlighted&&A)return i$(U,$.highlighted,j.length,K,B,_);return i$(U,v,W,K,B,_)}function t$($,J,Z,K,X,Q){switch($.type){case"diff-header":return J9($.content,K);case"diff-hunk":return Z9($.content,K);case"diff-add":return Y0($,J,Z,K,X,Q,"add");case"diff-del":return Y0($,J,Z,K,X,Q,"del");case"diff-context":{let q=$.isContinuation,z=q?"»":" ",Y=`${_0($.lineNum,J)} ${z} `,U=$.content||"",j=`\x1B[90m${Y}\x1B[0m`;if($.highlighted&&!q){let B=Q?$.highlighted:L$($.highlighted,Z);return`{escape}${j}${B}${C}{/escape}`}let G=Q?U:p(U,Z);return`{escape}${j}${G}${C}{/escape}`}case"commit-header":return`{escape}${t5}${p($.content,K)}${C}{/escape}`;case"commit-message":return`{escape}${p($.content,K)}${C}{/escape}`;case"spacer":return""}}function e$($,J,Z=0,K,X="dark",Q=!1,q,z){let V=q!==void 0&&q>=0,Y=H$($);if(Y.length===0)return{content:"{gray-fg}No diff to display{/gray-fg}",totalRows:0,hunkCount:0,hunkBoundaries:[]};let U=D$(X),j=E$(Y),G=V?1:0,B=J-j-5-G,_=J-2,v=k$(Y,B,Q),W=v.length,A=n$(v),T=A.length,H=Math.min(q??0,T-1),M=V&&T>0?A[H]:null,O=Z;return{content:(K?v.slice(O,O+K):v.slice(O)).map((N,E)=>{let h=O+E,y=t$(N,j,B,_,U,Q);if(!V)return y;let c=M&&h>=M.startRow&&h<M.endRow,$$=c?`{escape}${z?B0:X$}▌${C}{/escape}`:" ";if(c&&N.type==="diff-hunk")return $$+y.replace("{escape}",`{escape}${j0}`);return $$+y}).join(`
15
+ `),totalRows:W,hunkCount:T,hunkBoundaries:A}}function O0($,J,Z,K=0,X,Q="dark",q=!1){let z=Q0($,J);if(z.length===0)return{content:"{gray-fg}No commit selected{/gray-fg}",totalRows:0,hunkCount:0,hunkBoundaries:[]};let V=D$(Q),Y=E$(z),U=Z-Y-5,j=Z-2,G=k$(z,U,q),B=G.length;return{content:(X?G.slice(K,K+X):G.slice(K)).map((W)=>t$(W,Y,U,j,V,q)).join(`
16
+ `),totalRows:B,hunkCount:0,hunkBoundaries:[]}}function v0($,J,Z,K=0,X,Q="dark",q=!1,z){let{rows:V,hunkMapping:Y}=q0($,J);if(V.length===0)return{content:"{gray-fg}No diff to display{/gray-fg}",totalRows:0,hunkCount:0,hunkBoundaries:[],hunkMapping:[]};let U=z!==void 0&&z>=0,j=D$(Q),G=E$(V),B=U?1:0,_=Z-G-5-B,v=Z-2,W=k$(V,_,q),A=W.length,T=n$(W),H=T.length,M=Math.min(z??0,H-1),O=new Map;if(U)for(let E=0;E<T.length;E++){let h=T[E];for(let y=h.startRow;y<h.endRow;y++)O.set(y,E)}let D=K;return{content:(X?W.slice(D,D+X):W.slice(D)).map((E,h)=>{let y=D+h,c=t$(E,G,_,v,j,q);if(!U)return c;let z$=O.get(y);if(z$===void 0)return" "+c;let $$=z$===M,W5=Y[z$]?.source==="staged"?B0:X$,k8=`{escape}${$$?U0:""}${W5}▌${C}{/escape}`;if($$&&E.type==="diff-hunk")return k8+c.replace("{escape}",`{escape}${j0}`);return k8+c}).join(`
17
+ `),totalRows:A,hunkCount:H,hunkBoundaries:T,hunkMapping:Y}}function W0($,J,Z){let K=[],X="{bold}Commit Message{/bold}";if($.amend)X+=" {yellow-fg}(amending){/yellow-fg}";K.push(X),K.push("");let Q="│",q=$.inputFocused?"cyan":"gray",z=Math.max(20,Z-6);K.push(`{${q}-fg}┌${"─".repeat(z+2)}┐{/${q}-fg}`);let V=$.message||($.inputFocused?"":"Press i or Enter to edit..."),Y=$.message?"":"{gray-fg}",U=$.message?"":"{/gray-fg}",j=V.length>z?V.slice(0,z-1)+"…":V.padEnd(z);K.push(`{${q}-fg}${Q}{/${q}-fg} ${Y}${j}${U} {${q}-fg}${Q}{/${q}-fg}`),K.push(`{${q}-fg}└${"─".repeat(z+2)}┘{/${q}-fg}`),K.push("");let G=$.amend?"[x]":"[ ]",B=$.amend?"green":"gray";if(K.push(`{${B}-fg}${G}{/${B}-fg} Amend {gray-fg}(a){/gray-fg}`),$.error)K.push(""),K.push(`{red-fg}${$.error}{/red-fg}`);if($.isCommitting)K.push(""),K.push("{yellow-fg}Committing...{/yellow-fg}");K.push("");let _=$.inputFocused?"Enter: commit | Esc: unfocus":"i/Enter: edit | Esc: cancel | a: toggle amend";return K.push(`{gray-fg}Staged: ${J} file(s) | ${_}{/gray-fg}`),K.join(`
18
+ `)}function $8($,J,Z){if(!$)return[];let K=$.split(`
19
+ `),X=[],Q=J?N$(J):null;for(let q=0;q<K.length;q++){let z=K[q],V=Q?Z0(z,Q):void 0;X.push({type:"code",lineNum:q+1,content:z,highlighted:V})}if(Z)X.push({type:"truncation",content:"(file truncated)"});return X}function A0($,J,Z){if(!Z)return $;let X=Math.max(10,J),Q=[];for(let q of $)if(q.type==="code"){let z=q.content;if(!z||z.length<=X){Q.push(q);continue}let V=T$(z,X);for(let Y=0;Y<V.length;Y++){let U=V[Y];Q.push({type:"code",lineNum:U.isContinuation?0:q.lineNum,content:U.text,highlighted:void 0,isContinuation:U.isContinuation})}}else Q.push(q);return Q}function D0($,J,Z){if(!Z)return $.length;let X=Math.max(10,J),Q=0;for(let q of $)if(q.type==="code"){let z=q.content;if(!z||z.length<=X)Q+=1;else Q+=o$(z,X)}else Q+=1;return Q}function J8($){let J=0;for(let Z of $)if(Z.type==="code"&&Z.lineNum>J)J=Z.lineNum;return Math.max(3,String(J).length)}var T0="\x1B[0m",Q9="\x1B[90m",q9="\x1B[36m",z9="\x1B[33m";function N0($,J,Z,K=0,X,Q=!1,q=!1){if(!$)return"{gray-fg}Select a file to view its contents{/gray-fg}";if(!J)return"{gray-fg}Loading...{/gray-fg}";let z=$8(J,$,Q);if(z.length===0)return"{gray-fg}(empty file){/gray-fg}";let V=J8(z),Y=Z-V-2,U=A0(z,Y,q),j=X?U.slice(K,K+X):U.slice(K),G=[];for(let B of j){if(B.type==="truncation"){G.push(`{escape}${z9}${B.content}${T0}{/escape}`);continue}let _=B.isContinuation??!1,v;if(_)v=">>".padStart(V," ");else v=String(B.lineNum).padStart(V," ");let W=B.content,A=!q&&W.length>Y,T=B.highlighted&&!_,H;if(T&&B.highlighted)H=A?L$(B.highlighted,Y):B.highlighted;else{let D=W;if(A)D=D.slice(0,Math.max(0,Y-1))+"...";H=D}let O=`{escape}${_?q9:Q9}${v}${T0} ${H||" "}{/escape}`;G.push(O)}return G.join(`
20
+ `)}function H0($,J,Z,K,X){if(!$)return 0;let Q=$8($,J,Z),q=J8(Q),z=K-q-2;return D0(Q,z,X)}function E0($,J,Z,K,X,Q,q,z,V,Y){if($.bottomTab==="history")return x8(Z,$.historySelectedIndex,$.currentPane==="history",q,$.historyScrollOffset,z);if($.bottomTab==="compare"){let U=K?.commits??[],j=K?.files??[];return r8(U,j,X,$.currentPane==="compare",q,$.compareScrollOffset,z)}if($.bottomTab==="explorer"){let U=Q?.displayRows??[];return s8(U,$.explorerSelectedIndex,$.currentPane==="explorer",q,$.explorerScrollOffset,z,Q?.isLoading??!1,Q?.error??null)}if($.flatViewMode&&Y)return S8(Y,$.selectedIndex,$.currentPane==="files",q,$.fileListScrollOffset,z);return R8(J,$.selectedIndex,$.currentPane==="files",q,$.fileListScrollOffset,z,V)}function k0($,J,Z,K,X,Q,q,z,V,Y,U,j,G){if($.bottomTab==="commit")return{content:W0(Q,q,V),totalRows:0,hunkCount:0,hunkBoundaries:[]};if($.bottomTab==="history"){let A=Z?.selectedCommit??null,T=Z?.commitDiff??null,{content:H,totalRows:M}=O0(A,T,V,$.diffScrollOffset,Y,z,$.wrapMode);return{content:H,totalRows:M,hunkCount:0,hunkBoundaries:[]}}if($.bottomTab==="compare"){let A=K?.diff??null;if(A){let{content:T,totalRows:H}=e$(A,V,$.diffScrollOffset,Y,z,$.wrapMode);return{content:T,totalRows:H,hunkCount:0,hunkBoundaries:[]}}return{content:"{gray-fg}Select a commit or file to view diff{/gray-fg}",totalRows:0,hunkCount:0,hunkBoundaries:[]}}if($.bottomTab==="explorer")return{content:N0(X?.path??null,X?.content??null,V,$.explorerFileScrollOffset,Y,X?.truncated??!1,$.wrapMode),totalRows:0,hunkCount:0,hunkBoundaries:[]};if($.flatViewMode&&G){let A=v0(G.unstaged,G.staged,V,$.diffScrollOffset,Y,z,$.wrapMode,U);return{content:A.content,totalRows:A.totalRows,hunkCount:A.hunkCount,hunkBoundaries:A.hunkBoundaries,hunkMapping:A.hunkMapping}}let{content:B,totalRows:_,hunkCount:v,hunkBoundaries:W}=e$(J,V,$.diffScrollOffset,Y,z,$.wrapMode,U,j);return{content:B,totalRows:_,hunkCount:v,hunkBoundaries:W}}var R$=3;function F0($,J,Z){$.topPane.on("wheeldown",()=>{L0(R$,$,Z)}),$.topPane.on("wheelup",()=>{L0(-R$,$,Z)}),$.bottomPane.on("wheeldown",()=>{R0(R$,$,Z)}),$.bottomPane.on("wheelup",()=>{R0(-R$,$,Z)}),$.topPane.on("click",(K)=>{let X=$.screenYToTopPaneRow(K.y);if(X>=0)Y9(X,K.x,J,Z)}),$.bottomPane.on("click",(K)=>{let X=$.screenYToBottomPaneRow(K.y);if(X>=0)J.selectHunkAtRow(X)}),$.footerBox.on("click",(K)=>{U9(K.x,J,Z)})}function V9($,J,Z,K){let X=K.uiState.state;if(X.flatViewMode){let q=$+X.fileListScrollOffset-1,z=K.getCachedFlatFiles();if(q<0||q>=z.length)return;if(J!==void 0&&J>=2&&J<=4)Z.toggleFileByIndex(q);else K.uiState.setSelectedIndex(q),Z.selectFileByIndex(q)}else{let Q=K.getStatusFiles(),q=I8($+X.fileListScrollOffset,Q);if(q===null||q<0)return;if(J!==void 0&&J>=2&&J<=4)Z.toggleFileByIndex(q);else K.uiState.setSelectedIndex(q),Z.selectFileByIndex(q)}}function Y9($,J,Z,K){let X=K.uiState.state;if(X.bottomTab==="history"){let Q=X.historyScrollOffset+$;K.uiState.setHistorySelectedIndex(Q),Z.selectHistoryCommitByIndex(Q)}else if(X.bottomTab==="compare"){let Q=K.getCompareCommits(),q=K.getCompareFiles(),z=d$(X.compareScrollOffset+$,Q,q);if(z)Z.selectCompareItem(z)}else if(X.bottomTab==="explorer"){let Q=X.explorerScrollOffset+$,q=K.getExplorerManager(),z=q?.state.selectedIndex===Q,V=q?.state.displayRows[Q];if(z&&V?.node.isDirectory)Z.enterExplorerDirectory();else q?.selectIndex(Q),K.uiState.setExplorerSelectedIndex(Q)}else V9($,J,Z,K)}function U9($,J,Z){let K=Z.getScreenWidth(),X=[{tab:"explorer",width:11},{tab:"compare",width:10},{tab:"history",width:10},{tab:"commit",width:9},{tab:"diff",width:7}],Q=K;for(let{tab:q,width:z}of X){let V=Q-z-1;if($>=V&&$<Q){Z.uiState.setTab(q);return}Q=V}if($>=2&&$<=9)J.toggleMouseMode();else if($>=11&&$<=16)Z.uiState.toggleAutoTab();else if($>=18&&$<=23)Z.uiState.toggleWrapMode();else if($>=25&&$<=32)J.toggleFollow();else if($>=34&&$<=43&&Z.uiState.state.bottomTab==="explorer")Z.getExplorerManager()?.toggleShowOnlyChanges();else if($===0)Z.uiState.openModal("hotkeys")}function L0($,J,Z){let K=Z.uiState.state,X=J.dimensions.topPaneHeight;if(K.bottomTab==="history"){let Q=Z.getHistoryCommitCount(),q=Math.max(0,Q-X),z=Math.min(q,Math.max(0,K.historyScrollOffset+$));Z.uiState.setHistoryScrollOffset(z)}else if(K.bottomTab==="compare"){let Q=a8(Z.getCompareCommits(),Z.getCompareFiles()),q=Math.max(0,Q-X),z=Math.min(q,Math.max(0,K.compareScrollOffset+$));Z.uiState.setCompareScrollOffset(z)}else if(K.bottomTab==="explorer"){let Q=n8(Z.getExplorerManager()?.state.displayRows??[]),q=Math.max(0,Q-X),z=Math.min(q,Math.max(0,K.explorerScrollOffset+$));Z.uiState.setExplorerScrollOffset(z)}else{let Q=K.flatViewMode?b8(Z.getCachedFlatFiles()):F8(Z.getStatusFiles()),q=Math.max(0,Q-X),z=Math.min(q,Math.max(0,K.fileListScrollOffset+$));Z.uiState.setFileListScrollOffset(z)}}function R0($,J,Z){let K=Z.uiState.state,X=J.dimensions.bottomPaneHeight,Q=Z.getScreenWidth();if(K.bottomTab==="explorer"){let q=Z.getExplorerManager()?.state.selectedFile,z=H0(q?.content??null,q?.path??null,q?.truncated??!1,Q,K.wrapMode),V=Math.max(0,z-X),Y=Math.min(V,Math.max(0,K.explorerFileScrollOffset+$));Z.uiState.setExplorerFileScrollOffset(Y)}else{let q=Math.max(0,Z.getBottomPaneTotalRows()-X),z=Math.min(q,Math.max(0,K.diffScrollOffset+$));Z.uiState.setDiffScrollOffset(z)}}import*as l from"node:fs";import*as I$ from"node:path";import{watch as _9}from"chokidar";import{EventEmitter as M9}from"node:events";import*as F from"node:fs";import*as e from"node:path";import*as F$ from"node:os";var G9={targetFile:e.join(F$.homedir(),".cache","diffstalker","target"),watcherEnabled:!1,debug:!1,theme:"dark"},t=e.join(F$.homedir(),".config","diffstalker","config.json"),B9=["dark","light","dark-colorblind","light-colorblind","dark-ansi","light-ansi"];function j9($){return typeof $==="string"&&B9.includes($)}function I0(){let $={...G9};if(process.env.DIFFSTALKER_PAGER)$.pager=process.env.DIFFSTALKER_PAGER;if(F.existsSync(t))try{let J=JSON.parse(F.readFileSync(t,"utf-8"));if(J.pager)$.pager=J.pager;if(J.targetFile)$.targetFile=J.targetFile;if(j9(J.theme))$.theme=J.theme;if(typeof J.splitRatio==="number"&&J.splitRatio>=0.15&&J.splitRatio<=0.85)$.splitRatio=J.splitRatio}catch{}return $}function Z8($){let J=e.dirname(t);if(!F.existsSync(J))F.mkdirSync(J,{recursive:!0});let Z={};if(F.existsSync(t))try{Z=JSON.parse(F.readFileSync(t,"utf-8"))}catch{}Object.assign(Z,$),F.writeFileSync(t,JSON.stringify(Z,null,2)+`
21
+ `)}function C0($){let J=e.dirname($);if(!F.existsSync(J))F.mkdirSync(J,{recursive:!0})}function y0($){let J=F$.homedir();if($.startsWith(J))return"~"+$.slice(J.length);return $}import*as P0 from"node:path";import*as K8 from"node:os";function S0($){if($.startsWith("~/"))return P0.join(K8.homedir(),$.slice(2));if($==="~")return K8.homedir();return $}function X8($){let J=$.split(`
22
+ `);for(let Z=J.length-1;Z>=0;Z--){let K=J[Z].trim();if(K)return K}return""}class Q8 extends M9{targetFile;debug;watcher=null;debounceTimer=null;lastReadPath=null;_state={path:null,lastUpdate:null,rawContent:null,sourceFile:null};constructor($,J=!1){super();this.targetFile=$,this.debug=J,this._state.sourceFile=$}get state(){return this._state}updateState($){this._state={...this._state,...$},this.emit("path-change",this._state)}processContent($){if(!$)return null;let J=S0($);return I$.isAbsolute(J)?J:I$.resolve(J)}readTargetDebounced(){if(this.debounceTimer)clearTimeout(this.debounceTimer);this.debounceTimer=setTimeout(()=>{this.readTarget()},100)}readTarget(){try{let $=l.readFileSync(this.targetFile,"utf-8"),J=X8($);if(J&&J!==this.lastReadPath){let Z=this.processContent(J),K=new Date;if(this.debug&&Z)process.stderr.write(`[diffstalker ${K.toISOString()}] Path change detected
46
23
  `),process.stderr.write(` Source file: ${this.targetFile}
47
- `),process.stderr.write(` Raw content: "${$}"
24
+ `),process.stderr.write(` Raw content: "${J}"
48
25
  `),process.stderr.write(` Previous: "${this.lastReadPath??"(none)"}"
49
- `),process.stderr.write(` Resolved: "${J}"
50
- `);this.lastReadPath=J,this.updateState({path:J,lastUpdate:X,rawContent:$})}}catch{}}start(){if(J7(this.targetFile),!m.existsSync(this.targetFile))m.writeFileSync(this.targetFile,"");try{let K=m.readFileSync(this.targetFile,"utf-8"),$=iK(K);if($){let J=this.processContent($),X=new Date;if(this.debug&&J)process.stderr.write(`[diffstalker ${X.toISOString()}] Initial path read
26
+ `),process.stderr.write(` Resolved: "${Z}"
27
+ `);this.lastReadPath=Z,this.updateState({path:Z,lastUpdate:K,rawContent:J})}}catch{}}start(){if(C0(this.targetFile),!l.existsSync(this.targetFile))l.writeFileSync(this.targetFile,"");try{let $=l.readFileSync(this.targetFile,"utf-8"),J=X8($);if(J){let Z=this.processContent(J),K=new Date;if(this.debug&&Z)process.stderr.write(`[diffstalker ${K.toISOString()}] Initial path read
51
28
  `),process.stderr.write(` Source file: ${this.targetFile}
52
- `),process.stderr.write(` Raw content: "${$}"
53
- `),process.stderr.write(` Resolved: "${J}"
54
- `);this.lastReadPath=J,this._state={path:J,lastUpdate:X,rawContent:$,sourceFile:this.targetFile}}}catch{}this.watcher=Z9(this.targetFile,{persistent:!0,ignoreInitial:!0}),this.watcher.on("change",()=>this.readTargetDebounced()),this.watcher.on("add",()=>this.readTargetDebounced())}stop(){if(this.debounceTimer)clearTimeout(this.debounceTimer),this.debounceTimer=null;if(this.watcher)this.watcher.close(),this.watcher=null}}class eK{screen;layout;uiState;gitManager=null;fileWatcher=null;explorerManager=null;config;commandServer;repoPath;watcherState={enabled:!1};currentTheme;commitFlowState;commitTextarea=null;activeModal=null;bottomPaneTotalRows=0;constructor(K){this.config=K.config,this.commandServer=K.commandServer??null,this.repoPath=K.initialPath??process.cwd(),this.currentTheme=K.config.theme,this.uiState=new hK({splitRatio:K.config.splitRatio??0.4}),this.screen=G8.screen({smartCSR:!0,fullUnicode:!0,title:"diffstalker",mouse:!0,terminal:"xterm-256color"});let $=this.screen;if($.tput)$.tput.colors=256;if($.program?.tput)$.program.tput.colors=256;if(this.layout=new OK(this.screen,this.uiState.state.splitRatio),this.screen.on("resize",()=>{setImmediate(()=>this.render())}),this.commitFlowState=new fK({getHeadMessage:()=>this.gitManager?.getHeadCommitMessage()??Promise.resolve(""),onCommit:async(J,X)=>{await this.gitManager?.commit(J,X)},onSuccess:()=>{this.uiState.setTab("diff"),this.render()}}),this.commitTextarea=G8.textarea({parent:this.layout.bottomPane,top:3,left:1,width:"100%-4",height:1,inputOnFocus:!0,hidden:!0,style:{fg:"white",bg:"default"}}),this.commitTextarea.on("submit",()=>{this.commitFlowState.submit()}),this.commitTextarea.on("keypress",()=>{setImmediate(()=>{let J=this.commitTextarea?.getValue()??"";this.commitFlowState.setMessage(J)})}),this.setupKeyboardHandlers(),this.setupMouseHandlers(),this.setupStateListeners(),this.config.watcherEnabled)this.setupFileWatcher();if(this.commandServer)this.setupCommandHandler();this.initGitManager(),this.render()}setupKeyboardHandlers(){this.screen.key(["q","C-c"],()=>{this.exit()}),this.screen.key(["j","down"],()=>{if(this.activeModal)return;this.navigateDown()}),this.screen.key(["k","up"],()=>{if(this.activeModal)return;this.navigateUp()}),this.screen.key(["1"],()=>{if(this.activeModal)return;this.uiState.setTab("diff")}),this.screen.key(["2"],()=>{if(this.activeModal)return;this.uiState.setTab("commit")}),this.screen.key(["3"],()=>{if(this.activeModal)return;this.uiState.setTab("history")}),this.screen.key(["4"],()=>{if(this.activeModal)return;this.uiState.setTab("compare")}),this.screen.key(["5"],()=>{if(this.activeModal)return;this.uiState.setTab("explorer")}),this.screen.key(["tab"],()=>{if(this.activeModal)return;this.uiState.togglePane()}),this.screen.key(["s"],()=>{if(this.activeModal)return;this.stageSelected()}),this.screen.key(["S-u"],()=>{if(this.activeModal)return;this.unstageSelected()}),this.screen.key(["S-a"],()=>{if(this.activeModal)return;this.stageAll()}),this.screen.key(["S-z"],()=>{if(this.activeModal)return;this.unstageAll()}),this.screen.key(["enter","space"],()=>{if(this.activeModal)return;let K=this.uiState.state;if(K.bottomTab==="explorer"&&K.currentPane==="explorer")this.enterExplorerDirectory();else this.toggleSelected()}),this.screen.key(["backspace"],()=>{if(this.activeModal)return;let K=this.uiState.state;if(K.bottomTab==="explorer"&&K.currentPane==="explorer")this.goExplorerUp()}),this.screen.key(["c"],()=>{if(this.activeModal)return;this.uiState.setTab("commit")}),this.screen.key(["i"],()=>{if(this.uiState.state.bottomTab==="commit"&&!this.commitFlowState.state.inputFocused)this.focusCommitInput()}),this.screen.key(["a"],()=>{if(this.uiState.state.bottomTab==="commit"&&!this.commitFlowState.state.inputFocused)this.commitFlowState.toggleAmend(),this.render()}),this.screen.key(["escape"],()=>{if(this.uiState.state.bottomTab==="commit")if(this.commitFlowState.state.inputFocused)this.unfocusCommitInput();else this.uiState.setTab("diff")}),this.screen.key(["r"],()=>this.refresh()),this.screen.key(["w"],()=>this.uiState.toggleWrapMode()),this.screen.key(["m"],()=>this.toggleMouseMode()),this.screen.key(["S-t"],()=>this.uiState.toggleAutoTab()),this.screen.key(["-","_"],()=>{this.uiState.adjustSplitRatio(-MK),this.layout.setSplitRatio(this.uiState.state.splitRatio),this.render()}),this.screen.key(["=","+"],()=>{this.uiState.adjustSplitRatio(MK),this.layout.setSplitRatio(this.uiState.state.splitRatio),this.render()}),this.screen.key(["t"],()=>this.uiState.openModal("theme")),this.screen.key(["?"],()=>this.uiState.toggleModal("hotkeys")),this.screen.key(["f"],()=>this.toggleFollow()),this.screen.key(["b"],()=>{if(this.uiState.state.bottomTab==="compare")this.uiState.openModal("baseBranch")}),this.screen.key(["u"],()=>{if(this.uiState.state.bottomTab==="compare"){this.uiState.toggleIncludeUncommitted();let K=this.uiState.state.includeUncommitted;this.gitManager?.refreshCompareDiff(K)}}),this.screen.key(["d"],()=>{if(this.uiState.state.bottomTab==="diff"){let K=this.gitManager?.state.status?.files??[],$=this.uiState.state.selectedIndex,J=K[$];if(J&&!J.staged&&J.status!=="untracked")this.showDiscardConfirm(J)}})}setupMouseHandlers(){this.layout.topPane.on("wheeldown",()=>{this.handleTopPaneScroll(3)}),this.layout.topPane.on("wheelup",()=>{this.handleTopPaneScroll(-3)}),this.layout.bottomPane.on("wheeldown",()=>{this.handleBottomPaneScroll(3)}),this.layout.bottomPane.on("wheelup",()=>{this.handleBottomPaneScroll(-3)}),this.layout.topPane.on("click",($)=>{let J=this.layout.screenYToTopPaneRow($.y);if(J>=0)this.handleTopPaneClick(J)}),this.layout.footerBox.on("click",($)=>{this.handleFooterClick($.x)})}handleTopPaneClick(K){let $=this.uiState.state;if($.bottomTab==="history"){let J=$.historyScrollOffset+K;this.uiState.setHistorySelectedIndex(J),this.selectHistoryCommitByIndex(J)}else if($.bottomTab==="compare"){let J=this.gitManager?.compareState,X=J?.compareDiff?.commits??[],Z=J?.compareDiff?.files??[],Q=PK($.compareScrollOffset+K,X,Z);if(Q)this.selectCompareItem(Q)}else if($.bottomTab==="explorer"){let J=$.explorerScrollOffset+K;this.explorerManager?.selectIndex(J),this.uiState.setExplorerSelectedIndex(J)}else{let J=this.gitManager?.state.status?.files??[],X=V7(K+$.fileListScrollOffset,J);if(X!==null&&X>=0)this.uiState.setSelectedIndex(X),this.selectFileByIndex(X)}}handleFooterClick(K){let $=this.screen.width||80,J=[{tab:"explorer",label:"[5]Explorer",width:11},{tab:"compare",label:"[4]Compare",width:10},{tab:"history",label:"[3]History",width:10},{tab:"commit",label:"[2]Commit",width:9},{tab:"diff",label:"[1]Diff",width:7}],X=$;for(let{tab:Z,width:Q}of J){let q=X-Q-1;if(K>=q&&K<X){this.uiState.setTab(Z);return}X=q}if(K>=2&&K<=9)this.toggleMouseMode();else if(K>=11&&K<=16)this.uiState.toggleAutoTab();else if(K>=18&&K<=23)this.uiState.toggleWrapMode();else if(K>=25&&K<=30&&this.uiState.state.bottomTab==="explorer")this.uiState.toggleMiddleDots();else if(K===0)this.uiState.openModal("hotkeys")}handleTopPaneScroll(K){let $=this.uiState.state,J=this.layout.dimensions.topPaneHeight;if($.bottomTab==="history"){let X=this.gitManager?.historyState.commits.length??0,Z=Math.max(0,X-J),Q=Math.min(Z,Math.max(0,$.historyScrollOffset+K));this.uiState.setHistoryScrollOffset(Q)}else if($.bottomTab==="compare"){let X=this.gitManager?.compareState,Z=L7(X?.compareDiff?.commits??[],X?.compareDiff?.files??[]),Q=Math.max(0,Z-J),q=Math.min(Q,Math.max(0,$.compareScrollOffset+K));this.uiState.setCompareScrollOffset(q)}else if($.bottomTab==="explorer"){let X=y7(this.explorerManager?.state.items??[]),Z=Math.max(0,X-J),Q=Math.min(Z,Math.max(0,$.explorerScrollOffset+K));this.uiState.setExplorerScrollOffset(Q)}else{let X=this.gitManager?.state.status?.files??[],Z=Y7(X),Q=Math.max(0,Z-J),q=Math.min(Q,Math.max(0,$.fileListScrollOffset+K));this.uiState.setFileListScrollOffset(q)}}handleBottomPaneScroll(K){let $=this.uiState.state,J=this.layout.dimensions.bottomPaneHeight,X=this.screen.width||80;if($.bottomTab==="explorer"){let Z=this.explorerManager?.state.selectedFile,Q=w7(Z?.content??null,Z?.path??null,Z?.truncated??!1,X,$.wrapMode),q=Math.max(0,Q-J),Y=Math.min(q,Math.max(0,$.explorerFileScrollOffset+K));this.uiState.setExplorerFileScrollOffset(Y)}else{let Z=Math.max(0,this.bottomPaneTotalRows-J),Q=Math.min(Z,Math.max(0,$.diffScrollOffset+K));this.uiState.setDiffScrollOffset(Q)}}setupStateListeners(){this.uiState.on("change",()=>{this.render()}),this.uiState.on("tab-change",($)=>{if($==="history")this.gitManager?.loadHistory();else if($==="compare")this.gitManager?.refreshCompareDiff(this.uiState.state.includeUncommitted);else if($==="explorer"){if(!this.explorerManager?.state.items.length)this.explorerManager?.loadDirectory("")}}),this.uiState.on("modal-change",($)=>{if(this.activeModal)this.activeModal=null;if($==="theme")this.activeModal=new uK(this.screen,this.currentTheme,(J)=>{this.currentTheme=J,NK({theme:J}),this.activeModal=null,this.uiState.closeModal(),this.render()},()=>{this.activeModal=null,this.uiState.closeModal()}),this.activeModal.focus();else if($==="hotkeys")this.activeModal=new pK(this.screen,()=>{this.activeModal=null,this.uiState.closeModal()}),this.activeModal.focus();else if($==="baseBranch")this.gitManager?.getCandidateBaseBranches().then((J)=>{let X=this.gitManager?.compareState.compareBaseBranch??null;this.activeModal=new gK(this.screen,J,X,(Z)=>{this.activeModal=null,this.uiState.closeModal();let Q=this.uiState.state.includeUncommitted;this.gitManager?.setCompareBaseBranch(Z,Q)},()=>{this.activeModal=null,this.uiState.closeModal()}),this.activeModal.focus()})});let K=null;this.uiState.on("change",($)=>{if(K)clearTimeout(K);K=setTimeout(()=>{if($.splitRatio!==this.config.splitRatio)NK({splitRatio:$.splitRatio})},500)})}setupFileWatcher(){this.fileWatcher=new tK(this.config.targetFile),this.fileWatcher.on("path-change",($)=>{if($.path&&$.path!==this.repoPath)this.repoPath=$.path,this.watcherState={enabled:!0,sourceFile:$.sourceFile??this.config.targetFile,rawContent:$.rawContent??void 0,lastUpdate:$.lastUpdate??void 0},this.initGitManager(),this.render();if($.rawContent)this.navigateToFile($.rawContent),this.render()}),this.watcherState={enabled:!0,sourceFile:this.config.targetFile},this.fileWatcher.start();let K=this.fileWatcher.state;if(K.rawContent)this.watcherState.rawContent=K.rawContent,this.navigateToFile(K.rawContent)}initGitManager(){if(this.gitManager)this.gitManager.removeAllListeners(),aK(this.repoPath);this.gitManager=U8(this.repoPath),this.gitManager.on("state-change",()=>{this.render()}),this.gitManager.on("history-state-change",(K)=>{if(K.commits.length>0&&!K.selectedCommit){let $=this.uiState.state;if($.bottomTab==="history")this.selectHistoryCommitByIndex($.historySelectedIndex)}this.render()}),this.gitManager.on("compare-state-change",()=>{this.render()}),this.gitManager.on("compare-selection-change",()=>{this.render()}),this.gitManager.startWatching(),this.gitManager.refresh(),this.initExplorerManager()}initExplorerManager(){if(this.explorerManager)this.explorerManager.dispose();let K={hideHidden:!0,hideGitignored:!0};this.explorerManager=new wK(this.repoPath,K),this.explorerManager.on("state-change",()=>{this.render()}),this.explorerManager.loadDirectory("")}setupCommandHandler(){if(!this.commandServer)return;let K={navigateUp:()=>this.navigateUp(),navigateDown:()=>this.navigateDown(),switchTab:($)=>this.uiState.setTab($),togglePane:()=>this.uiState.togglePane(),stage:async()=>this.stageSelected(),unstage:async()=>this.unstageSelected(),stageAll:async()=>this.stageAll(),unstageAll:async()=>this.unstageAll(),commit:async($)=>this.commit($),refresh:async()=>this.refresh(),getState:()=>this.getAppState(),quit:()=>this.exit()};this.commandServer.setHandler(K),this.commandServer.notifyReady()}getAppState(){let K=this.uiState.state,$=this.gitManager?.state,J=this.gitManager?.historyState,X=$?.status?.files??[],Z=J?.commits??[];return{currentTab:K.bottomTab,currentPane:K.currentPane,selectedIndex:K.selectedIndex,totalFiles:X.length,stagedCount:X.filter((Q)=>Q.staged).length,files:X.map((Q)=>({path:Q.path,status:Q.status,staged:Q.staged})),historySelectedIndex:K.historySelectedIndex,historyCommitCount:Z.length,compareSelectedIndex:K.compareSelectedIndex,compareTotalItems:0,includeUncommitted:K.includeUncommitted,explorerPath:this.repoPath,explorerSelectedIndex:K.explorerSelectedIndex,explorerItemCount:0,wrapMode:K.wrapMode,mouseEnabled:K.mouseEnabled,autoTabEnabled:K.autoTabEnabled}}navigateUp(){let K=this.uiState.state;if(K.bottomTab==="history"){if(K.currentPane==="history")this.navigateHistoryUp();else if(K.currentPane==="diff")this.uiState.setDiffScrollOffset(Math.max(0,K.diffScrollOffset-3));return}if(K.bottomTab==="compare"){if(K.currentPane==="compare")this.navigateCompareUp();else if(K.currentPane==="diff")this.uiState.setDiffScrollOffset(Math.max(0,K.diffScrollOffset-3));return}if(K.bottomTab==="explorer"){if(K.currentPane==="explorer")this.navigateExplorerUp();else if(K.currentPane==="diff")this.uiState.setExplorerFileScrollOffset(Math.max(0,K.explorerFileScrollOffset-3));return}if(K.currentPane==="files"){let $=this.gitManager?.state.status?.files??[],J=Math.max(0,K.selectedIndex-1);this.uiState.setSelectedIndex(J),this.selectFileByIndex(J);let X=TK(J,$);if(X<K.fileListScrollOffset)this.uiState.setFileListScrollOffset(X)}else if(K.currentPane==="diff")this.uiState.setDiffScrollOffset(Math.max(0,K.diffScrollOffset-3))}navigateDown(){let K=this.uiState.state,$=this.gitManager?.state.status?.files??[];if(K.bottomTab==="history"){if(K.currentPane==="history")this.navigateHistoryDown();else if(K.currentPane==="diff")this.uiState.setDiffScrollOffset(K.diffScrollOffset+3);return}if(K.bottomTab==="compare"){if(K.currentPane==="compare")this.navigateCompareDown();else if(K.currentPane==="diff")this.uiState.setDiffScrollOffset(K.diffScrollOffset+3);return}if(K.bottomTab==="explorer"){if(K.currentPane==="explorer")this.navigateExplorerDown();else if(K.currentPane==="diff")this.uiState.setExplorerFileScrollOffset(K.explorerFileScrollOffset+3);return}if(K.currentPane==="files"){let J=Math.min($.length-1,K.selectedIndex+1);this.uiState.setSelectedIndex(J),this.selectFileByIndex(J);let X=TK(J,$),Z=K.fileListScrollOffset+this.layout.dimensions.topPaneHeight-1;if(X>=Z)this.uiState.setFileListScrollOffset(K.fileListScrollOffset+(X-Z+1))}else if(K.currentPane==="diff")this.uiState.setDiffScrollOffset(K.diffScrollOffset+3)}navigateHistoryUp(){let K=this.uiState.state,$=Math.max(0,K.historySelectedIndex-1);if($!==K.historySelectedIndex){if(this.uiState.setHistorySelectedIndex($),$<K.historyScrollOffset)this.uiState.setHistoryScrollOffset($);this.selectHistoryCommitByIndex($)}}navigateHistoryDown(){let K=this.uiState.state,$=this.gitManager?.historyState.commits??[],J=Math.min($.length-1,K.historySelectedIndex+1);if(J!==K.historySelectedIndex){this.uiState.setHistorySelectedIndex(J);let X=K.historyScrollOffset+this.layout.dimensions.topPaneHeight-1;if(J>=X)this.uiState.setHistoryScrollOffset(K.historyScrollOffset+1);this.selectHistoryCommitByIndex(J)}}selectHistoryCommitByIndex(K){let $=this.gitManager?.historyState.commits??[],J=F7($,K);if(J)this.uiState.setDiffScrollOffset(0),this.gitManager?.selectHistoryCommit(J)}compareSelection=null;navigateCompareUp(){let K=this.gitManager?.compareState,$=K?.compareDiff?.commits??[],J=K?.compareDiff?.files??[];if($.length===0&&J.length===0)return;let X=CK(this.compareSelection,$,J,"up");if(X&&(X.type!==this.compareSelection?.type||X.index!==this.compareSelection?.index)){this.selectCompareItem(X);let Z=this.uiState.state,Q=UK(X,$,J);if(Q<Z.compareScrollOffset)this.uiState.setCompareScrollOffset(Q)}}navigateCompareDown(){let K=this.gitManager?.compareState,$=K?.compareDiff?.commits??[],J=K?.compareDiff?.files??[];if($.length===0&&J.length===0)return;if(!this.compareSelection){if($.length>0)this.selectCompareItem({type:"commit",index:0});else if(J.length>0)this.selectCompareItem({type:"file",index:0});return}let X=CK(this.compareSelection,$,J,"down");if(X&&(X.type!==this.compareSelection?.type||X.index!==this.compareSelection?.index)){this.selectCompareItem(X);let Z=this.uiState.state,Q=UK(X,$,J),q=Z.compareScrollOffset+this.layout.dimensions.topPaneHeight-1;if(Q>=q)this.uiState.setCompareScrollOffset(Z.compareScrollOffset+(Q-q+1))}}selectCompareItem(K){if(this.compareSelection=K,this.uiState.setDiffScrollOffset(0),K.type==="commit")this.gitManager?.selectCompareCommit(K.index);else this.gitManager?.selectCompareFile(K.index)}navigateExplorerUp(){let K=this.uiState.state;if((this.explorerManager?.state.items??[]).length===0)return;let J=this.explorerManager?.navigateUp(K.explorerScrollOffset);if(J!==null&&J!==void 0)this.uiState.setExplorerScrollOffset(J);this.uiState.setExplorerSelectedIndex(this.explorerManager?.state.selectedIndex??0)}navigateExplorerDown(){let K=this.uiState.state;if((this.explorerManager?.state.items??[]).length===0)return;let J=this.layout.dimensions.topPaneHeight,X=this.explorerManager?.navigateDown(K.explorerScrollOffset,J);if(X!==null&&X!==void 0)this.uiState.setExplorerScrollOffset(X);this.uiState.setExplorerSelectedIndex(this.explorerManager?.state.selectedIndex??0)}async enterExplorerDirectory(){await this.explorerManager?.enterDirectory(),this.uiState.setExplorerScrollOffset(0),this.uiState.setExplorerFileScrollOffset(0),this.uiState.setExplorerSelectedIndex(0)}async goExplorerUp(){await this.explorerManager?.goUp(),this.uiState.setExplorerScrollOffset(0),this.uiState.setExplorerFileScrollOffset(0),this.uiState.setExplorerSelectedIndex(0)}selectFileByIndex(K){let $=this.gitManager?.state.status?.files??[],J=z7($,K);if(J)this.uiState.setDiffScrollOffset(0),this.gitManager?.selectFile(J)}navigateToFile(K){if(!K||!this.repoPath)return;let $=this.repoPath.endsWith("/")?this.repoPath:this.repoPath+"/";if(!K.startsWith($))return;let J=K.slice($.length);if(!J)return;let Z=(this.gitManager?.state.status?.files??[]).findIndex((Q)=>Q.path===J);if(Z>=0)this.uiState.setSelectedIndex(Z),this.selectFileByIndex(Z)}async stageSelected(){let $=(this.gitManager?.state.status?.files??[])[this.uiState.state.selectedIndex];if($&&!$.staged)await this.gitManager?.stage($)}async unstageSelected(){let $=(this.gitManager?.state.status?.files??[])[this.uiState.state.selectedIndex];if($?.staged)await this.gitManager?.unstage($)}async toggleSelected(){let $=(this.gitManager?.state.status?.files??[])[this.uiState.state.selectedIndex];if($)if($.staged)await this.gitManager?.unstage($);else await this.gitManager?.stage($)}async stageAll(){await this.gitManager?.stageAll()}async unstageAll(){await this.gitManager?.unstageAll()}showDiscardConfirm(K){this.activeModal=new mK(this.screen,K.path,async()=>{this.activeModal=null,await this.gitManager?.discard(K)},()=>{this.activeModal=null}),this.activeModal.focus()}async commit(K){await this.gitManager?.commit(K)}async refresh(){await this.gitManager?.refresh()}toggleMouseMode(){let K=!this.uiState.state.mouseEnabled;this.uiState.toggleMouse();let $=this.screen.program;if(K)$.enableMouse();else $.disableMouse()}toggleFollow(){if(this.fileWatcher)this.fileWatcher.stop(),this.fileWatcher=null,this.watcherState={enabled:!1};else this.setupFileWatcher();this.render()}focusCommitInput(){if(this.commitTextarea)this.commitTextarea.show(),this.commitTextarea.focus(),this.commitTextarea.setValue(this.commitFlowState.state.message),this.commitFlowState.setInputFocused(!0),this.render()}unfocusCommitInput(){if(this.commitTextarea){let K=this.commitTextarea.getValue()??"";this.commitFlowState.setMessage(K),this.commitTextarea.hide(),this.commitFlowState.setInputFocused(!1),this.screen.focusPush(this.layout.bottomPane),this.render()}}render(){this.updateHeader(),this.updateTopPane(),this.updateBottomPane(),this.updateFooter(),this.screen.render()}updateHeader(){let K=this.gitManager?.state,$=this.screen.width||80,J=X7(this.repoPath,K?.status?.branch??null,K?.isLoading??!1,K?.error??null,this.watcherState,$);this.layout.headerBox.setContent(J)}updateTopPane(){let K=this.gitManager?.state,$=this.gitManager?.historyState,J=this.gitManager?.compareState,X=K?.status?.files??[],Z=this.uiState.state,Q=this.screen.width||80,q;if(Z.bottomTab==="history"){let Y=$?.commits??[];q=R7(Y,Z.historySelectedIndex,Z.currentPane==="history",Q,Z.historyScrollOffset,this.layout.dimensions.topPaneHeight)}else if(Z.bottomTab==="compare"){let Y=J?.compareDiff,V=Y?.commits??[],_=Y?.files??[];q=v7(V,_,this.compareSelection,Z.currentPane==="compare",Q,Z.compareScrollOffset,this.layout.dimensions.topPaneHeight)}else if(Z.bottomTab==="explorer"){let Y=this.explorerManager?.state,V=Y?.items??[];q=W7(V,Z.explorerSelectedIndex,Z.currentPane==="explorer",Q,Z.explorerScrollOffset,this.layout.dimensions.topPaneHeight,Y?.isLoading??!1,Y?.error??null)}else q=q7(X,Z.selectedIndex,Z.currentPane==="files",Q,Z.fileListScrollOffset,this.layout.dimensions.topPaneHeight);this.layout.topPane.setContent(q)}updateBottomPane(){let K=this.gitManager?.state,$=this.gitManager?.historyState,J=K?.diff??null,X=this.uiState.state,Z=this.screen.width||80,q=(K?.status?.files??[]).filter((Y)=>Y.staged).length;if(this.commitFlowState.setStagedCount(q),X.bottomTab==="commit"){let Y=D7(this.commitFlowState.state,q,Z);if(this.layout.bottomPane.setContent(Y),this.commitTextarea)if(this.commitFlowState.state.inputFocused)this.commitTextarea.show();else this.commitTextarea.hide()}else if(X.bottomTab==="history"){if(this.commitTextarea)this.commitTextarea.hide();let Y=$?.selectedCommit??null,V=$?.commitDiff??null,{content:_,totalRows:z}=I7(Y,V,Z,X.diffScrollOffset,this.layout.dimensions.bottomPaneHeight,this.currentTheme,X.wrapMode);this.bottomPaneTotalRows=z,this.layout.bottomPane.setContent(_)}else if(X.bottomTab==="compare"){if(this.commitTextarea)this.commitTextarea.hide();let V=this.gitManager?.compareSelectionState?.diff??null;if(V){let{content:_,totalRows:z}=yK(V,Z,X.diffScrollOffset,this.layout.dimensions.bottomPaneHeight,this.currentTheme,X.wrapMode);this.bottomPaneTotalRows=z,this.layout.bottomPane.setContent(_)}else this.bottomPaneTotalRows=0,this.layout.bottomPane.setContent("{gray-fg}Select a commit or file to view diff{/gray-fg}")}else if(X.bottomTab==="explorer"){if(this.commitTextarea)this.commitTextarea.hide();let V=this.explorerManager?.state?.selectedFile??null,_=x7(V?.path??null,V?.content??null,Z,X.explorerFileScrollOffset,this.layout.dimensions.bottomPaneHeight,V?.truncated??!1,X.wrapMode,X.showMiddleDots);this.layout.bottomPane.setContent(_)}else{if(this.commitTextarea)this.commitTextarea.hide();let{content:Y,totalRows:V}=yK(J,Z,X.diffScrollOffset,this.layout.dimensions.bottomPaneHeight,this.currentTheme,X.wrapMode);this.bottomPaneTotalRows=V,this.layout.bottomPane.setContent(Y)}}updateFooter(){let K=this.uiState.state,$=this.screen.width||80,J=Q7(K.bottomTab,K.mouseEnabled,K.autoTabEnabled,K.wrapMode,K.showMiddleDots,$);this.layout.footerBox.setContent(J)}exit(){if(this.gitManager)aK(this.repoPath);if(this.explorerManager)this.explorerManager.dispose();if(this.fileWatcher)this.fileWatcher.stop();if(this.commandServer)this.commandServer.stop();this.screen.destroy()}start(){return new Promise((K)=>{this.screen.on("destroy",()=>{K()})})}}import*as A8 from"net";import*as u from"fs";import{EventEmitter as q9}from"events";class K7 extends q9{server=null;socketPath;handler=null;ready=!1;constructor(K){super();this.socketPath=K}setHandler(K){this.handler=K}notifyReady(){this.ready=!0,this.emit("ready")}isReady(){return this.ready&&this.handler!==null}async start(){if(u.existsSync(this.socketPath))u.unlinkSync(this.socketPath);return new Promise((K,$)=>{this.server=A8.createServer((J)=>{this.handleConnection(J)}),this.server.on("error",(J)=>{$(J)}),this.server.listen(this.socketPath,()=>{u.chmodSync(this.socketPath,384),K()})})}stop(){if(this.server)this.server.close(),this.server=null;if(u.existsSync(this.socketPath))u.unlinkSync(this.socketPath)}handleConnection(K){let $="";K.on("data",async(J)=>{$+=J.toString();let X=$.split(`
55
- `);$=X.pop()||"";for(let Z of X)if(Z.trim()){let Q=await this.processCommand(Z);K.write(JSON.stringify(Q)+`
56
- `)}}),K.on("error",(J)=>{this.emit("error",J)})}async processCommand(K){try{let $=JSON.parse(K);if($.action==="ping")return{success:!0,ready:this.isReady()};if(!this.handler)return{success:!1,error:"No handler registered"};switch($.action){case"navigateUp":return this.handler.navigateUp(),{success:!0};case"navigateDown":return this.handler.navigateDown(),{success:!0};case"switchTab":return this.handler.switchTab($.tab),{success:!0};case"togglePane":return this.handler.togglePane(),{success:!0};case"stage":return await this.handler.stage(),{success:!0};case"unstage":return await this.handler.unstage(),{success:!0};case"stageAll":return await this.handler.stageAll(),{success:!0};case"unstageAll":return await this.handler.unstageAll(),{success:!0};case"commit":return await this.handler.commit($.message),{success:!0};case"refresh":return await this.handler.refresh(),{success:!0};case"getState":return{success:!0,state:this.handler.getState()};case"quit":return this.handler.quit(),{success:!0};default:return{success:!1,error:`Unknown action: ${$.action}`}}}catch($){return{success:!1,error:$ instanceof Error?$.message:String($)}}}}function f(){process.stdout.write("\x1B[?1006l"),process.stdout.write("\x1B[?1002l"),process.stdout.write("\x1B[?1000l"),process.stdout.write("\x1B[?1003l"),process.stdout.write("\x1B[?25h"),process.stdout.write("\x1B[?1049l"),process.stdout.write("\x1B[r")}f();process.on("exit",f);process.on("SIGINT",()=>{f(),process.exit(0)});process.on("SIGTERM",()=>{f(),process.exit(0)});process.on("uncaughtException",(K)=>{f(),console.error("Uncaught exception:",K),process.exit(1)});process.on("unhandledRejection",(K)=>{f(),console.error("Unhandled rejection:",K),process.exit(1)});function Y9(K){let $={};for(let J=0;J<K.length;J++){let X=K[J];if(X==="--follow"||X==="-f"){if($.follow=!0,K[J+1]&&!K[J+1].startsWith("-"))$.followFile=K[++J]}else if(X==="--once")$.once=!0;else if(X==="--debug"||X==="-d")$.debug=!0;else if(X==="--socket"||X==="-s")if(K[J+1]&&!K[J+1].startsWith("-"))$.socket=K[++J];else console.error("Error: --socket requires a path argument"),process.exit(1);else if(X==="--help"||X==="-h")console.log(`
29
+ `),process.stderr.write(` Raw content: "${J}"
30
+ `),process.stderr.write(` Resolved: "${Z}"
31
+ `);this.lastReadPath=Z,this._state={path:Z,lastUpdate:K,rawContent:J,sourceFile:this.targetFile}}}catch{}this.watcher=_9(this.targetFile,{persistent:!0,ignoreInitial:!0}),this.watcher.on("change",()=>this.readTargetDebounced()),this.watcher.on("add",()=>this.readTargetDebounced())}stop(){if(this.debounceTimer)clearTimeout(this.debounceTimer),this.debounceTimer=null;if(this.watcher)this.watcher.close(),this.watcher=null}}class C${targetFile;getCurrentRepoPath;callbacks;watcher=null;_watcherState={enabled:!1};constructor($,J,Z){this.targetFile=$,this.getCurrentRepoPath=J,this.callbacks=Z}get watcherState(){return this._watcherState}get isEnabled(){return this.watcher!==null}start(){this.watcher=new Q8(this.targetFile),this.watcher.on("path-change",(J)=>{if(J.path&&J.path!==this.getCurrentRepoPath())this._watcherState={enabled:!0,sourceFile:J.sourceFile??this.targetFile,rawContent:J.rawContent??void 0,lastUpdate:J.lastUpdate??void 0},this.callbacks.onRepoChange(J.path,this._watcherState);if(J.rawContent)this.callbacks.onFileNavigate(J.rawContent)}),this._watcherState={enabled:!0,sourceFile:this.targetFile},this.watcher.start();let $=this.watcher.state;if($.path&&$.path!==this.getCurrentRepoPath())this._watcherState={enabled:!0,sourceFile:$.sourceFile??this.targetFile,rawContent:$.rawContent??void 0,lastUpdate:$.lastUpdate??void 0},this.callbacks.onRepoChange($.path,this._watcherState);else if($.rawContent)this._watcherState.rawContent=$.rawContent,this.callbacks.onFileNavigate($.rawContent)}toggle(){if(this.watcher)this.stop();else this.start()}stop(){if(this.watcher)this.watcher.stop(),this.watcher=null,this._watcherState={enabled:!1}}}function O9($){let J=`{bold}{green-fg}${$.current}{/green-fg}{/bold}`;if($.tracking)J+=` {gray-fg}→{/gray-fg} {blue-fg}${$.tracking}{/blue-fg}`;if($.ahead>0)J+=` {green-fg}↑${$.ahead}{/green-fg}`;if($.behind>0)J+=` {red-fg}↓${$.behind}{/red-fg}`;return J}function v9($){let J=$.current.length;if($.tracking)J+=3+$.tracking.length;if($.ahead>0)J+=3+String($.ahead).length;if($.behind>0)J+=3+String($.behind).length;return J}function b0($,J,Z,K,X){if(!$)return"{gray-fg}Waiting for target path...{/gray-fg}";let Q=y0($),q=K==="Not a git repository",z=`{bold}{cyan-fg}${Q}{/cyan-fg}{/bold}`;if(Z)z+=" {yellow-fg}⟳{/yellow-fg}";if(q)z+=" {yellow-fg}(not a git repository){/yellow-fg}";else if(K)z+=` {red-fg}(${K}){/red-fg}`;let V=J?O9(J):"";if(V){let Y=Q.length;if(Z)Y+=2;if(q)Y+=24;else if(K)Y+=K.length+3;let U=J?v9(J):0,j=Math.max(1,X-Y-U-2);return z+" ".repeat(j)+V}return z}function w0($){return $.replace(/\{[^}]+\}/g,"").length}function y$($,J){return J?`{blue-fg}[${$}]{/blue-fg}`:`{gray-fg}[${$}]{/gray-fg}`}function W9($,J,Z,K,X,Q){let q=[];if(q.push($?"{yellow-fg}[scroll]{/yellow-fg}":"{yellow-fg}m:[select]{/yellow-fg}"),q.push(y$("auto",J)),q.push(y$("wrap",Z)),q.push(y$("follow",K)),Q==="explorer")q.push(y$("changes",X));return q.join(" ")}function x0($,J,Z,K,X,Q,q,z){let V="{gray-fg}?{/gray-fg} ";if(V+=W9(J,Z,K,X,Q,$),$==="diff"&&z==="diff")V+=" {gray-fg}n/N:hunk s:toggle{/gray-fg}";let U=[{key:"1",label:"Diff",tab:"diff"},{key:"2",label:"Commit",tab:"commit"},{key:"3",label:"History",tab:"history"},{key:"4",label:"Compare",tab:"compare"},{key:"5",label:"Explorer",tab:"explorer"}].map(({key:_,label:v,tab:W})=>{if($===W)return`{bold}{cyan-fg}[${_}]${v}{/cyan-fg}{/bold}`;return`[${_}]${v}`}).join(" "),j=w0(V),G=w0(U),B=Math.max(1,q-j-G);return V+" ".repeat(B)+U}import*as o from"node:fs";import*as L from"node:path";import{EventEmitter as D9}from"node:events";import{simpleGit as A9}from"simple-git";async function Q$($,J){if(J.length===0)return new Set;let Z=A9($),K=new Set,X=100;for(let Q=0;Q<J.length;Q+=X){let q=J.slice(Q,Q+X);try{let V=(await Z.raw(["check-ignore",...q])).trim().split(`
32
+ `).filter((Y)=>Y.length>0);for(let Y of V)K.add(Y)}catch{}}return K}var T9=1048576,N9=102400;function H9($){let J=Math.min($.length,8192);for(let Z=0;Z<J;Z++)if($[Z]===0)return!0;return!1}class q8 extends D9{repoPath;options;expandedPaths=new Set;gitStatusMap={files:new Map,directories:new Set};_state={currentPath:"",tree:null,displayRows:[],selectedIndex:0,selectedFile:null,isLoading:!1,error:null};constructor($,J){super();this.repoPath=$,this.options={hideHidden:J.hideHidden??!0,hideGitignored:J.hideGitignored??!0,showOnlyChanges:J.showOnlyChanges??!1},this.expandedPaths.add("")}get state(){return this._state}updateState($){this._state={...this._state,...$},this.emit("state-change",this._state)}async setOptions($){this.options={...this.options,...$},await this.loadTree()}setGitStatus($){if(this.gitStatusMap=$,this._state.tree)this.applyGitStatusToTree(this._state.tree),this.refreshDisplayRows()}async toggleShowOnlyChanges(){this.options.showOnlyChanges=!this.options.showOnlyChanges,this.refreshDisplayRows()}get showOnlyChanges(){return this.options.showOnlyChanges}async loadTree(){this.updateState({isLoading:!0,error:null});try{let $=await this.buildTreeNode("",0);if($){$.expanded=!0,this.applyGitStatusToTree($);let J=this.flattenTree($);this.updateState({tree:$,displayRows:J,selectedIndex:0,selectedFile:null,isLoading:!1})}else this.updateState({tree:null,displayRows:[],isLoading:!1,error:"Failed to load directory"})}catch($){this.updateState({error:$ instanceof Error?$.message:"Failed to read directory",tree:null,displayRows:[],isLoading:!1})}}async buildTreeNode($,J){try{let Z=L.join(this.repoPath,$);if(!(await o.promises.stat(Z)).isDirectory())return{name:L.basename($)||this.getRepoName(),path:$,isDirectory:!1,expanded:!1,children:[],childrenLoaded:!0};let X=this.expandedPaths.has($),Q={name:L.basename($)||this.getRepoName(),path:$,isDirectory:!0,expanded:X,children:[],childrenLoaded:!1};if($===""||X)await this.loadChildrenForNode(Q);return Q}catch{return null}}async loadChildrenForNode($){if($.childrenLoaded)return;try{let J=L.join(this.repoPath,$.path),Z=await o.promises.readdir(J,{withFileTypes:!0}),K=Z.map((q)=>$.path?L.join($.path,q.name):q.name),X=this.options.hideGitignored?await Q$(this.repoPath,K):new Set,Q=[];for(let q of Z){if(this.options.hideHidden&&q.name.startsWith("."))continue;let z=$.path?L.join($.path,q.name):q.name;if(this.options.hideGitignored&&X.has(z))continue;let V=q.isDirectory(),Y=this.expandedPaths.has(z),U={name:q.name,path:z,isDirectory:V,expanded:Y,children:[],childrenLoaded:!V};if(V&&Y)await this.loadChildrenForNode(U);Q.push(U)}Q.sort((q,z)=>{if(q.isDirectory&&!z.isDirectory)return-1;if(!q.isDirectory&&z.isDirectory)return 1;return q.name.localeCompare(z.name)}),this.collapseNode($,Q),$.childrenLoaded=!0}catch{$.childrenLoaded=!0,$.children=[]}}collapseNode($,J){for(let Z of J)if(Z.isDirectory&&Z.childrenLoaded)while(Z.children.length===1&&Z.children[0].isDirectory&&Z.children[0].childrenLoaded){let K=Z.children[0];Z.name=`${Z.name}/${K.name}`,Z.path=K.path,Z.children=K.children,Z.expanded=this.expandedPaths.has(Z.path)}$.children=J}applyGitStatusToTree($){if(!$.isDirectory){let J=this.gitStatusMap.files.get($.path);if(J)$.gitStatus=J.status;else $.gitStatus=void 0}else{$.hasChangedChildren=this.gitStatusMap.directories.has($.path);for(let J of $.children)this.applyGitStatusToTree(J)}}shouldIncludeNode($){if(!this.options.showOnlyChanges)return!0;if($.isDirectory)return!!$.hasChangedChildren;return!!$.gitStatus}flattenTree($){let J=[],Z=(K,X,Q)=>{for(let q=0;q<K.children.length;q++){let z=K.children[q],V=q===K.children.length-1;if(!this.shouldIncludeNode(z))continue;if(J.push({node:z,depth:X,isLast:V,parentIsLast:[...Q]}),z.isDirectory&&z.expanded)Z(z,X+1,[...Q,V])}};return Z($,0,[]),J}refreshDisplayRows(){if(!this._state.tree)return;let $=this._state.displayRows[this._state.selectedIndex]?.node.path??null,J=this.flattenTree(this._state.tree),Z=0;if($!==null){let K=J.findIndex((X)=>X.node.path===$);if(K>=0)Z=K}Z=Math.min(Z,Math.max(0,J.length-1)),this.updateState({displayRows:J,selectedIndex:Z})}getRepoName(){return L.basename(this.repoPath)||"repo"}async loadDirectory($){this._state.currentPath=$,await this.loadTree()}async loadFile($){try{let J=L.join(this.repoPath,$),Z=await o.promises.stat(J);if(Z.size>T9){this.updateState({selectedFile:{path:$,content:`File too large to display (${(Z.size/1024/1024).toFixed(2)} MB).
33
+ Maximum size: 1 MB`,truncated:!0}});return}let K=await o.promises.readFile(J);if(H9(K)){this.updateState({selectedFile:{path:$,content:"Binary file - cannot display"}});return}let X=K.toString("utf-8"),Q=!1;if(Z.size>N9)X=`Warning: Large file (${(Z.size/1024).toFixed(1)} KB)
34
+
35
+ `+X;let q=5000,z=X.split(`
36
+ `);if(z.length>q)X=z.slice(0,q).join(`
37
+ `)+`
38
+
39
+ ... (truncated, ${z.length-q} more lines)`,Q=!0;this.updateState({selectedFile:{path:$,content:X,truncated:Q}})}catch(J){this.updateState({selectedFile:{path:$,content:J instanceof Error?`Error: ${J.message}`:"Failed to read file"}})}}async selectIndex($){let J=this._state.displayRows;if($<0||$>=J.length)return;let Z=J[$];if(this.updateState({selectedIndex:$}),Z&&!Z.node.isDirectory)await this.loadFile(Z.node.path);else this.updateState({selectedFile:null})}navigateUp($){let J=Math.max(0,this._state.selectedIndex-1);if(J===this._state.selectedIndex)return null;if(this.selectIndex(J),J<$)return J;return null}navigateDown($,J){let Z=Math.min(this._state.displayRows.length-1,this._state.selectedIndex+1);if(Z===this._state.selectedIndex)return null;this.selectIndex(Z);let X=this._state.displayRows.length>J?J-2:J,Q=$+X;if(Z>=Q)return $+1;return null}async toggleExpand(){let $=this._state.displayRows,J=this._state.selectedIndex;if(J<0||J>=$.length)return;let Z=$[J];if(!Z.node.isDirectory)return;let K=Z.node;if(K.expanded)this.expandedPaths.delete(K.path),K.expanded=!1;else if(this.expandedPaths.add(K.path),K.expanded=!0,!K.childrenLoaded)await this.loadChildrenForNode(K),this.applyGitStatusToTree(K);this.refreshDisplayRows()}async enterDirectory(){let $=this._state.displayRows,J=this._state.selectedIndex;if(J<0||J>=$.length)return;if($[J].node.isDirectory)await this.toggleExpand()}async goUp(){let $=this._state.displayRows,J=this._state.selectedIndex;if(J<0||J>=$.length)return;let K=$[J].node.path,X=L.dirname(K);if(X==="."||X==="")return;let Q=K.split("/");for(let q=Q.length-1;q>0;q--){let z=Q.slice(0,q).join("/");if(this.expandedPaths.has(z)){this.expandedPaths.delete(z);let V=this.findNodeByPath(z);if(V)V.expanded=!1;this.refreshDisplayRows();let U=this._state.displayRows.findIndex((j)=>j.node.path===z);if(U>=0)this.updateState({selectedIndex:U,selectedFile:null});return}}}findNodeByPath($){if(!this._state.tree)return null;let J=(Z)=>{if(Z.path===$)return Z;for(let K of Z.children){let X=J(K);if(X)return X}return null};return J(this._state.tree)}async getAllFilePaths(){let $=[],J=async(Z)=>{try{let K=L.join(this.repoPath,Z),X=await o.promises.readdir(K,{withFileTypes:!0}),Q=X.map((z)=>Z?L.join(Z,z.name):z.name),q=this.options.hideGitignored?await Q$(this.repoPath,Q):new Set;for(let z of X){if(this.options.hideHidden&&z.name.startsWith("."))continue;let V=Z?L.join(Z,z.name):z.name;if(this.options.hideGitignored&&q.has(V))continue;if(z.isDirectory())await J(V);else $.push(V)}}catch{}};return await J(""),$}async navigateToPath($){if(!this._state.tree)return!1;let J=$.split("/"),Z="";for(let X=0;X<J.length-1;X++)Z=Z?`${Z}/${J[X]}`:J[X],this.expandedPaths.add(Z);await this.loadTree();let K=this._state.displayRows.findIndex((X)=>X.node.path===$);if(K>=0)return await this.selectIndex(K),!0;return!1}dispose(){this.removeAllListeners()}}import E9 from"neo-blessed";class z8{box;screen;selectedIndex;currentTheme;onSelect;onCancel;constructor($,J,Z,K){if(this.screen=$,this.currentTheme=J,this.onSelect=Z,this.onCancel=K,this.selectedIndex=d.indexOf(J),this.selectedIndex<0)this.selectedIndex=0;let X=50,Q=d.length+12;this.box=E9.box({parent:$,top:"center",left:"center",width:X,height:Q,border:{type:"line"},style:{border:{fg:"cyan"}},tags:!0,keys:!0}),this.setupKeyHandlers(),this.render()}setupKeyHandlers(){this.box.key(["escape","q"],()=>{this.close(),this.onCancel()}),this.box.key(["enter","space"],()=>{let $=d[this.selectedIndex];this.close(),this.onSelect($)}),this.box.key(["up","k"],()=>{this.selectedIndex=Math.max(0,this.selectedIndex-1),this.render()}),this.box.key(["down","j"],()=>{this.selectedIndex=Math.min(d.length-1,this.selectedIndex+1),this.render()})}render(){let $=[];$.push("{bold}{cyan-fg} Select Theme{/cyan-fg}{/bold}"),$.push("");for(let J=0;J<d.length;J++){let Z=d[J],K=A$[Z],X=J===this.selectedIndex,Q=Z===this.currentTheme,q=X?"{cyan-fg}{bold}> ":" ";if(q+=K.displayName,X)q+="{/bold}{/cyan-fg}";if(Q)q+=" {gray-fg}(current){/gray-fg}";$.push(q)}$.push(""),$.push("{gray-fg}Preview:{/gray-fg}"),$.push(" {green-fg}+ added line{/green-fg}"),$.push(" {red-fg}- deleted line{/red-fg}"),$.push(""),$.push("{gray-fg}j/k: navigate | Enter: select | Esc: cancel{/gray-fg}"),this.box.setContent($.join(`
40
+ `)),this.screen.render()}close(){this.box.destroy()}focus(){this.box.focus()}}import k9 from"neo-blessed";var g=[{title:"Navigation",entries:[{key:"j/k",description:"Move up/down"},{key:"Tab",description:"Toggle pane focus"}]},{title:"Staging",entries:[{key:"s",description:"Stage file"},{key:"U",description:"Unstage file"},{key:"A",description:"Stage all"},{key:"Z",description:"Unstage all"},{key:"Space",description:"Toggle stage"}]},{title:"Actions",entries:[{key:"c",description:"Commit panel"},{key:"r",description:"Refresh"},{key:"q",description:"Quit"}]},{title:"Resize",entries:[{key:"-",description:"Shrink top pane"},{key:"+",description:"Grow top pane"}]},{title:"Tabs",entries:[{key:"1",description:"Diff view"},{key:"2",description:"Commit panel"},{key:"3",description:"History view"},{key:"4",description:"Compare view"},{key:"5",description:"Explorer view"}]},{title:"Toggles",entries:[{key:"h",description:"Flat file view"},{key:"m",description:"Mouse mode"},{key:"w",description:"Wrap mode"},{key:"f",description:"Follow mode"},{key:"t",description:"Theme picker"},{key:"?",description:"This help"}]},{title:"Explorer",entries:[{key:"Enter",description:"Enter directory"},{key:"Backspace",description:"Go up"},{key:"/",description:"Find file"},{key:"Ctrl+P",description:"Find file (any tab)"},{key:"g",description:"Show changes only"}]},{title:"Compare",entries:[{key:"b",description:"Base branch picker"},{key:"u",description:"Toggle uncommitted"}]},{title:"Diff (pane focus)",entries:[{key:"n",description:"Next hunk"},{key:"N",description:"Previous hunk"},{key:"s",description:"Toggle hunk staged/unstaged"},{key:"d",description:"Discard changes"}]}];class V8{box;screen;onClose;constructor($,J){this.screen=$,this.onClose=J;let{width:Z,height:K}=$,X=Z>=90,Q=X?Math.min(80,Z-4):Math.min(42,Z-4),q=Math.min(this.calculateHeight(X),K-4);this.box=k9.box({parent:$,top:"center",left:"center",width:Q,height:q,border:{type:"line"},style:{border:{fg:"cyan"}},tags:!0,keys:!0,scrollable:!0,alwaysScroll:!0}),this.setupKeyHandlers(),this.render(X,Q)}calculateHeight($){if($){let J=Math.ceil(g.length/2),Z=g.slice(0,J),K=g.slice(J),X=Z.reduce((q,z)=>q+z.entries.length+2,0),Q=K.reduce((q,z)=>q+z.entries.length+2,0);return Math.max(X,Q)+5}else return g.reduce((J,Z)=>J+Z.entries.length+2,0)+5}setupKeyHandlers(){this.box.key(["escape","enter","?","q"],()=>{this.close(),this.onClose()}),this.box.on("click",()=>{this.close(),this.onClose()})}visibleWidth($){return $.replace(/\{[^}]+\}/g,"").length}padToVisible($,J){let Z=this.visibleWidth($),K=Math.max(0,J-Z);return $+" ".repeat(K)}render($,J){let Z=[];if(Z.push("{bold}{cyan-fg} Keyboard Shortcuts{/cyan-fg}{/bold}"),Z.push(""),$){let K=Math.ceil(g.length/2),X=g.slice(0,K),Q=g.slice(K),q=Math.floor((J-6)/2),z=this.renderGroups(X,q),V=this.renderGroups(Q,q),Y=Math.max(z.length,V.length);for(let U=0;U<Y;U++){let j=this.padToVisible(z[U]||"",q),G=V[U]||"";Z.push(j+" "+G)}}else for(let K of g){Z.push(`{bold}{gray-fg}${K.title}{/gray-fg}{/bold}`);for(let X of K.entries)Z.push(` {cyan-fg}${X.key.padEnd(10)}{/cyan-fg} ${X.description}`);Z.push("")}Z.push(""),Z.push("{gray-fg}Press Esc, Enter, or ? to close{/gray-fg}"),this.box.setContent(Z.join(`
41
+ `)),this.screen.render()}renderGroups($,J){let Z=[];for(let K of $){Z.push(`{bold}{gray-fg}${K.title}{/gray-fg}{/bold}`);for(let X of K.entries)Z.push(` {cyan-fg}${X.key.padEnd(10)}{/cyan-fg} ${X.description}`);Z.push("")}return Z}close(){this.box.destroy()}focus(){this.box.focus()}}import L9 from"neo-blessed";class Y8{box;screen;branches;selectedIndex;currentBranch;onSelect;onCancel;constructor($,J,Z,K,X){if(this.screen=$,this.branches=J,this.currentBranch=Z,this.onSelect=K,this.onCancel=X,this.selectedIndex=Z?J.indexOf(Z):0,this.selectedIndex<0)this.selectedIndex=0;let Q=50,z=Math.min(J.length,15)+6;this.box=L9.box({parent:$,top:"center",left:"center",width:Q,height:z,border:{type:"line"},style:{border:{fg:"cyan"}},tags:!0,keys:!0,scrollable:!0,alwaysScroll:!0}),this.setupKeyHandlers(),this.render()}setupKeyHandlers(){this.box.key(["escape","q"],()=>{this.close(),this.onCancel()}),this.box.key(["enter","space"],()=>{let $=this.branches[this.selectedIndex];if($)this.close(),this.onSelect($)}),this.box.key(["up","k"],()=>{this.selectedIndex=Math.max(0,this.selectedIndex-1),this.render()}),this.box.key(["down","j"],()=>{this.selectedIndex=Math.min(this.branches.length-1,this.selectedIndex+1),this.render()})}render(){let $=[];if($.push("{bold}{cyan-fg} Select Base Branch{/cyan-fg}{/bold}"),$.push(""),this.branches.length===0)$.push("{gray-fg}No branches found{/gray-fg}");else for(let J=0;J<this.branches.length;J++){let Z=this.branches[J],K=J===this.selectedIndex,X=Z===this.currentBranch,Q=K?"{cyan-fg}{bold}> ":" ";if(Q+=Z,K)Q+="{/bold}{/cyan-fg}";if(X)Q+=" {gray-fg}(current){/gray-fg}";$.push(Q)}$.push(""),$.push("{gray-fg}j/k: navigate | Enter: select | Esc: cancel{/gray-fg}"),this.box.setContent($.join(`
42
+ `)),this.screen.render()}close(){this.box.destroy()}focus(){this.box.focus()}}import R9 from"neo-blessed";class U8{box;screen;filePath;onConfirm;onCancel;constructor($,J,Z,K){this.screen=$,this.filePath=J,this.onConfirm=Z,this.onCancel=K;let X=Math.min(60,Math.max(40,J.length+20)),Q=7;this.box=R9.box({parent:$,top:"center",left:"center",width:X,height:Q,border:{type:"line"},style:{border:{fg:"yellow"}},tags:!0,keys:!0}),this.setupKeyHandlers(),this.render()}setupKeyHandlers(){this.box.key(["y","Y"],()=>{this.close(),this.onConfirm()}),this.box.key(["n","N","escape","q"],()=>{this.close(),this.onCancel()})}render(){let $=[];$.push("{bold}{yellow-fg} Discard Changes?{/yellow-fg}{/bold}"),$.push("");let J=this.box.width-6,Z=this.filePath.length>J?"..."+this.filePath.slice(-(J-3)):this.filePath;$.push(`{white-fg}${Z}{/white-fg}`),$.push(""),$.push("{gray-fg}Press {/gray-fg}{green-fg}y{/green-fg}{gray-fg} to confirm, {/gray-fg}{red-fg}n{/red-fg}{gray-fg} or Esc to cancel{/gray-fg}"),this.box.setContent($.join(`
43
+ `)),this.screen.render()}close(){this.box.destroy()}focus(){this.box.focus()}}import p0 from"neo-blessed";import{Fzf as F9}from"fzf";var P$=15;function I9($,J,Z){let K="";for(let X=0;X<$.length;X++)if(J.has(X+Z))K+=`{yellow-fg}${$[X]}{/yellow-fg}`;else K+=$[X];return K}class G8{box;textbox;screen;fzf;allPaths;results=[];selectedIndex=0;query="";onSelect;onCancel;constructor($,J,Z,K){this.screen=$,this.allPaths=J,this.fzf=new F9(J,{limit:P$,forward:!1}),this.onSelect=Z,this.onCancel=K;let X=Math.min(80,$.width-10),Q=P$+6;this.box=p0.box({parent:$,top:"center",left:"center",width:X,height:Q,border:{type:"line"},style:{border:{fg:"cyan"}},tags:!0,keys:!1}),this.textbox=p0.textarea({parent:this.box,top:1,left:1,width:X-4,height:1,inputOnFocus:!0,style:{fg:"white",bg:"default"}}),this.setupKeyHandlers(),this.updateResults(),this.render()}setupKeyHandlers(){this.textbox.key(["escape"],()=>{this.close(),this.onCancel()}),this.textbox.key(["enter"],()=>{if(this.results.length>0){let $=this.results[this.selectedIndex];this.close(),this.onSelect($.item)}}),this.textbox.key(["C-j","down"],()=>{this.selectedIndex=Math.min(this.results.length-1,this.selectedIndex+1),this.render()}),this.textbox.key(["C-k","up"],()=>{this.selectedIndex=Math.max(0,this.selectedIndex-1),this.render()}),this.textbox.key(["tab"],()=>{this.selectedIndex=(this.selectedIndex+1)%Math.max(1,this.results.length),this.render()}),this.textbox.key(["S-tab"],()=>{this.selectedIndex=(this.selectedIndex-1+this.results.length)%Math.max(1,this.results.length),this.render()}),this.textbox.on("keypress",()=>{setImmediate(()=>{let $=this.textbox.getValue()||"";if($!==this.query)this.query=$,this.selectedIndex=0,this.updateResults(),this.render()})})}updateResults(){if(!this.query){this.results=this.allPaths.slice(0,P$).map(($)=>({item:$,positions:new Set,start:0,end:0,score:0}));return}this.results=this.fzf.find(this.query)}render(){let $=[],J=this.box.width-4;if($.push("{bold}{cyan-fg}Find File{/cyan-fg}{/bold}"),$.push(""),$.push(""),this.results.length===0&&this.query)$.push("{gray-fg}No matches{/gray-fg}");else for(let Z=0;Z<this.results.length;Z++){let K=this.results[Z],X=Z===this.selectedIndex,Q=K.item,q=J-4,z=Q,V=0;if(z.length>q)V=z.length-(q-1),z="…"+z.slice(V),V=V-1;let Y=I9(z,K.positions,V);if(X)$.push(`{cyan-fg}{bold}> ${Y}{/bold}{/cyan-fg}`);else $.push(` ${Y}`)}while($.length<P$+3)$.push("");$.push("{gray-fg}Enter: select | Esc: cancel | Ctrl+j/k or ↑↓: navigate{/gray-fg}"),this.box.setContent($.join(`
44
+ `)),this.screen.render()}close(){this.textbox.destroy(),this.box.destroy()}focus(){this.textbox.focus()}}import{EventEmitter as C9}from"node:events";function g0($,J,Z){if(!$.trim())return{valid:!1,error:"Commit message cannot be empty"};if(J===0&&!Z)return{valid:!1,error:"No changes staged for commit"};return{valid:!0,error:null}}function u0($){return $.trim()}var m0={message:"",amend:!1,isCommitting:!1,error:null,inputFocused:!1};class B8 extends C9{_state={...m0};getHeadMessage;onCommit;onSuccess;stagedCount=0;constructor($){super();this.getHeadMessage=$.getHeadMessage,this.onCommit=$.onCommit,this.onSuccess=$.onSuccess}get state(){return this._state}update($){this._state={...this._state,...$},this.emit("change",this._state)}setStagedCount($){this.stagedCount=$}setMessage($){this.update({message:$,error:null})}setInputFocused($){this.update({inputFocused:$}),this.emit("focus-change",$)}async toggleAmend(){let $=!this._state.amend;if(this.update({amend:$}),$&&!this._state.message)try{let J=await this.getHeadMessage();if(J)this.update({message:J})}catch{}}async submit(){let $=g0(this._state.message,this.stagedCount,this._state.amend);if(!$.valid){this.update({error:$.error});return}this.update({isCommitting:!0,error:null});try{await this.onCommit(u0(this._state.message),this._state.amend),this.update({message:"",amend:!1,isCommitting:!1,inputFocused:!1}),this.onSuccess()}catch(J){this.update({isCommitting:!1,error:J instanceof Error?J.message:"Commit failed"})}}reset(){this._state={...m0},this.emit("change",this._state)}}import{EventEmitter as y9}from"node:events";var P9={currentPane:"files",bottomTab:"diff",selectedIndex:0,fileListScrollOffset:0,diffScrollOffset:0,historyScrollOffset:0,compareScrollOffset:0,explorerScrollOffset:0,explorerFileScrollOffset:0,historySelectedIndex:0,compareSelectedIndex:0,includeUncommitted:!1,explorerSelectedIndex:0,selectedHunkIndex:0,wrapMode:!1,autoTabEnabled:!1,mouseEnabled:!0,hideHiddenFiles:!0,hideGitignored:!0,flatViewMode:!1,splitRatio:0.4,activeModal:null,pendingDiscard:null,commitInputFocused:!1};class j8 extends y9{_state;constructor($={}){super();this._state={...P9,...$}}get state(){return this._state}update($){this._state={...this._state,...$},this.emit("change",this._state)}setPane($){if(this._state.currentPane!==$)this.update({currentPane:$}),this.emit("pane-change",$)}setTab($){if(this._state.bottomTab!==$){let J={diff:"files",commit:"commit",history:"history",compare:"compare",explorer:"explorer"};this.update({bottomTab:$,currentPane:J[$]}),this.emit("tab-change",$)}}setSelectedIndex($){if(this._state.selectedIndex!==$)this.update({selectedIndex:$}),this.emit("selection-change",$)}setFileListScrollOffset($){this.update({fileListScrollOffset:Math.max(0,$)}),this.emit("scroll-change",{type:"fileList",offset:$})}setDiffScrollOffset($){this.update({diffScrollOffset:Math.max(0,$)}),this.emit("scroll-change",{type:"diff",offset:$})}setHistoryScrollOffset($){this.update({historyScrollOffset:Math.max(0,$)}),this.emit("scroll-change",{type:"history",offset:$})}setCompareScrollOffset($){this.update({compareScrollOffset:Math.max(0,$)}),this.emit("scroll-change",{type:"compare",offset:$})}setExplorerScrollOffset($){this.update({explorerScrollOffset:Math.max(0,$)}),this.emit("scroll-change",{type:"explorer",offset:$})}setExplorerFileScrollOffset($){this.update({explorerFileScrollOffset:Math.max(0,$)}),this.emit("scroll-change",{type:"explorerFile",offset:$})}setHistorySelectedIndex($){this.update({historySelectedIndex:Math.max(0,$)})}setCompareSelectedIndex($){this.update({compareSelectedIndex:Math.max(0,$)})}toggleIncludeUncommitted(){this.update({includeUncommitted:!this._state.includeUncommitted})}setExplorerSelectedIndex($){this.update({explorerSelectedIndex:Math.max(0,$)})}setSelectedHunkIndex($){this.update({selectedHunkIndex:Math.max(0,$)})}clampSelectedHunkIndex($){if($<=0)this._state.selectedHunkIndex=0;else if(this._state.selectedHunkIndex>=$)this._state.selectedHunkIndex=$-1}toggleWrapMode(){this.update({wrapMode:!this._state.wrapMode,diffScrollOffset:0})}toggleAutoTab(){this.update({autoTabEnabled:!this._state.autoTabEnabled})}toggleMouse(){this.update({mouseEnabled:!this._state.mouseEnabled})}toggleHideHiddenFiles(){this.update({hideHiddenFiles:!this._state.hideHiddenFiles})}toggleHideGitignored(){this.update({hideGitignored:!this._state.hideGitignored})}toggleFlatViewMode(){this.update({flatViewMode:!this._state.flatViewMode,fileListScrollOffset:0})}adjustSplitRatio($){let J=Math.min(0.85,Math.max(0.15,this._state.splitRatio+$));this.update({splitRatio:J})}setSplitRatio($){this.update({splitRatio:Math.min(0.85,Math.max(0.15,$))})}openModal($){this.update({activeModal:$}),this.emit("modal-change",$)}closeModal(){this.update({activeModal:null}),this.emit("modal-change",null)}toggleModal($){if(this._state.activeModal===$)this.closeModal();else this.openModal($)}setPendingDiscard($){this.update({pendingDiscard:$})}setCommitInputFocused($){this.update({commitInputFocused:$})}togglePane(){let{bottomTab:$,currentPane:J}=this._state;if($==="diff"||$==="commit")this.setPane(J==="files"?"diff":"files");else if($==="history")this.setPane(J==="history"?"diff":"history");else if($==="compare")this.setPane(J==="compare"?"diff":"compare");else if($==="explorer")this.setPane(J==="explorer"?"diff":"explorer")}resetForNewRepo(){this._state={...this._state,selectedIndex:0,fileListScrollOffset:0,diffScrollOffset:0,historySelectedIndex:0,historyScrollOffset:0,compareSelectedIndex:0,compareScrollOffset:0,explorerSelectedIndex:0,explorerScrollOffset:0,explorerFileScrollOffset:0,selectedHunkIndex:0},this.emit("change",this._state)}}import*as I from"node:path";import*as m from"node:fs";import{execFileSync as g9}from"node:child_process";import{watch as B5}from"chokidar";import{EventEmitter as u9}from"node:events";import j5 from"ignore";class f0{queue=[];isProcessing=!1;pendingMutations=0;refreshScheduled=!1;enqueue($){return new Promise((J,Z)=>{this.queue.push({execute:$,resolve:J,reject:Z}),this.processNext()})}enqueueMutation($){return this.pendingMutations++,this.enqueue($).finally(()=>{this.pendingMutations--})}hasPendingMutations(){return this.pendingMutations>0}scheduleRefresh($){if(this.pendingMutations>0)return;if(this.refreshScheduled)return;this.refreshScheduled=!0,this.enqueue(async()=>{this.refreshScheduled=!1,await $()}).catch(()=>{this.refreshScheduled=!1})}isBusy(){return this.isProcessing||this.queue.length>0}async processNext(){if(this.isProcessing||this.queue.length===0)return;this.isProcessing=!0;let $=this.queue.shift();try{let J=await $.execute();$.resolve(J)}catch(J){$.reject(J instanceof Error?J:Error(String(J)))}finally{this.isProcessing=!1,this.processNext()}}}var _8=new Map;function h0($){let J=_8.get($);if(!J)J=new f0,_8.set($,J);return J}function c0($){_8.delete($)}import{simpleGit as P}from"simple-git";import{execFileSync as o0}from"node:child_process";import*as r0 from"node:fs";import*as a0 from"node:path";function d0($){let J=new Map;for(let Z of $.trim().split(`
45
+ `)){if(!Z)continue;let K=Z.split("\t");if(K.length>=3){let X=K[0]==="-"?0:parseInt(K[0],10),Q=K[1]==="-"?0:parseInt(K[1],10),q=K.slice(2).join("\t");J.set(q,{insertions:X,deletions:Q})}}return J}async function S9($,J){try{let Z=a0.join($,J);return(await r0.promises.readFile(Z,"utf-8")).split(`
46
+ `).filter((X)=>X.length>0).length}catch{return 0}}function l0($){switch($){case"M":return"modified";case"A":return"added";case"D":return"deleted";case"?":return"untracked";case"R":return"renamed";case"C":return"copied";default:return"modified"}}async function M8($){let J=P($);try{if(!await J.checkIsRepo())return{files:[],branch:{current:"",ahead:0,behind:0},isRepo:!1};let K=await J.status(),X=[],Q=new Set,q=K.files.filter((B)=>B.working_dir==="?").map((B)=>B.path),z=await Q$($,q);for(let B of K.files){if(B.index==="!"||B.working_dir==="!"||z.has(B.path))continue;let _=`${B.path}-${B.index!==" "&&B.index!=="?"}`;if(Q.has(_))continue;if(Q.add(_),B.index&&B.index!==" "&&B.index!=="?")X.push({path:B.path,status:l0(B.index),staged:!0});if(B.working_dir&&B.working_dir!==" ")X.push({path:B.path,status:B.working_dir==="?"?"untracked":l0(B.working_dir),staged:!1})}let[V,Y]=await Promise.all([J.diff(["--cached","--numstat"]).catch(()=>""),J.diff(["--numstat"]).catch(()=>"")]),U=d0(V),j=d0(Y);for(let B of X){let _=B.staged?U.get(B.path):j.get(B.path);if(_)B.insertions=_.insertions,B.deletions=_.deletions}let G=X.filter((B)=>B.status==="untracked");if(G.length>0){let B=await Promise.all(G.map((_)=>S9($,_.path)));for(let _=0;_<G.length;_++)G[_].insertions=B[_],G[_].deletions=0}return{files:X,branch:{current:K.current||"HEAD",tracking:K.tracking||void 0,ahead:K.ahead,behind:K.behind},isRepo:!0}}catch{return{files:[],branch:{current:"",ahead:0,behind:0},isRepo:!1}}}async function s0($,J){await P($).add(J)}async function n0($,J){await P($).reset(["HEAD","--",J])}async function i0($){await P($).add("-A")}async function t0($){await P($).reset(["HEAD"])}async function e0($,J){await P($).checkout(["--",J])}async function $5($,J,Z=!1){await P($).commit(J,void 0,Z?{"--amend":null}:void 0)}async function J5($){let J=P($);try{return(await J.log({n:1})).latest?.message||""}catch{return""}}function Z5($,J){o0("git",["apply","--cached","--unidiff-zero"],{cwd:$,input:J,encoding:"utf-8"})}function K5($,J){o0("git",["apply","--cached","--reverse","--unidiff-zero"],{cwd:$,input:J,encoding:"utf-8"})}async function X5($,J=50){let Z=P($);try{return(await Z.log({n:J})).all.map((X)=>({hash:X.hash,shortHash:X.hash.slice(0,7),message:X.message.split(`
47
+ `)[0],author:X.author_name,date:new Date(X.date),refs:X.refs||""}))}catch{return[]}}import{execSync as b9}from"node:child_process";import{simpleGit as q$}from"simple-git";function w9($){let J=$.match(/^@@ -(\d+)(?:,\d+)? \+(\d+)(?:,\d+)? @@/);if(J)return{oldStart:parseInt(J[1],10),newStart:parseInt(J[2],10)};return null}function S$($){let J=$.split(`
48
+ `);if(J.length>1&&J[J.length-1]==="")J.pop();let Z=[],K=0,X=0;for(let Q of J)if(Q.startsWith("diff --git")||Q.startsWith("index ")||Q.startsWith("---")||Q.startsWith("+++")||Q.startsWith("new file")||Q.startsWith("deleted file")||Q.startsWith("Binary files")||Q.startsWith("similarity index")||Q.startsWith("rename from")||Q.startsWith("rename to"))Z.push({type:"header",content:Q});else if(Q.startsWith("@@")){let q=w9(Q);if(q)K=q.oldStart,X=q.newStart;Z.push({type:"hunk",content:Q})}else if(Q.startsWith("+"))Z.push({type:"addition",content:Q,newLineNum:X++});else if(Q.startsWith("-"))Z.push({type:"deletion",content:Q,oldLineNum:K++});else Z.push({type:"context",content:Q,oldLineNum:K++,newLineNum:X++});return Z}function O8($,J){if(!$)return null;let Z=$.split(`
49
+ `),K=[],X=-1;for(let Y=0;Y<Z.length;Y++){if(Z[Y].startsWith("@@")){X=Y;break}K.push(Z[Y])}if(X===-1)return null;let Q=-1,q=-1;for(let Y=X;Y<Z.length;Y++)if(Z[Y].startsWith("@@")){if(Q++,Q===J){q=Y;break}}if(q===-1)return null;let z=[Z[q]];for(let Y=q+1;Y<Z.length;Y++){if(Z[Y].startsWith("@@")||Z[Y].startsWith("diff --git"))break;z.push(Z[Y])}while(z.length>1&&z[z.length-1]==="")z.pop();return[...K,...z].join(`
50
+ `)+`
51
+ `}function v8($){let J=new Map;if(!$)return J;let Z=null;for(let K of $.split(`
52
+ `))if(K.startsWith("diff --git")){let X=K.match(/^diff --git a\/.+ b\/(.+)$/);if(X){if(Z=X[1],!J.has(Z))J.set(Z,0)}}else if(K.startsWith("@@")&&Z)J.set(Z,(J.get(Z)??0)+1);return J}async function u($,J,Z=!1){let K=q$($);try{let X=[];if(Z)X.push("--cached");if(J)X.push("--",J);let Q=await K.diff(X),q=S$(Q);return{raw:Q,lines:q}}catch{return{raw:"",lines:[]}}}async function W8($,J){try{let Z=b9(`cat "${J}"`,{cwd:$,encoding:"utf-8"}),K=[{type:"header",content:`diff --git a/${J} b/${J}`},{type:"header",content:"new file mode 100644"},{type:"header",content:"--- /dev/null"},{type:"header",content:`+++ b/${J}`}],X=Z.split(`
53
+ `);K.push({type:"hunk",content:`@@ -0,0 +1,${X.length} @@`});let Q=1;for(let z of X)K.push({type:"addition",content:"+"+z,newLineNum:Q++});return{raw:K.map((z)=>z.content).join(`
54
+ `),lines:K}}catch{return{raw:"",lines:[]}}}async function Q5($){return u($,void 0,!0)}async function A8($){let J=q$($),Z=new Set,K=[];try{let X=await J.raw(["log","--oneline","--decorate=short","--all","-n","200"]),Q=/\(([^)]+)\)/g;for(let q of X.split(`
55
+ `)){let z=Q.exec(q);if(z){let V=z[1].split(",").map((Y)=>Y.trim());for(let Y of V){if(Y.startsWith("HEAD")||Y.startsWith("tag:")||!Y.includes("/"))continue;let U=Y.replace(/^.*-> /,"");if(U.includes("/")&&!Z.has(U))Z.add(U),K.push(U)}}Q.lastIndex=0}if(K.length>0)K.sort((q,z)=>{let V=q.split("/").slice(1).join("/"),Y=z.split("/").slice(1).join("/"),U=V==="main"||V==="master",j=Y==="main"||Y==="master";if(U&&!j)return-1;if(!U&&j)return 1;if(U&&j){let G=q.startsWith("origin/"),B=z.startsWith("origin/");if(G&&!B)return 1;if(!G&&B)return-1}return 0})}catch{}return[...new Set(K)]}async function q5($){return(await A8($))[0]??null}async function D8($,J){let Z=q$($),X=(await Z.raw(["merge-base",J,"HEAD"])).trim(),Q=await Z.raw(["diff","--numstat",`${X}...HEAD`]),q=await Z.raw(["diff","--name-status",`${X}...HEAD`]),z=await Z.raw(["diff",`${X}...HEAD`]),V=Q.trim().split(`
56
+ `).filter((M)=>M),Y=new Map;for(let M of V){let O=M.split("\t");if(O.length>=3){let D=O[0]==="-"?0:parseInt(O[0],10),R=O[1]==="-"?0:parseInt(O[1],10),N=O.slice(2).join("\t");Y.set(N,{additions:D,deletions:R})}}let U=q.trim().split(`
57
+ `).filter((M)=>M),j=new Map;for(let M of U){let O=M.split("\t");if(O.length>=2){let D=O[0][0],R=O[O.length-1],N;switch(D){case"A":N="added";break;case"D":N="deleted";break;case"R":N="renamed";break;default:N="modified"}j.set(R,N)}}let G=[],B=z.split(/(?=^diff --git )/m).filter((M)=>M.trim());for(let M of B){let O=M.match(/^diff --git a\/.+ b\/(.+)$/m);if(!O)continue;let D=O[1],R=S$(M),N=Y.get(D)||{additions:0,deletions:0},E=j.get(D)||"modified";G.push({path:D,status:E,additions:N.additions,deletions:N.deletions,diff:{raw:M,lines:R}})}let _=0,v=0;for(let M of G)_+=M.additions,v+=M.deletions;let A=(await Z.status()).files.length,H=(await Z.log({from:X,to:"HEAD"})).all.map((M)=>({hash:M.hash,shortHash:M.hash.slice(0,7),message:M.message.split(`
58
+ `)[0],author:M.author_name,date:new Date(M.date),refs:M.refs||""}));return G.sort((M,O)=>M.path.localeCompare(O.path)),{baseBranch:J,stats:{filesChanged:G.length,additions:_,deletions:v},files:G,commits:H,uncommittedCount:A}}async function T8($,J){let Z=q$($);try{let K=await Z.raw(["show",J,"--format="]),X=S$(K);return{raw:K,lines:X}}catch{return{raw:"",lines:[]}}}async function z5($,J){let Z=q$($),K=await D8($,J),X=await Z.diff(["--cached","--numstat"]),Q=await Z.diff(["--numstat"]),q=await Z.diff(["--cached"]),z=await Z.diff([]),V=new Map;for(let M of X.trim().split(`
59
+ `).filter((O)=>O)){let O=M.split("\t");if(O.length>=3){let D=O[0]==="-"?0:parseInt(O[0],10),R=O[1]==="-"?0:parseInt(O[1],10),N=O.slice(2).join("\t");V.set(N,{additions:D,deletions:R,staged:!0,unstaged:!1})}}for(let M of Q.trim().split(`
60
+ `).filter((O)=>O)){let O=M.split("\t");if(O.length>=3){let D=O[0]==="-"?0:parseInt(O[0],10),R=O[1]==="-"?0:parseInt(O[1],10),N=O.slice(2).join("\t"),E=V.get(N);if(E)E.additions+=D,E.deletions+=R,E.unstaged=!0;else V.set(N,{additions:D,deletions:R,staged:!1,unstaged:!0})}}let Y=await Z.status(),U=new Map;for(let M of Y.files)if(M.index==="A"||M.working_dir==="?")U.set(M.path,"added");else if(M.index==="D"||M.working_dir==="D")U.set(M.path,"deleted");else if(M.index==="R")U.set(M.path,"renamed");else U.set(M.path,"modified");let j=[],B=(q+z).split(/(?=^diff --git )/m).filter((M)=>M.trim()),_=new Set;for(let M of B){let O=M.match(/^diff --git a\/.+ b\/(.+)$/m);if(!O)continue;let D=O[1];if(_.has(D))continue;_.add(D);let R=S$(M),N=V.get(D)||{additions:0,deletions:0},E=U.get(D)||"modified";j.push({path:D,status:E,additions:N.additions,deletions:N.deletions,diff:{raw:M,lines:R},isUncommitted:!0})}let v=new Set(K.files.map((M)=>M.path)),W=[];for(let M of K.files){let O=j.find((D)=>D.path===M.path);if(O)W.push(M),W.push(O);else W.push(M)}for(let M of j)if(!v.has(M.path))W.push(M);let A=0,T=0,H=new Set;for(let M of W)H.add(M.path),A+=M.additions,T+=M.deletions;return W.sort((M,O)=>M.path.localeCompare(O.path)),{baseBranch:K.baseBranch,stats:{filesChanged:H.size,additions:A,deletions:T},files:W,commits:K.commits,uncommittedCount:K.uncommittedCount}}import*as S from"node:fs";import*as r from"node:path";import*as V5 from"node:os";var b$=r.join(V5.homedir(),".cache","diffstalker","base-branches.json");function x9(){let $=r.dirname(b$);if(!S.existsSync($))S.mkdirSync($,{recursive:!0})}function Y5(){try{if(S.existsSync(b$))return JSON.parse(S.readFileSync(b$,"utf-8"))}catch{}return{}}function p9($){x9(),S.writeFileSync(b$,JSON.stringify($,null,2)+`
61
+ `)}function U5($){let J=Y5(),Z=r.resolve($);return J[Z]}function G5($,J){let Z=Y5(),K=r.resolve($);Z[K]=J,p9(Z)}class _5 extends u9{repoPath;queue;gitWatcher=null;workingDirWatcher=null;ignorers=new Map;diffDebounceTimer=null;_state={status:null,diff:null,combinedFileDiffs:null,selectedFile:null,isLoading:!1,error:null,hunkCounts:null};_compareState={compareDiff:null,compareBaseBranch:null,compareLoading:!1,compareError:null};_historyState={commits:[],selectedCommit:null,commitDiff:null,isLoading:!1};_compareSelectionState={type:null,index:0,diff:null};constructor($){super();this.repoPath=$,this.queue=h0($)}get state(){return this._state}get compareState(){return this._compareState}get historyState(){return this._historyState}get compareSelectionState(){return this._compareSelectionState}updateState($){this._state={...this._state,...$},this.emit("state-change",this._state)}updateCompareState($){this._compareState={...this._compareState,...$},this.emit("compare-state-change",this._compareState)}updateHistoryState($){this._historyState={...this._historyState,...$},this.emit("history-state-change",this._historyState)}updateCompareSelectionState($){this._compareSelectionState={...this._compareSelectionState,...$},this.emit("compare-selection-change",this._compareSelectionState)}loadGitignores(){let $=new Map,J=j5();J.add(".git");let Z=I.join(this.repoPath,".gitignore");if(m.existsSync(Z))J.add(m.readFileSync(Z,"utf-8"));let K=I.join(this.repoPath,".git","info","exclude");if(m.existsSync(K))J.add(m.readFileSync(K,"utf-8"));$.set("",J);try{let X=g9("git",["ls-files","-z","--cached","--others","**/.gitignore"],{cwd:this.repoPath,encoding:"utf-8"});for(let Q of X.split("\x00")){if(!Q||Q===".gitignore")continue;if(!Q.endsWith(".gitignore"))continue;let q=I.dirname(Q),z=I.join(this.repoPath,Q);try{let V=m.readFileSync(z,"utf-8"),Y=j5();Y.add(V),$.set(q,Y)}catch{}}}catch{}return $}startWatching(){let $=I.join(this.repoPath,".git");if(!m.existsSync($))return;let J=I.join($,"index"),Z=I.join($,"HEAD"),K=I.join($,"refs"),X=I.join(this.repoPath,".gitignore");this.gitWatcher=B5([J,Z,K,X],{persistent:!0,ignoreInitial:!0,usePolling:!0,interval:100}),this.ignorers=this.loadGitignores(),this.workingDirWatcher=B5(this.repoPath,{persistent:!0,ignoreInitial:!0,ignored:(q)=>{let z=I.relative(this.repoPath,q);if(!z)return!1;let V=z.split("/");for(let Y=0;Y<V.length;Y++){let U=Y===0?"":V.slice(0,Y).join("/"),j=this.ignorers.get(U);if(j){let G=Y===0?z:V.slice(Y).join("/");if(j.ignores(G))return!0}}return!1},awaitWriteFinish:{stabilityThreshold:100,pollInterval:50}});let Q=()=>this.scheduleRefresh();this.gitWatcher.on("change",(q)=>{if(q===X)this.ignorers=this.loadGitignores();Q()}),this.gitWatcher.on("add",Q),this.gitWatcher.on("unlink",Q),this.gitWatcher.on("error",(q)=>{let z=q instanceof Error?q.message:String(q);this.emit("error",`Git watcher error: ${z}`)}),this.workingDirWatcher.on("change",Q),this.workingDirWatcher.on("add",Q),this.workingDirWatcher.on("unlink",Q),this.workingDirWatcher.on("error",(q)=>{let z=q instanceof Error?q.message:String(q);this.emit("error",`Working dir watcher error: ${z}`)})}dispose(){if(this.diffDebounceTimer)clearTimeout(this.diffDebounceTimer);this.gitWatcher?.close(),this.workingDirWatcher?.close(),c0(this.repoPath)}scheduleRefresh(){this.queue.scheduleRefresh(async()=>{if(await this.doRefresh(),this._historyState.commits.length>0)await this.doLoadHistory();if(this._compareState.compareBaseBranch)await this.doRefreshCompareDiff(!1)})}scheduleStatusRefresh(){this.queue.scheduleRefresh(async()=>{let $=await M8(this.repoPath);if(!$.isRepo){this.updateState({status:$,diff:null,isLoading:!1,error:"Not a git repository"});return}this.updateState({status:$,isLoading:!1})})}async refresh(){await this.queue.enqueue(()=>this.doRefresh())}async doRefresh(){this.updateState({isLoading:!0,error:null});try{let $=await M8(this.repoPath);if(!$.isRepo){this.updateState({status:$,diff:null,isLoading:!1,error:"Not a git repository"});return}let[J,Z]=await Promise.all([u(this.repoPath,void 0,!1),u(this.repoPath,void 0,!0)]),K={unstaged:v8(J.raw),staged:v8(Z.raw)},{displayDiff:X,combinedFileDiffs:Q}=await this.resolveFileDiffs($,J);this.updateState({status:$,diff:X,combinedFileDiffs:Q,hunkCounts:K,isLoading:!1})}catch($){this.updateState({isLoading:!1,error:$ instanceof Error?$.message:"Unknown error"})}}async resolveFileDiffs($,J){let Z=this._state.selectedFile;if(!Z)return{displayDiff:J,combinedFileDiffs:null};let K=$.files.find((z)=>z.path===Z.path&&z.staged===Z.staged)??$.files.find((z)=>z.path===Z.path);if(!K)return this.updateState({selectedFile:null}),{displayDiff:J,combinedFileDiffs:null};if(K.status==="untracked"){let z=await W8(this.repoPath,K.path);return{displayDiff:z,combinedFileDiffs:{unstaged:z,staged:{raw:"",lines:[]}}}}let[X,Q]=await Promise.all([u(this.repoPath,K.path,!1),u(this.repoPath,K.path,!0)]);return{displayDiff:K.staged?Q:X,combinedFileDiffs:{unstaged:X,staged:Q}}}selectFile($){if(this.updateState({selectedFile:$}),!this._state.status?.isRepo)return;if(this.diffDebounceTimer)clearTimeout(this.diffDebounceTimer),this.diffDebounceTimer=setTimeout(()=>{this.diffDebounceTimer=null,this.fetchDiffForSelection()},20);else this.fetchDiffForSelection(),this.diffDebounceTimer=setTimeout(()=>{this.diffDebounceTimer=null},20)}fetchDiffForSelection(){let $=this._state.selectedFile;this.queue.enqueue(async()=>{if($!==this._state.selectedFile)return;await this.doFetchDiffForFile($)}).catch((J)=>{this.updateState({error:`Failed to load diff: ${J instanceof Error?J.message:String(J)}`})})}async doFetchDiffForFile($){if(!$){let K=await Q5(this.repoPath);if(this._state.selectedFile===null)this.updateState({diff:K,combinedFileDiffs:null});return}if($.status==="untracked"){let K=await W8(this.repoPath,$.path);if($===this._state.selectedFile)this.updateState({diff:K,combinedFileDiffs:{unstaged:K,staged:{raw:"",lines:[]}}});return}let[J,Z]=await Promise.all([u(this.repoPath,$.path,!1),u(this.repoPath,$.path,!0)]);if($===this._state.selectedFile){let K=$.staged?Z:J;this.updateState({diff:K,combinedFileDiffs:{unstaged:J,staged:Z}})}}async stage($){try{await this.queue.enqueueMutation(()=>s0(this.repoPath,$.path)),this.scheduleStatusRefresh()}catch(J){await this.refresh(),this.updateState({error:`Failed to stage ${$.path}: ${J instanceof Error?J.message:String(J)}`})}}async unstage($){try{await this.queue.enqueueMutation(()=>n0(this.repoPath,$.path)),this.scheduleStatusRefresh()}catch(J){await this.refresh(),this.updateState({error:`Failed to unstage ${$.path}: ${J instanceof Error?J.message:String(J)}`})}}async stageHunk($){try{await this.queue.enqueueMutation(async()=>Z5(this.repoPath,$)),this.scheduleRefresh()}catch(J){await this.refresh(),this.updateState({error:`Failed to stage hunk: ${J instanceof Error?J.message:String(J)}`})}}async unstageHunk($){try{await this.queue.enqueueMutation(async()=>K5(this.repoPath,$)),this.scheduleRefresh()}catch(J){await this.refresh(),this.updateState({error:`Failed to unstage hunk: ${J instanceof Error?J.message:String(J)}`})}}async discard($){if($.staged||$.status==="untracked")return;try{await this.queue.enqueueMutation(()=>e0(this.repoPath,$.path)),await this.refresh()}catch(J){this.updateState({error:`Failed to discard ${$.path}: ${J instanceof Error?J.message:String(J)}`})}}async stageAll(){try{await this.queue.enqueueMutation(()=>i0(this.repoPath)),await this.refresh()}catch($){this.updateState({error:`Failed to stage all: ${$ instanceof Error?$.message:String($)}`})}}async unstageAll(){try{await this.queue.enqueueMutation(()=>t0(this.repoPath)),await this.refresh()}catch($){this.updateState({error:`Failed to unstage all: ${$ instanceof Error?$.message:String($)}`})}}async commit($,J=!1){try{await this.queue.enqueue(()=>$5(this.repoPath,$,J)),await this.refresh()}catch(Z){this.updateState({error:`Failed to commit: ${Z instanceof Error?Z.message:String(Z)}`})}}async getHeadCommitMessage(){return this.queue.enqueue(()=>J5(this.repoPath))}async refreshCompareDiff($=!1){this.updateCompareState({compareLoading:!0,compareError:null});try{await this.queue.enqueue(()=>this.doRefreshCompareDiff($))}catch(J){this.updateCompareState({compareLoading:!1,compareError:`Failed to load compare diff: ${J instanceof Error?J.message:String(J)}`})}}async doRefreshCompareDiff($){let J=this._compareState.compareBaseBranch;if(!J)J=U5(this.repoPath)??await q5(this.repoPath),this.updateCompareState({compareBaseBranch:J});if(J){let Z=$?await z5(this.repoPath,J):await D8(this.repoPath,J);this.updateCompareState({compareDiff:Z,compareLoading:!1})}else this.updateCompareState({compareDiff:null,compareLoading:!1,compareError:"No base branch found"})}async getCandidateBaseBranches(){return A8(this.repoPath)}async setCompareBaseBranch($,J=!1){this.updateCompareState({compareBaseBranch:$}),G5(this.repoPath,$),await this.refreshCompareDiff(J)}async loadHistory($=100){this.updateHistoryState({isLoading:!0});try{await this.queue.enqueue(()=>this.doLoadHistory($))}catch(J){this.updateHistoryState({isLoading:!1}),this.updateState({error:`Failed to load history: ${J instanceof Error?J.message:String(J)}`})}}async doLoadHistory($=100){let J=await X5(this.repoPath,$);this.updateHistoryState({commits:J,isLoading:!1})}async selectHistoryCommit($){if(this.updateHistoryState({selectedCommit:$,commitDiff:null}),!$)return;try{await this.queue.enqueue(async()=>{let J=await T8(this.repoPath,$.hash);this.updateHistoryState({commitDiff:J})})}catch(J){this.updateState({error:`Failed to load commit diff: ${J instanceof Error?J.message:String(J)}`})}}async selectCompareCommit($){let J=this._compareState.compareDiff;if(!J||$<0||$>=J.commits.length){this.updateCompareSelectionState({type:null,index:0,diff:null});return}let Z=J.commits[$];this.updateCompareSelectionState({type:"commit",index:$,diff:null});try{await this.queue.enqueue(async()=>{let K=await T8(this.repoPath,Z.hash);this.updateCompareSelectionState({diff:K})})}catch(K){this.updateState({error:`Failed to load commit diff: ${K instanceof Error?K.message:String(K)}`})}}selectCompareFile($){let J=this._compareState.compareDiff;if(!J||$<0||$>=J.files.length){this.updateCompareSelectionState({type:null,index:0,diff:null});return}let Z=J.files[$];this.updateCompareSelectionState({type:"file",index:$,diff:Z.diff})}}var w$=new Map;function M5($){let J=w$.get($);if(!J)J=new _5($),w$.set($,J);return J}function N8($){let J=w$.get($);if(J)J.dispose(),w$.delete($)}class H8{screen;layout;uiState;gitManager=null;followMode=null;explorerManager=null;config;commandServer;repoPath;currentTheme;commitFlowState;commitTextarea=null;activeModal=null;bottomPaneTotalRows=0;bottomPaneHunkCount=0;bottomPaneHunkBoundaries=[];pendingSelectionAnchor=null;cachedFlatFiles=[];pendingFlatSelectionPath=null;pendingHunkIndex=null;combinedHunkMapping=[];constructor($){this.config=$.config,this.commandServer=$.commandServer??null,this.repoPath=$.initialPath??process.cwd(),this.currentTheme=$.config.theme,this.uiState=new j8({splitRatio:$.config.splitRatio??0.4}),this.screen=O5.screen({smartCSR:!0,fullUnicode:!0,title:"diffstalker",mouse:!0,terminal:"xterm-256color"});let J=this.screen;if(J.tput)J.tput.colors=256;if(J.program?.tput)J.program.tput.colors=256;if(this.layout=new p$(this.screen,this.uiState.state.splitRatio),this.screen.on("resize",()=>{setImmediate(()=>this.render())}),this.commitFlowState=new B8({getHeadMessage:()=>this.gitManager?.getHeadCommitMessage()??Promise.resolve(""),onCommit:async(Z,K)=>{await this.gitManager?.commit(Z,K)},onSuccess:()=>{this.uiState.setTab("diff"),this.render()}}),this.commitTextarea=O5.textarea({parent:this.layout.bottomPane,top:3,left:1,width:"100%-4",height:1,inputOnFocus:!0,hidden:!0,style:{fg:"white",bg:"default"}}),this.commitTextarea.on("submit",()=>{this.commitFlowState.submit()}),this.commitTextarea.on("keypress",()=>{setImmediate(()=>{let Z=this.commitTextarea?.getValue()??"";this.commitFlowState.setMessage(Z)})}),this.setupKeyboardHandlers(),this.setupMouseEventHandlers(),this.setupStateListeners(),this.config.watcherEnabled)this.followMode=new C$(this.config.targetFile,()=>this.repoPath,{onRepoChange:(Z,K)=>this.handleFollowRepoChange(Z,K),onFileNavigate:(Z)=>this.handleFollowFileNavigate(Z)}),this.followMode.start();if(this.commandServer)this.setupCommandHandler();this.initGitManager(),this.render()}setupKeyboardHandlers(){P8(this.screen,{exit:()=>this.exit(),navigateDown:()=>this.navigateDown(),navigateUp:()=>this.navigateUp(),stageSelected:()=>this.stageSelected(),unstageSelected:()=>this.unstageSelected(),stageAll:()=>this.stageAll(),unstageAll:()=>this.unstageAll(),toggleSelected:()=>this.toggleSelected(),enterExplorerDirectory:()=>this.enterExplorerDirectory(),goExplorerUp:()=>this.goExplorerUp(),openFileFinder:()=>this.openFileFinder(),focusCommitInput:()=>this.focusCommitInput(),unfocusCommitInput:()=>this.unfocusCommitInput(),refresh:()=>this.refresh(),toggleMouseMode:()=>this.toggleMouseMode(),toggleFollow:()=>this.toggleFollow(),showDiscardConfirm:($)=>this.showDiscardConfirm($),render:()=>this.render(),toggleCurrentHunk:()=>this.toggleCurrentHunk(),navigateNextHunk:()=>this.navigateNextHunk(),navigatePrevHunk:()=>this.navigatePrevHunk()},{hasActiveModal:()=>this.activeModal!==null,getBottomTab:()=>this.uiState.state.bottomTab,getCurrentPane:()=>this.uiState.state.currentPane,isCommitInputFocused:()=>this.commitFlowState.state.inputFocused,getStatusFiles:()=>this.gitManager?.state.status?.files??[],getSelectedIndex:()=>this.uiState.state.selectedIndex,uiState:this.uiState,getExplorerManager:()=>this.explorerManager,commitFlowState:this.commitFlowState,getGitManager:()=>this.gitManager,layout:this.layout,getCachedFlatFiles:()=>this.cachedFlatFiles})}setupMouseEventHandlers(){F0(this.layout,{selectHistoryCommitByIndex:($)=>this.selectHistoryCommitByIndex($),selectCompareItem:($)=>this.selectCompareItem($),selectFileByIndex:($)=>this.selectFileByIndex($),toggleFileByIndex:($)=>this.toggleFileByIndex($),enterExplorerDirectory:()=>this.enterExplorerDirectory(),toggleMouseMode:()=>this.toggleMouseMode(),toggleFollow:()=>this.toggleFollow(),selectHunkAtRow:($)=>this.selectHunkAtRow($),render:()=>this.render()},{uiState:this.uiState,getExplorerManager:()=>this.explorerManager,getStatusFiles:()=>this.gitManager?.state.status?.files??[],getHistoryCommitCount:()=>this.gitManager?.historyState.commits.length??0,getCompareCommits:()=>this.gitManager?.compareState?.compareDiff?.commits??[],getCompareFiles:()=>this.gitManager?.compareState?.compareDiff?.files??[],getBottomPaneTotalRows:()=>this.bottomPaneTotalRows,getScreenWidth:()=>this.screen.width||80,getCachedFlatFiles:()=>this.cachedFlatFiles})}async toggleFlatEntry($){if(this.pendingFlatSelectionPath=$.path,$.stagingState==="staged"){if($.stagedEntry)await this.gitManager?.unstage($.stagedEntry)}else if($.unstagedEntry)await this.gitManager?.stage($.unstagedEntry)}async toggleFileByIndex($){if(this.uiState.state.flatViewMode){let J=w(this.cachedFlatFiles,$);if(J)await this.toggleFlatEntry(J)}else{let J=this.gitManager?.state.status?.files??[],Z=b(J,$);if(Z)if(this.pendingSelectionAnchor=s(J,this.uiState.state.selectedIndex),Z.staged)await this.gitManager?.unstage(Z);else await this.gitManager?.stage(Z)}}setupStateListeners(){this.uiState.on("change",()=>{this.render()}),this.uiState.on("tab-change",(J)=>{if(J!=="diff")this.uiState.setSelectedHunkIndex(0);if(J==="history")this.gitManager?.loadHistory();else if(J==="compare")this.gitManager?.refreshCompareDiff(this.uiState.state.includeUncommitted);else if(J==="explorer"){if(!this.explorerManager?.state.displayRows.length)this.explorerManager?.loadDirectory("")}}),this.uiState.on("modal-change",(J)=>{if(this.activeModal)this.activeModal=null;if(J==="theme")this.activeModal=new z8(this.screen,this.currentTheme,(Z)=>{this.currentTheme=Z,Z8({theme:Z}),this.activeModal=null,this.uiState.closeModal(),this.render()},()=>{this.activeModal=null,this.uiState.closeModal()}),this.activeModal.focus();else if(J==="hotkeys")this.activeModal=new V8(this.screen,()=>{this.activeModal=null,this.uiState.closeModal()}),this.activeModal.focus();else if(J==="baseBranch")this.gitManager?.getCandidateBaseBranches().then((Z)=>{let K=this.gitManager?.compareState.compareBaseBranch??null;this.activeModal=new Y8(this.screen,Z,K,(X)=>{this.activeModal=null,this.uiState.closeModal();let Q=this.uiState.state.includeUncommitted;this.gitManager?.setCompareBaseBranch(X,Q)},()=>{this.activeModal=null,this.uiState.closeModal()}),this.activeModal.focus()})});let $=null;this.uiState.on("change",(J)=>{if($)clearTimeout($);$=setTimeout(()=>{if(J.splitRatio!==this.config.splitRatio)Z8({splitRatio:J.splitRatio})},500)})}handleFollowRepoChange($,J){let Z=this.repoPath;this.repoPath=$,this.initGitManager(Z),this.resetRepoSpecificState(),this.loadCurrentTabData(),this.render()}handleFollowFileNavigate($){this.navigateToFile($),this.render()}initGitManager($){if(this.gitManager)this.gitManager.removeAllListeners(),N8($??this.repoPath);this.gitManager=M5(this.repoPath),this.gitManager.on("state-change",()=>{if(!this.gitManager?.state.isLoading)this.reconcileSelectionAfterStateChange();this.updateExplorerGitStatus(),this.render()}),this.gitManager.on("history-state-change",(J)=>{if(J.commits.length>0&&!J.selectedCommit){let Z=this.uiState.state;if(Z.bottomTab==="history")this.selectHistoryCommitByIndex(Z.historySelectedIndex)}this.render()}),this.gitManager.on("compare-state-change",()=>{this.render()}),this.gitManager.on("compare-selection-change",()=>{this.render()}),this.gitManager.startWatching(),this.gitManager.refresh(),this.initExplorerManager()}reconcileSelectionAfterStateChange(){let $=this.gitManager?.state.status?.files??[];if(this.uiState.state.flatViewMode&&this.pendingFlatSelectionPath){let J=M$($,this.gitManager?.state.hunkCounts??null),Z=this.pendingFlatSelectionPath;this.pendingFlatSelectionPath=null;let K=y8(J,Z);if(K>=0)this.uiState.setSelectedIndex(K),this.selectFileByIndex(K);else if(J.length>0){let X=Math.min(this.uiState.state.selectedIndex,J.length-1);this.uiState.setSelectedIndex(X),this.selectFileByIndex(X)}return}if(this.pendingSelectionAnchor){let J=this.pendingSelectionAnchor;this.pendingSelectionAnchor=null;let Z=L8($,J.category,J.categoryIndex);this.uiState.setSelectedIndex(Z),this.selectFileByIndex(Z);return}if(this.uiState.state.flatViewMode){let Z=M$($,this.gitManager?.state.hunkCounts??null).length-1;if(Z>=0&&this.uiState.state.selectedIndex>Z)this.uiState.setSelectedIndex(Z)}else if($.length>0){let J=$.length-1;if(this.uiState.state.selectedIndex>J)this.uiState.setSelectedIndex(J)}}initExplorerManager(){if(this.explorerManager)this.explorerManager.dispose();let $={hideHidden:!0,hideGitignored:!0,showOnlyChanges:!1};this.explorerManager=new q8(this.repoPath,$),this.explorerManager.on("state-change",()=>{this.render()}),this.explorerManager.loadDirectory(""),this.updateExplorerGitStatus()}updateExplorerGitStatus(){if(!this.explorerManager||!this.gitManager)return;let $=this.gitManager.state.status?.files??[],J={files:new Map,directories:new Set};for(let Z of $){J.files.set(Z.path,{status:Z.status,staged:Z.staged});let K=Z.path.split("/"),X="";for(let Q=0;Q<K.length-1;Q++)X=X?`${X}/${K[Q]}`:K[Q],J.directories.add(X);J.directories.add("")}this.explorerManager.setGitStatus(J)}resetRepoSpecificState(){this.compareSelection=null,this.uiState.resetForNewRepo()}loadCurrentTabData(){let $=this.uiState.state.bottomTab;if($==="history")this.gitManager?.loadHistory();else if($==="compare")this.gitManager?.refreshCompareDiff(this.uiState.state.includeUncommitted)}setupCommandHandler(){if(!this.commandServer)return;let $={navigateUp:()=>this.navigateUp(),navigateDown:()=>this.navigateDown(),switchTab:(J)=>this.uiState.setTab(J),togglePane:()=>this.uiState.togglePane(),stage:async()=>this.stageSelected(),unstage:async()=>this.unstageSelected(),stageAll:async()=>this.stageAll(),unstageAll:async()=>this.unstageAll(),commit:async(J)=>this.commit(J),refresh:async()=>this.refresh(),getState:()=>this.getAppState(),quit:()=>this.exit()};this.commandServer.setHandler($),this.commandServer.notifyReady()}getAppState(){let $=this.uiState.state,J=this.gitManager?.state,Z=this.gitManager?.historyState,K=J?.status?.files??[],X=Z?.commits??[];return{currentTab:$.bottomTab,currentPane:$.currentPane,selectedIndex:$.selectedIndex,totalFiles:K.length,stagedCount:K.filter((Q)=>Q.staged).length,files:K.map((Q)=>({path:Q.path,status:Q.status,staged:Q.staged})),historySelectedIndex:$.historySelectedIndex,historyCommitCount:X.length,compareSelectedIndex:$.compareSelectedIndex,compareTotalItems:0,includeUncommitted:$.includeUncommitted,explorerPath:this.repoPath,explorerSelectedIndex:$.explorerSelectedIndex,explorerItemCount:0,wrapMode:$.wrapMode,mouseEnabled:$.mouseEnabled,autoTabEnabled:$.autoTabEnabled}}scrollActiveDiffPane($){let J=this.uiState.state;if(J.bottomTab==="explorer"){let Z=Math.max(0,J.explorerFileScrollOffset+$);this.uiState.setExplorerFileScrollOffset(Z)}else{let Z=Math.max(0,J.diffScrollOffset+$);this.uiState.setDiffScrollOffset(Z)}}navigateFileList($){let J=this.uiState.state,Z=this.gitManager?.state.status?.files??[],K=J.flatViewMode?this.cachedFlatFiles.length-1:Z.length-1;if(K<0)return;let X=$===-1?Math.max(0,J.selectedIndex-1):Math.min(K,J.selectedIndex+1);this.uiState.setSelectedIndex(X),this.selectFileByIndex(X);let Q=J.flatViewMode?X+1:C8(X,Z);this.scrollToKeepRowVisible(Q,$,J.fileListScrollOffset)}scrollToKeepRowVisible($,J,Z){if(J===-1&&$<Z)this.uiState.setFileListScrollOffset($);else if(J===1){let K=Z+this.layout.dimensions.topPaneHeight-1;if($>=K)this.uiState.setFileListScrollOffset(Z+($-K+1))}}navigateActiveList($){let J=this.uiState.state.bottomTab;if(J==="history")if($===-1)this.navigateHistoryUp();else this.navigateHistoryDown();else if(J==="compare")if($===-1)this.navigateCompareUp();else this.navigateCompareDown();else if(J==="explorer")if($===-1)this.navigateExplorerUp();else this.navigateExplorerDown();else this.navigateFileList($)}navigateUp(){if(this.uiState.state.currentPane!=="diff")this.navigateActiveList(-1);else this.scrollActiveDiffPane(-3)}navigateDown(){if(this.uiState.state.currentPane!=="diff")this.navigateActiveList(1);else this.scrollActiveDiffPane(3)}navigateHistoryUp(){let $=this.uiState.state,J=Math.max(0,$.historySelectedIndex-1);if(J!==$.historySelectedIndex){if(this.uiState.setHistorySelectedIndex(J),J<$.historyScrollOffset)this.uiState.setHistoryScrollOffset(J);this.selectHistoryCommitByIndex(J)}}navigateHistoryDown(){let $=this.uiState.state,J=this.gitManager?.historyState.commits??[],Z=Math.min(J.length-1,$.historySelectedIndex+1);if(Z!==$.historySelectedIndex){this.uiState.setHistorySelectedIndex(Z);let K=$.historyScrollOffset+this.layout.dimensions.topPaneHeight-1;if(Z>=K)this.uiState.setHistoryScrollOffset($.historyScrollOffset+1);this.selectHistoryCommitByIndex(Z)}}selectHistoryCommitByIndex($){let J=this.gitManager?.historyState.commits??[],Z=p8(J,$);if(Z)this.uiState.setDiffScrollOffset(0),this.gitManager?.selectHistoryCommit(Z)}compareSelection=null;navigateCompareUp(){let $=this.gitManager?.compareState,J=$?.compareDiff?.commits??[],Z=$?.compareDiff?.files??[];if(J.length===0&&Z.length===0)return;let K=l$(this.compareSelection,J,Z,"up");if(K&&(K.type!==this.compareSelection?.type||K.index!==this.compareSelection?.index)){this.selectCompareItem(K);let X=this.uiState.state,Q=W$(K,J,Z);if(Q<X.compareScrollOffset)this.uiState.setCompareScrollOffset(Q)}}navigateCompareDown(){let $=this.gitManager?.compareState,J=$?.compareDiff?.commits??[],Z=$?.compareDiff?.files??[];if(J.length===0&&Z.length===0)return;if(!this.compareSelection){if(J.length>0)this.selectCompareItem({type:"commit",index:0});else if(Z.length>0)this.selectCompareItem({type:"file",index:0});return}let K=l$(this.compareSelection,J,Z,"down");if(K&&(K.type!==this.compareSelection?.type||K.index!==this.compareSelection?.index)){this.selectCompareItem(K);let X=this.uiState.state,Q=W$(K,J,Z),q=X.compareScrollOffset+this.layout.dimensions.topPaneHeight-1;if(Q>=q)this.uiState.setCompareScrollOffset(X.compareScrollOffset+(Q-q+1))}}selectCompareItem($){if(this.compareSelection=$,this.uiState.setDiffScrollOffset(0),$.type==="commit")this.gitManager?.selectCompareCommit($.index);else this.gitManager?.selectCompareFile($.index)}navigateExplorerUp(){let $=this.uiState.state;if((this.explorerManager?.state.displayRows??[]).length===0)return;let Z=this.explorerManager?.navigateUp($.explorerScrollOffset);if(Z!==null&&Z!==void 0)this.uiState.setExplorerScrollOffset(Z);this.uiState.setExplorerSelectedIndex(this.explorerManager?.state.selectedIndex??0)}navigateExplorerDown(){let $=this.uiState.state;if((this.explorerManager?.state.displayRows??[]).length===0)return;let Z=this.layout.dimensions.topPaneHeight,K=this.explorerManager?.navigateDown($.explorerScrollOffset,Z);if(K!==null&&K!==void 0)this.uiState.setExplorerScrollOffset(K);this.uiState.setExplorerSelectedIndex(this.explorerManager?.state.selectedIndex??0)}async enterExplorerDirectory(){await this.explorerManager?.enterDirectory(),this.uiState.setExplorerFileScrollOffset(0),this.uiState.setExplorerSelectedIndex(this.explorerManager?.state.selectedIndex??0)}async goExplorerUp(){await this.explorerManager?.goUp(),this.uiState.setExplorerFileScrollOffset(0),this.uiState.setExplorerSelectedIndex(this.explorerManager?.state.selectedIndex??0)}selectFileByIndex($){if(this.uiState.state.flatViewMode){let J=w(this.cachedFlatFiles,$);if(J){let Z=J.unstagedEntry??J.stagedEntry;if(Z)this.uiState.setDiffScrollOffset(0),this.uiState.setSelectedHunkIndex(0),this.gitManager?.selectFile(Z)}}else{let J=this.gitManager?.state.status?.files??[],Z=b(J,$);if(Z)this.uiState.setDiffScrollOffset(0),this.uiState.setSelectedHunkIndex(0),this.gitManager?.selectFile(Z)}}navigateToFile($){if(!$||!this.repoPath)return;let J=this.repoPath.endsWith("/")?this.repoPath:this.repoPath+"/";if(!$.startsWith(J))return;let Z=$.slice(J.length);if(!Z)return;let X=(this.gitManager?.state.status?.files??[]).findIndex((Q)=>Q.path===Z);if(X>=0)this.uiState.setSelectedIndex(X),this.selectFileByIndex(X)}async stageSelected(){let $=this.gitManager?.state.status?.files??[],J=this.uiState.state.selectedIndex;if(this.uiState.state.flatViewMode){let Z=w(this.cachedFlatFiles,J);if(!Z)return;let K=Z.unstagedEntry;if(K)this.pendingFlatSelectionPath=Z.path,await this.gitManager?.stage(K)}else{let Z=b($,J);if(Z&&!Z.staged)this.pendingSelectionAnchor=s($,J),await this.gitManager?.stage(Z)}}async unstageSelected(){let $=this.gitManager?.state.status?.files??[],J=this.uiState.state.selectedIndex;if(this.uiState.state.flatViewMode){let Z=w(this.cachedFlatFiles,J);if(!Z)return;let K=Z.stagedEntry;if(K)this.pendingFlatSelectionPath=Z.path,await this.gitManager?.unstage(K)}else{let Z=b($,J);if(Z?.staged)this.pendingSelectionAnchor=s($,J),await this.gitManager?.unstage(Z)}}async toggleSelected(){let $=this.uiState.state.selectedIndex;if(this.uiState.state.flatViewMode){let J=w(this.cachedFlatFiles,$);if(J)await this.toggleFlatEntry(J)}else{let J=this.gitManager?.state.status?.files??[],Z=b(J,$);if(Z)if(this.pendingSelectionAnchor=s(J,$),Z.staged)await this.gitManager?.unstage(Z);else await this.gitManager?.stage(Z)}}async stageAll(){await this.gitManager?.stageAll()}async unstageAll(){await this.gitManager?.unstageAll()}showDiscardConfirm($){this.activeModal=new U8(this.screen,$.path,async()=>{this.activeModal=null,await this.gitManager?.discard($)},()=>{this.activeModal=null}),this.activeModal.focus()}navigateNextHunk(){let $=this.uiState.state.selectedHunkIndex;if(this.bottomPaneHunkCount>0&&$<this.bottomPaneHunkCount-1)this.uiState.setSelectedHunkIndex($+1),this.scrollHunkIntoView($+1)}navigatePrevHunk(){let $=this.uiState.state.selectedHunkIndex;if($>0)this.uiState.setSelectedHunkIndex($-1),this.scrollHunkIntoView($-1)}scrollHunkIntoView($){let J=this.bottomPaneHunkBoundaries[$];if(!J)return;let Z=this.uiState.state.diffScrollOffset,K=this.layout.dimensions.bottomPaneHeight;if(J.startRow<Z||J.startRow>=Z+K)this.uiState.setDiffScrollOffset(J.startRow)}selectHunkAtRow($){if(this.uiState.state.bottomTab!=="diff")return;if(this.bottomPaneHunkBoundaries.length===0)return;this.uiState.setPane("diff");let J=this.uiState.state.diffScrollOffset+$;for(let Z=0;Z<this.bottomPaneHunkBoundaries.length;Z++){let K=this.bottomPaneHunkBoundaries[Z];if(J>=K.startRow&&J<K.endRow){this.uiState.setSelectedHunkIndex(Z);return}}}async toggleCurrentHunk(){let $=this.gitManager?.state.selectedFile;if(!$||$.status==="untracked")return;if(this.uiState.state.flatViewMode)await this.toggleCurrentHunkFlat();else await this.toggleCurrentHunkCategorized($)}async toggleCurrentHunkFlat(){let $=this.combinedHunkMapping[this.uiState.state.selectedHunkIndex];if(!$)return;let J=this.gitManager?.state.combinedFileDiffs;if(!J)return;let Z=$.source==="unstaged"?J.unstaged.raw:J.staged.raw,K=O8(Z,$.hunkIndex);if(!K)return;if(this.pendingHunkIndex=this.uiState.state.selectedHunkIndex,$.source==="staged")await this.gitManager?.unstageHunk(K);else await this.gitManager?.stageHunk(K)}async toggleCurrentHunkCategorized($){let J=this.gitManager?.state.diff?.raw;if(!J)return;let Z=O8(J,this.uiState.state.selectedHunkIndex);if(!Z)return;let K=this.gitManager?.state.status?.files??[];if(this.pendingSelectionAnchor=s(K,this.uiState.state.selectedIndex),$.staged)await this.gitManager?.unstageHunk(Z);else await this.gitManager?.stageHunk(Z)}async openFileFinder(){let $=await this.explorerManager?.getAllFilePaths()??[];if($.length===0)return;this.activeModal=new G8(this.screen,$,async(J)=>{if(this.activeModal=null,this.uiState.state.bottomTab!=="explorer")this.uiState.setTab("explorer");if(await this.explorerManager?.navigateToPath(J)){let K=this.explorerManager?.state.selectedIndex??0;this.uiState.setExplorerSelectedIndex(K),this.uiState.setExplorerFileScrollOffset(0);let X=this.layout.dimensions.topPaneHeight;if(K>=X)this.uiState.setExplorerScrollOffset(K-Math.floor(X/2));else this.uiState.setExplorerScrollOffset(0)}this.render()},()=>{this.activeModal=null,this.render()}),this.activeModal.focus()}async commit($){await this.gitManager?.commit($)}async refresh(){await this.gitManager?.refresh()}toggleMouseMode(){let $=!this.uiState.state.mouseEnabled;this.uiState.toggleMouse();let J=this.screen.program;if($)J.enableMouse();else J.disableMouse()}toggleFollow(){if(!this.followMode)this.followMode=new C$(this.config.targetFile,()=>this.repoPath,{onRepoChange:($,J)=>this.handleFollowRepoChange($,J),onFileNavigate:($)=>this.handleFollowFileNavigate($)});this.followMode.toggle(),this.render()}focusCommitInput(){if(this.commitTextarea)this.commitTextarea.show(),this.commitTextarea.focus(),this.commitTextarea.setValue(this.commitFlowState.state.message),this.commitFlowState.setInputFocused(!0),this.render()}unfocusCommitInput(){if(this.commitTextarea){let $=this.commitTextarea.getValue()??"";this.commitFlowState.setMessage($),this.commitTextarea.hide(),this.commitFlowState.setInputFocused(!1),this.screen.focusPush(this.layout.bottomPane),this.render()}}render(){if(this.updateHeader(),this.updateTopPane(),this.updateBottomPane(),this.pendingHunkIndex!==null&&this.bottomPaneHunkCount>0){let $=Math.min(this.pendingHunkIndex,this.bottomPaneHunkCount-1);this.pendingHunkIndex=null,this.uiState.setSelectedHunkIndex($),this.updateBottomPane()}this.updateFooter(),this.screen.render()}updateHeader(){let $=this.gitManager?.state,J=this.screen.width||80,Z=b0(this.repoPath,$?.status?.branch??null,$?.isLoading??!1,$?.error??null,J);this.layout.headerBox.setContent(Z)}updateTopPane(){let $=this.uiState.state,J=this.screen.width||80,Z=this.gitManager?.state.status?.files??[];if($.flatViewMode)this.cachedFlatFiles=M$(Z,this.gitManager?.state.hunkCounts??null);let K=E0($,Z,this.gitManager?.historyState?.commits??[],this.gitManager?.compareState?.compareDiff??null,this.compareSelection,this.explorerManager?.state,J,this.layout.dimensions.topPaneHeight,this.gitManager?.state.hunkCounts,$.flatViewMode?this.cachedFlatFiles:void 0);this.layout.topPane.setContent(K)}updateBottomPane(){let $=this.uiState.state,J=this.screen.width||80,K=(this.gitManager?.state.status?.files??[]).filter((G)=>G.staged).length;this.commitFlowState.setStagedCount(K);let X=$.bottomTab==="diff"&&$.currentPane==="diff",Q=X?$.selectedHunkIndex:void 0,q=X?this.gitManager?.state.selectedFile?.staged:void 0,{content:z,totalRows:V,hunkCount:Y,hunkBoundaries:U,hunkMapping:j}=k0($,this.gitManager?.state.diff??null,this.gitManager?.historyState,this.gitManager?.compareSelectionState,this.explorerManager?.state?.selectedFile??null,this.commitFlowState.state,K,this.currentTheme,J,this.layout.dimensions.bottomPaneHeight,Q,q,$.flatViewMode?this.gitManager?.state.combinedFileDiffs:void 0);if(this.bottomPaneTotalRows=V,this.bottomPaneHunkCount=Y,this.bottomPaneHunkBoundaries=U,this.combinedHunkMapping=j??[],this.uiState.clampSelectedHunkIndex(Y),this.layout.bottomPane.setContent(z),this.commitTextarea)if($.bottomTab==="commit"&&this.commitFlowState.state.inputFocused)this.commitTextarea.show();else this.commitTextarea.hide()}updateFooter(){let $=this.uiState.state,J=this.screen.width||80,Z=x0($.bottomTab,$.mouseEnabled,$.autoTabEnabled,$.wrapMode,this.followMode?.isEnabled??!1,this.explorerManager?.showOnlyChanges??!1,J,$.currentPane);this.layout.footerBox.setContent(Z)}exit(){if(this.gitManager)N8(this.repoPath);if(this.explorerManager)this.explorerManager.dispose();if(this.followMode)this.followMode.stop();if(this.commandServer)this.commandServer.stop();this.screen.destroy()}start(){return new Promise(($)=>{this.screen.on("destroy",()=>{$()})})}}import*as v5 from"net";import*as f from"fs";import{EventEmitter as m9}from"events";class E8 extends m9{server=null;socketPath;handler=null;ready=!1;constructor($){super();this.socketPath=$}setHandler($){this.handler=$}notifyReady(){this.ready=!0,this.emit("ready")}isReady(){return this.ready&&this.handler!==null}async start(){if(f.existsSync(this.socketPath))f.unlinkSync(this.socketPath);return new Promise(($,J)=>{this.server=v5.createServer((Z)=>{this.handleConnection(Z)}),this.server.on("error",(Z)=>{J(Z)}),this.server.listen(this.socketPath,()=>{f.chmodSync(this.socketPath,384),$()})})}stop(){if(this.server)this.server.close(),this.server=null;if(f.existsSync(this.socketPath))f.unlinkSync(this.socketPath)}handleConnection($){let J="";$.on("data",async(Z)=>{J+=Z.toString();let K=J.split(`
62
+ `);J=K.pop()||"";for(let X of K)if(X.trim()){let Q=await this.processCommand(X);$.write(JSON.stringify(Q)+`
63
+ `)}}),$.on("error",(Z)=>{this.emit("error",Z)})}async processCommand($){try{let J=JSON.parse($);if(J.action==="ping")return{success:!0,ready:this.isReady()};if(!this.handler)return{success:!1,error:"No handler registered"};switch(J.action){case"navigateUp":return this.handler.navigateUp(),{success:!0};case"navigateDown":return this.handler.navigateDown(),{success:!0};case"switchTab":return this.handler.switchTab(J.tab),{success:!0};case"togglePane":return this.handler.togglePane(),{success:!0};case"stage":return await this.handler.stage(),{success:!0};case"unstage":return await this.handler.unstage(),{success:!0};case"stageAll":return await this.handler.stageAll(),{success:!0};case"unstageAll":return await this.handler.unstageAll(),{success:!0};case"commit":return await this.handler.commit(J.message),{success:!0};case"refresh":return await this.handler.refresh(),{success:!0};case"getState":return{success:!0,state:this.handler.getState()};case"quit":return this.handler.quit(),{success:!0};default:return{success:!1,error:`Unknown action: ${J.action}`}}}catch(J){return{success:!1,error:J instanceof Error?J.message:String(J)}}}}function a(){process.stdout.write("\x1B[?1006l"),process.stdout.write("\x1B[?1002l"),process.stdout.write("\x1B[?1000l"),process.stdout.write("\x1B[?1003l"),process.stdout.write("\x1B[?25h")}a();process.on("exit",a);process.on("SIGINT",()=>{a(),process.exit(0)});process.on("SIGTERM",()=>{a(),process.exit(0)});process.on("uncaughtException",($)=>{a(),console.error("Uncaught exception:",$),process.exit(1)});process.on("unhandledRejection",($)=>{a(),console.error("Unhandled rejection:",$),process.exit(1)});function f9($){let J={};for(let Z=0;Z<$.length;Z++){let K=$[Z];if(K==="--follow"||K==="-f"){if(J.follow=!0,$[Z+1]&&!$[Z+1].startsWith("-"))J.followFile=$[++Z]}else if(K==="--once")J.once=!0;else if(K==="--debug"||K==="-d")J.debug=!0;else if(K==="--socket"||K==="-s")if($[Z+1]&&!$[Z+1].startsWith("-"))J.socket=$[++Z];else console.error("Error: --socket requires a path argument"),process.exit(1);else if(K==="--help"||K==="-h")console.log(`
57
64
  diffstalker - Terminal git diff/status viewer
58
65
 
59
66
  Usage: diffstalker [options] [path]
@@ -94,4 +101,4 @@ Keyboard:
94
101
  Mouse:
95
102
  Click Select file / focus pane
96
103
  Scroll Navigate files / scroll diff
97
- `),process.exit(0);else if(!X.startsWith("-"))$.initialPath=X}return $}async function z9(){let K=Y9(process.argv.slice(2)),$=$7();if(K.follow){if($.watcherEnabled=!0,K.followFile)$.targetFile=K.followFile}if(K.debug)$.debug=!0;let J=null;if(K.socket){J=new K7(K.socket);try{await J.start()}catch(Z){console.error("Failed to start command server:",Z),process.exit(1)}}if(await new eK({config:$,initialPath:K.initialPath,commandServer:J}).start(),J)J.stop();process.exit(0)}z9().catch((K)=>{console.error("Fatal error:",K),f(),process.exit(1)});
104
+ `),process.exit(0);else if(!K.startsWith("-"))J.initialPath=K}return J}async function h9(){let $=f9(process.argv.slice(2)),J=I0();if($.follow){if(J.watcherEnabled=!0,$.followFile)J.targetFile=$.followFile}if($.debug)J.debug=!0;let Z=null;if($.socket){Z=new E8($.socket);try{await Z.start()}catch(X){console.error("Failed to start command server:",X),process.exit(1)}}if(await new H8({config:J,initialPath:$.initialPath,commandServer:Z}).start(),Z)Z.stop();process.exit(0)}h9().catch(($)=>{console.error("Fatal error:",$),a(),process.exit(1)});