pandoc Включить фильтр файлов в haskell

Я использую этот фильтр файлов haskell pandoc include

#!/usr/bin/env runhaskell
-- includes.hs
import Text.Pandoc.JSON

doInclude :: Block -> IO Block
doInclude cb@(CodeBlock (id, classes, namevals) contents) =
  case lookup "include" namevals of
       Just f     -> return . (CodeBlock (id, classes, namevals)) =<< readFile f
       Nothing    -> return cb
doInclude x = return x

main :: IO ()
main = toJSONFilter doInclude

со следующим фрагментом кода в уценке

~~~~ {include="tasks/mdbook.js"}
~~~~

На самом деле это включает файл в уценку, однако я хотел бы, чтобы он также включал форматирование кода, например.

```js
file content here
```

Как я могу обновить приведенный выше код haskell, чтобы выполнить это? с чем-то вроде

~~~~ {code="tasks/mdbook.js", format="js"}
~~~~

person Anthony McCormick    schedule 05.02.2014    source источник


Ответы (3)


Поскольку фильтр include сохраняет все classes блока кода, вы можете включить содержимое файла и применить к нему форматирование кода, просто выполнив следующее:

~~~~ {.javascript include="tasks/mdbook.js"}
~~~~
person Ilya    schedule 11.03.2014

Я предполагаю, что проблема, которую вы пытаетесь решить, состоит в том, чтобы иметь документ уценки, который ссылается на некоторый фрагмент кода, и вы хотели бы избежать копирования и вставки кода в документ и кошмара синхронизации двух версий с помощью рука. Итак, вы попытались решить проблему, включив исходные файлы в документ уценки через фильтр.

Я решил ту же проблему другим способом. Я сохранил весь (соответствующий) исходный код в документе уценки и написал инструмент, который извлекает весь исходный код. Мой конкретный вариант использования заключался в том, что я писал слайды для лекций, и каждый раз, когда я компилировал свои слайды, я также извлекал код и следил за его компиляцией. Я также собрал весь код в zip-архив для удобства моих студентов.

Мой инструмент доступен здесь: https://github.com/josefs/CodeExtract

Вы можете написать такие блоки кода:

~~~ {.haskell file="Hello.hs"}
main = putStrLn "Hello World!"
~~~

При запуске документа, содержащего такие блоки кода, через мой маленький инструмент будет создан файл Hello.hs, содержащий код в блоке.

Существует также более продвинутая функция, поддерживающая несколько фрагментов кода, которые могут оказаться в одном документе. Например, у вас может быть два таких блока кода:

~~~ {.haskell template="Hello.hs.tmpl" var="mainfkn"}
main = putStrLn str
~~~

~~~ {.haskell template="Hello.hs.tmpl" var="misc"}
str = "Hello World!"
~~~

И затем файл шаблона, Hello.hs.tmpl подобный следующему (он использует тот же формат шаблона, что и pandoc):

~~~
module Main where
$mainfkn$
$misc$
~~~

Он сгенерирует файл Hello.hs, содержащий файл шаблона, но с заменой переменной соответствующим блоком кода в файле уценки. Это очень удобно.

Я надеюсь, что вы найдете мой инструмент полезным, хотя я понимаю, что он может не решить вашу конкретную проблему.

person svenningsson    schedule 05.02.2014
comment
Привет, svenningsson, спасибо за ответ, но мне нужно, чтобы все было наоборот. Я не хочу хранить исходный код в файлах уценки, так как потеряю все свои замечательные функции IDE. Нет ли способа добавить символы в начало блока ввода-вывода в haskell? - person Anthony McCormick; 06.02.2014
comment
Справедливо. Смотрите мой новый ответ. - person svenningsson; 06.02.2014

Кажется, вы хотите обновить атрибуты блока кода. Вот что вы можете сделать:

#!/usr/bin/env runhaskell
-- includes.hs
import Text.Pandoc.JSON

doInclude :: Block -> IO Block
doInclude cb@(CodeBlock (id, classes, namevals) contents) =
  case lookup "include" namevals of
       Just f     -> do
         let newAttrs = filter ((/= "include") . fst) namevals ++ [("code",f), ("format","js")]
         return . (CodeBlock (id, classes, newAttrs)) =<< readFile f
       Nothing    -> return cb
doInclude x = return x

main :: IO ()
main = toJSONFilter doInclude

Измените код для newAttr по своему усмотрению.

person svenningsson    schedule 06.02.2014
comment
это, кажется, не компилируется. Будет ли этот код обновлять блок кода? Похоже, он добавит код и отформатирует значения в массив атрибутов, чего я не пытаюсь достичь. в файле .md я хотел бы указать код, формат и добавить фильтру необходимые символы в начало возвращаемого блока кода, как в '''js (код файла для чтения здесь)''' - person Anthony McCormick; 07.02.2014
comment
Первая ошибка была лексической ошибкой в ​​строковом/символьном литерале в символе '\n'. Я думаю, что это произошло из-за отсутствия после включения после исправления, которое теперь не будет компилироваться со следующей ошибкой синтаксического анализа при вводе `return' - person Anthony McCormick; 07.02.2014
comment
Я не хотел усложнять вам задачу :-) Я обновил код, чтобы он выполнял проверку типов. Изменения следующие: отсутствующие, которые вы заметили, а затем «делать» после шаблона «Just f-›». Я не тестировал код, хотя. - person svenningsson; 07.02.2014
comment
это, кажется, не делает то, что я хотел. Я не хочу обновлять атрибуты, я хочу добавить строку '''(формат) и добавить строку ''' к содержимому, которое должно быть прочитанным файлом. Имеет ли это смысл? - person Anthony McCormick; 07.02.2014
comment
Я не уверен на 100%, что понимаю, но вы просите что-то вроде этого (замените строку, начинающуюся с return, на это): file <- readFile f let n = "```js\n" ++ file ++ "```\n" return (CodeBlock (id, classes, namevals) n) - person svenningsson; 07.02.2014
comment
Извините за испорченное форматирование. Там должны быть разрывы строк вместо пробелов между блоками кода. - person svenningsson; 07.02.2014