module StackOverflow where -- yes, the source of this post compiles as is
如果您想先玩这个(1/2路向下),请跳至如何使其正常工作。
如果我有点烦恼,你可以跳到我想要的东西,你只想找到我正在寻求的帮助。
:so
中定义的ghci.conf
命令中添加ghci来添加文件名完成吗? :l
像往常一样适用于.hs
和.lhs
个文件,但是使用我的手写预处理器来处理.so
个文件? Haskell支持.lhs
源文件中的文字编程,有两种方式:
\begin{code}
和\end{code}
。>
开头,其他任何内容都是评论
代码和注释之间必须有一个空行(以防止意外误用>
)。Bird不跟踪规则声音类似于StackOverflow的代码块吗?
参考文献: 1。 The .ghci manual
2。 GHCi haskellwiki
3。 Neil Mitchell blogs about :{
and :}
in .ghci
我喜欢在文本编辑器中编写SO答案,我喜欢发表一个包含有效代码的帖子,
但最终会发布评论块或>
,我必须在发布前编辑,这样不那么有趣。
所以,我给自己写了一个预处理器。
*
或:
开头。 首先,我们不知道(dunno)这一行是代码还是文本:
dunnoNow :: [String] -> [String]
dunnoNow [] = []
dunnoNow (line:lines)
| all (==' ') line = line:dunnoNow lines -- next line could be either
| otherwise = let (first4,therest) = splitAt 4 line in
if first4 /=" " --
|| null therest -- so the next line won't ever crash
|| head therest `elem` "*:" -- special chars that don't start lines of code.
then line:knowNow False lines -- this isn't code, so the next line isn't either
else ('>':line):knowNow True lines -- this is code, add > and the next line has to be too
但是如果我们知道,我们应该保持相同的模式,直到我们打出一个空行:
knowNow :: Bool -> [String] -> [String]
knowNow _ [] = []
knowNow itsCode (line:lines)
| all (==' ') line = line:dunnoNow lines
| otherwise = (if itsCode then '>':line else line):knowNow itsCode lines
现在我们可以获取一个模块名称,预处理该文件,并告诉ghci加载它:
loadso :: String -> IO String
loadso fn = fmap (unlines.dunnoNow.lines) (readFile $ fn++".so") -- so2bird each line
>>= writeFile (fn++"_so.lhs") -- write to a new file
>> return (":def! rso (\\_ -> return \":so "++ fn ++"\")\n:load "++fn++"_so.lhs")
我曾经默默地重新定义:rso
命令,因为我之前使用的是attemts
let currentStackOverflowFile = ....
或currentStackOverflowFile <- return ...
没让我到任何地方。
现在我需要将它放在我的ghci.conf
文件中,即在appdata/ghc/ghci.conf
中
根据{{3}}
:{
let dunnoNow [] = []
dunnoNow (line:lines)
| all (==' ') line = line:dunnoNow lines -- next line could be either
| otherwise = let (first4,therest) = splitAt 4 line in
if first4 /=" " --
|| null therest -- so the next line won't ever crash
|| head therest `elem` "*:" -- special chars that don't start lines of code.
then line:knowNow False lines -- this isn't code, so the next line isn't either
else ('>':line):knowNow True lines -- this is code, add > and the next line has to be too
knowNow _ [] = []
knowNow itsCode (line:lines)
| all (==' ') line = line:dunnoNow lines
| otherwise = (if itsCode then '>':line else line):knowNow itsCode lines
loadso fn = fmap (unlines.dunnoNow.lines) (readFile $ fn++".so") -- convert each line
>>= writeFile (fn++"_so.lhs") -- write to a new file
>> return (":def! rso (\\_ -> return \":so "++ fn ++"\")\n:load "++fn++"_so.lhs")
:}
:def so loadso
现在我可以将这整篇文章保存在LiterateSo.so
中并在ghci中做一些可爱的事情,比如
*Prelude> :so StackOverflow
[1 of 1] Compiling StackOverflow ( StackOverflow_so.lhs, interpreted )
Ok, modules loaded: StackOverflow.
*StackOverflow> :rso
[1 of 1] Compiling StackOverflow ( StackOverflow_so.lhs, interpreted )
Ok, modules loaded: StackOverflow.
*StackOverflow>
万岁!
我更愿意让ghci更直接地支持它。摆脱中间.lhs
文件会很好。
此外,似乎ghci从确定的:load
的最短子串开始执行文件名完成
你实际上在做load
,所以使用:lso
代替:so
不会欺骗它。
(我不喜欢在C中重写我的代码。我也不喜欢从源代码重新编译ghci。)
:so
中定义的ghci.conf
命令中添加ghci来添加文件名完成吗? :l
像往常一样适用于.hs
和.lhs
个文件,但是使用我的手写预处理器来处理.so
个文件?答案 0 :(得分:9)
我会尝试制作一个运行SO预处理代码或标准文学预处理器的独立预处理器,具体取决于文件扩展名。然后在:set -pgmL SO-preprocessor
中使用ghci.conf
。
对于标准文学预处理器,请运行unlit
程序,或使用Distribution.Simple.PreProcess.Unlit
。
这样,:load
和文件名完成才能正常工作。
GHCI按顺序将4个参数传递给预处理器:-h
,标签,源文件名和目标文件名。预处理器应该读取源并写入目标。标签用于输出#line
pragma。如果不改变源的行数,则可以忽略它(即用--
注释或空行替换“注释”行。