mirror of
https://github.com/jgm/pandoc.git
synced 2026-09-27 01:45:56 +00:00
Org: make code line comma-escaping match Emacs' behavior.
Org's escaping rule for code in src/example blocks adds a comma to lines matching `^[ \t]*,*(\*|#\+)`, i.e. lines already starting with commas before `*` or `#+` get an additional comma; unescaping removes one comma from such lines. The writer previously left a literal `,#+foo` line unescaped, and the reader then stripped its comma when reading the result back, corrupting the code on round trips. Writer and reader now both handle runs of commas, matching org-escape-code-in-region and org-unescape-code-in-region. Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude
parent
fa0ec573e1
commit
fa92e72c35
@@ -274,11 +274,15 @@ rawBlockContent' blockEnder = try $ do
|
||||
rawLine :: Monad m => OrgParser m Text
|
||||
rawLine = try $ ("" <$ blankline) <|> anyLine
|
||||
|
||||
-- Remove one comma from lines consisting of any number of commas
|
||||
-- followed by "*" or "#+", like Emacs' org-unescape-code-in-region.
|
||||
commaEscaped suff = case T.uncons suff of
|
||||
Just (',', cs)
|
||||
| "*" <- T.take 1 cs -> cs
|
||||
| "#+" <- T.take 2 cs -> cs
|
||||
_ -> suff
|
||||
| isEscaped cs -> cs
|
||||
_ -> suff
|
||||
where
|
||||
isEscaped cs = let cs' = T.dropWhile (== ',') cs
|
||||
in "*" `T.isPrefixOf` cs' || "#+" `T.isPrefixOf` cs'
|
||||
|
||||
-- | Read but ignore all remaining block headers.
|
||||
ignHeaders :: Monad m => OrgParser m ()
|
||||
|
||||
@@ -213,13 +213,18 @@ blockToOrg (CodeBlock (ident,classes,kvs) str) = do
|
||||
let (beg, end) = case lang of
|
||||
Nothing -> ("#+begin_example" <> numberlines, "#+end_example")
|
||||
Just x -> ("#+begin_src " <> x <> numberlines <> args, "#+end_src")
|
||||
-- escape special lines
|
||||
-- Escape special lines by prepending a comma. Like Emacs'
|
||||
-- org-escape-code-in-region, escape all lines consisting of
|
||||
-- indentation, then any number of commas, then "*" or "#+"; this
|
||||
-- keeps lines that already start with commas intact when the block
|
||||
-- is unescaped again.
|
||||
let needsEscape t = let t' = T.dropWhile (== ',') t
|
||||
in T.isPrefixOf "#+" t' || T.isPrefixOf "*" t'
|
||||
let escape_line line =
|
||||
let (spaces, code) = T.span (\c -> c == ' ' || c == '\t') line
|
||||
in spaces <>
|
||||
(if T.isPrefixOf "#+" code || T.isPrefixOf "*" code
|
||||
then T.cons ',' code
|
||||
else code)
|
||||
in if needsEscape code
|
||||
then spaces <> T.cons ',' code
|
||||
else line
|
||||
let escaped = T.unlines . map escape_line . T.lines $ str
|
||||
return $ name $$ literal beg $$ literal escaped $$ literal end $$ blankline
|
||||
blockToOrg (BlockQuote blocks) = do
|
||||
|
||||
Reference in New Issue
Block a user