@@ -4,6 +4,7 @@ import Text.Pandoc.JSON
44import System.IO (IOMode (WriteMode ), openFile , hFlush )
55import System.IO.Temp
66import System.IO.Error
7+ import System.IO.Unsafe
78import System.Environment (lookupEnv )
89import System.Directory
910import System.Directory.Internal (andM )
@@ -45,43 +46,35 @@ vimHl (Just fm@(Format fmt)) (CodeBlock (_, cls@(ft : _), namevals) contents)
4546 cmd (x, y) = mkCmd x y
4647 mkCmd x y = " --cmd 'let g:" ++ x ++ " = \" " ++ y ++ " \" '"
4748 strip = dropWhileEnd isSpace . dropWhile isSpace
48- vimrccmd <- do
49- home <- getHomeDirectory `catchIOError` const (return " " )
50- vimrc <- fromMaybe (home </> " .vimrc.pandoc" ) <$>
51- lookupEnv " VIMRC_PANDOC"
52- let exists = doesFileExist &&> (fmap readable . getPermissions)
53- (&&>) = liftM2 andM
54- (<<$) = liftM2 (<$>)
55- (bool " " . (" --noplugin -u '" ++ ) . (++ " '" )) <<$ exists $ vimrc
5649 block <- withSystemTempFile " _vimhl_src." $ \ src hsrc -> do
5750 T. hPutStr hsrc contents >> hFlush hsrc
58- bracket (emptySystemTempFile " _vimhl_dst." ) removeFile $
59- \ dst -> do
60- vimexe <- fromMaybe " vim " <$> lookupEnv " VIMHL_BACKEND "
61- let vimcmd =
62- unwords
63- [vimexe , " -Nen " , cmds, vimrccmd, colorscheme
64- , " -c 'set ft= " ++ T. unpack ft, " | "
65- ,vimhlcmd ++ " ' -c 'w! " , dst ++ " ' -c 'qa!' "
66- ,src
67- ]
68- {- Vim must think that it was launched from a terminal,
69- - otherwise it won't load its usual environment and the
70- - syntax engine! Using WriteMode for stdin prevents Vim
71- - from getting unresponsive on Ctrl-C interrupts while
72- - still doing well its task (Vim checks that input is a
73- - terminal using isatty(), however it does not check the
74- - mode of the handle). Note that Neovim loads the syntax
75- - engine without tty emulation just fine. -}
76- hin <- ( Just <$> openFile " /dev/tty " WriteMode )
77- `catchIOError` const ( return Nothing )
78- hout <- openFile " /dev/null" WriteMode
79- (_, _, _, handle) <- createProcess $
80- let cmd = (shell vimcmd) {std_out = UseHandle hout}
81- in maybe cmd (\ h -> cmd {std_in = UseHandle h}) hin
82- r <- waitForProcess handle
83- unless (r == ExitSuccess ) $ exitWith r
84- T. readFile dst
51+ bracket (emptySystemTempFile " _vimhl_dst." ) removeFile $ \ dst -> do
52+ let vimrccmd = maybe " " (( " --noplugin -u ' " ++ ) . ( ++ " ' " ))
53+ vimrcPandoc
54+ vimcmd = unwords
55+ [vimExe, " -Nen " , cmds, vimrccmd, colorscheme
56+ , " -c 'set ft= " ++ T. unpack ft , " | "
57+ ,vimhlcmd ++ " ' -c 'w! " , dst ++ " ' -c 'qa!' "
58+ ,src
59+ ]
60+ {- Vim must think that it has been launched from a terminal,
61+ - otherwise it won't load its usual environment and the syntax
62+ - engine! Using WriteMode for stdin prevents Vim from getting
63+ - unresponsive on Ctrl-C interrupts while it still keeps doing
64+ - well its task (Vim checks that input is a terminal using
65+ - isatty(), however it does not check the mode of the handle).
66+ - Note that Neovim loads the syntax engine without tty
67+ - emulation just fine. -}
68+ hin <- if vimExeIsNvim
69+ then return Nothing
70+ else Just <$> openFile " /dev/tty " WriteMode
71+ hout <- openFile " /dev/null" WriteMode
72+ (_, _, _, handle) <- createProcess $
73+ let cmd = (shell vimcmd) {std_out = UseHandle hout}
74+ in maybe cmd (\ h -> cmd {std_in = UseHandle h}) hin
75+ r <- waitForProcess handle
76+ unless (r == ExitSuccess ) $ exitWith r
77+ T. readFile dst
8578 return $ RawBlock fm' $ wrap fm block
8679 where namevals' = map (map toLower . T. unpack *** T. unpack) namevals
8780 fm' | fm == Format " latex" = fm
@@ -113,6 +106,39 @@ vimHl (Just fm@(Format fmt)) (CodeBlock (_, cls@(ft : _), namevals) contents)
113106 | otherwise = t
114107vimHl _ cb = return cb
115108
109+ vimExe :: String
110+ vimExe = unsafePerformIO $ fromMaybe " vim" <$> lookupEnv " VIMHL_BACKEND"
111+ {-# NOINLINE vimExe #-}
112+
113+ vimExeIsNvim :: Bool
114+ vimExeIsNvim = unsafePerformIO $
115+ bracket (emptySystemTempFile " _vimhl_test." ) removeFile $ \ test -> do
116+ let vimcmd = unwords
117+ [vimExe
118+ ," -Nens --noplugin -u NONE \
119+ \-c 'if has(\" nvim\" ) | exe \" normal i1\" | endif' -c wq"
120+ ,test
121+ ]
122+ hout <- openFile " /dev/null" WriteMode
123+ (_, _, _, handle) <- createProcess $
124+ (shell vimcmd) {std_out = UseHandle hout}
125+ r <- waitForProcess handle
126+ unless (r == ExitSuccess ) $ exitWith r
127+ maybe False ((' 1' == ) . fst ) . T. uncons <$> T. readFile test
128+ {-# NOINLINE vimExeIsNvim #-}
129+
130+ vimrcPandoc :: Maybe String
131+ vimrcPandoc = unsafePerformIO $ lookupEnv " VIMRC_PANDOC" >>=
132+ maybe (do
133+ home <- getHomeDirectory `catchIOError` const (return " " )
134+ let vimrc = home </> " .vimrc.pandoc"
135+ exists = doesFileExist &&> (fmap readable . getPermissions)
136+ (&&>) = liftM2 andM
137+ (<<$) = liftM2 (<$>)
138+ (bool Nothing . Just ) <<$ exists $ vimrc
139+ ) (return . Just )
140+ {-# NOINLINE vimrcPandoc #-}
141+
116142main :: IO ()
117143main = toJSONFilter vimHl
118144
0 commit comments