Skip to content

Instantly share code, notes, and snippets.

@alogic0
Last active August 29, 2015 14:16
Show Gist options
  • Select an option

  • Save alogic0/36993c169e2431f4d591 to your computer and use it in GitHub Desktop.

Select an option

Save alogic0/36993c169e2431f4d591 to your computer and use it in GitHub Desktop.
For ghci, pager of defined names in Haskell modules like *less*
-- author [Roman Cheplyaka](http://www.reddit.com/r/haskell/comments/2y2f1p/pager_in_ghci_like_less/cp5w8a9)
import System.Process
import System.Posix.IO
import System.Posix.Types
import Data.IORef
import Data.List (intersperse)
import System.IO.Unsafe
{-# NOINLINE pid_ref #-}
pid_ref :: IORef (ProcessHandle, Fd)
pid_ref = unsafePerformIO $ newIORef undefined
browseLess :: String -> IO String
browseLess mod_ = do
-- make a copy of stdout
stdout_copy <- dup stdOutput
-- launch less that reads from a pipe and writes to the terminal
(Just pipe_handle, Nothing, Nothing, pid)
<- createProcess (proc "less" ["-ix8RmPm "
++ intersperse '\\' mod_
++ " ?ltline %lt?L/%L..?e (END):?pB %pB\\%..$"])
{ std_in = CreatePipe }
closeFd stdOutput
-- obtain an fd for our end of the pipe
pipe_fd <- handleToFd pipe_handle
-- make the pipe our new stdout
dupTo pipe_fd stdOutput
-- close pipe_fd, so that less can observe the EOF
closeFd pipe_fd
writeIORef pid_ref (pid, stdout_copy)
return $ unlines
[ ":browse " ++ mod_
, "finish"
]
finish = do
closeFd stdOutput
(pid, stdout_copy) <- readIORef pid_ref
waitForProcess pid
dupTo stdout_copy stdOutput
closeFd stdout_copy
@alogic0
Copy link
Copy Markdown
Author

alogic0 commented Mar 12, 2015

Original author Roman Cheplyaka wrote this code in comment on Rredit.
To get it to work, put in your .ghci:

:load path/to/less.hs
:def browseLess browseLess

And try it:
> :browseLess Prelude

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment