mirror of
https://github.com/srid/nixos-config.git
synced 2025-12-26 15:04:59 +08:00
rewrite it in haskell
This commit is contained in:
parent
79825b9c21
commit
dcc45af9f0
1 changed files with 49 additions and 27 deletions
|
|
@ -2,6 +2,7 @@
|
|||
# `git diff HEAD` to show both staged and unstaged changes. Useful for
|
||||
# monitoring code changes made by LLMs in real-time without manually restarting
|
||||
# the diff viewer.
|
||||
|
||||
{ writers, haskellPackages, git, coreutils, ... }:
|
||||
|
||||
writers.writeHaskellBin "git-changes"
|
||||
|
|
@ -16,48 +17,69 @@ writers.writeHaskellBin "git-changes"
|
|||
import System.FSNotify
|
||||
import Control.Concurrent
|
||||
import Control.Monad
|
||||
import System.Process
|
||||
import System.Process (system)
|
||||
import System.IO
|
||||
import Data.List (isInfixOf)
|
||||
import System.Exit (ExitCode(..))
|
||||
import Control.Exception (catch, SomeException)
|
||||
|
||||
loadFromBins ["${git}", "${coreutils}"]
|
||||
|
||||
main :: IO ()
|
||||
main = do
|
||||
hSetBuffering stdout NoBuffering
|
||||
hSetBuffering stderr NoBuffering
|
||||
|
||||
hPutStrLn stderr "[git-changes] Starting..."
|
||||
|
||||
-- Use a simple approach: just run git diff in foreground, restart when files change
|
||||
runningRef <- newMVar False
|
||||
|
||||
-- Start initial git diff
|
||||
diffRef <- newMVar Nothing
|
||||
let runDiff = do
|
||||
-- Kill previous diff if running
|
||||
oldProc <- takeMVar diffRef
|
||||
case oldProc of
|
||||
Just ph -> do
|
||||
terminateProcess ph
|
||||
void $ waitForProcess ph
|
||||
Nothing -> return ()
|
||||
|
||||
-- Start new git diff
|
||||
ph <- spawnCommand "${git}/bin/git diff HEAD"
|
||||
putMVar diffRef (Just ph)
|
||||
-- Don't restart if already running
|
||||
isRunning <- tryTakeMVar runningRef
|
||||
case isRunning of
|
||||
Just True -> do
|
||||
hPutStrLn stderr "[git-changes] Diff already running, skipping..."
|
||||
putMVar runningRef True
|
||||
return ()
|
||||
_ -> do
|
||||
putMVar runningRef True
|
||||
hPutStrLn stderr "[git-changes] Running git diff..."
|
||||
|
||||
-- Run git diff - this blocks until it exits
|
||||
exitCode <- system "${git}/bin/git diff HEAD"
|
||||
|
||||
void $ takeMVar runningRef
|
||||
hPutStrLn stderr $ "[git-changes] Git diff exited with: " ++ show exitCode
|
||||
|
||||
-- If user quit successfully, exit the program
|
||||
case exitCode of
|
||||
ExitSuccess -> error "User quit"
|
||||
_ -> return ()
|
||||
|
||||
-- Run initial diff
|
||||
runDiff
|
||||
-- Run initial diff in a thread
|
||||
diffThread <- forkIO runDiff
|
||||
|
||||
-- Watch for file changes
|
||||
withManager $ \mgr -> do
|
||||
-- Fork a thread to watch for file changes
|
||||
hPutStrLn stderr "[git-changes] Starting file watcher..."
|
||||
void $ forkIO $ withManager $ \mgr -> do
|
||||
_ <- watchTree
|
||||
mgr
|
||||
"."
|
||||
(\event -> case event of
|
||||
_ -> let path = eventPath event
|
||||
in not (".git" `isInfixOf` path)
|
||||
)
|
||||
(\_ -> do
|
||||
putStrLn "File changed, restarting diff..."
|
||||
runDiff
|
||||
)
|
||||
(\event -> let path = eventPath event
|
||||
in not (".git" `isInfixOf` path))
|
||||
(\event -> do
|
||||
hPutStrLn stderr $ "[git-changes] File changed: " ++ eventPath event
|
||||
-- Kill the current diff thread
|
||||
killThread diffThread
|
||||
void $ takeMVar runningRef
|
||||
-- Start a new one
|
||||
void $ forkIO runDiff)
|
||||
|
||||
-- Keep running
|
||||
forever $ threadDelay 1000000
|
||||
|
||||
hPutStrLn stderr "[git-changes] Waiting for user to quit..."
|
||||
-- Wait for the diff thread to finish
|
||||
threadDelay maxBound
|
||||
''
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue