Skip to content

Commit cfecca8

Browse files
committed
do not use /dev/tty if the backend program is Neovim
1 parent ad698d0 commit cfecca8

File tree

3 files changed

+70
-36
lines changed

3 files changed

+70
-36
lines changed

pandoc/haskell/Changelog.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,11 @@
1+
### 0.3.2.0
2+
3+
- Improvement after the previous release: do not use */dev/tty* if the backend
4+
program is Neovim. The backend's flavor gets detected by testing against
5+
*has("nvim")* once at the first call.
6+
- As well, both the vim executable and the effective vim configuration file get
7+
detected once at the first call.
8+
19
### 0.3.1.0
210

311
- Do not throw the error if */dev/tty* cannot be open. Note that Neovim loads

pandoc/haskell/pandoc-vimhl.cabal

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
name: pandoc-vimhl
2-
version: 0.3.1.0
2+
version: 0.3.2.0
33
synopsis: Pandoc filter for native Vim code highlighting
44
description: Pandoc filter for native Vim code highlighting
55
in HTML and PDF documents. Requires Vim (or Neovim) and plugin

pandoc/haskell/vimhl.hs

Lines changed: 61 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import Text.Pandoc.JSON
44
import System.IO (IOMode (WriteMode), openFile, hFlush)
55
import System.IO.Temp
66
import System.IO.Error
7+
import System.IO.Unsafe
78
import System.Environment (lookupEnv)
89
import System.Directory
910
import 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
114107
vimHl _ 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+
116142
main :: IO ()
117143
main = toJSONFilter vimHl
118144

0 commit comments

Comments
 (0)