2012-03-15 5 views
8

मैं Text.PrettyPrint का उपयोग कर जावास्क्रिप्ट जेनरेट करने की कोशिश कर रहा हूं। समस्या यह है कि nest एक और सुंदर मुद्रित तत्व के बगल में रखे हुए बड़े इंडेंटेशन का उत्पादन करता है। उदाहरण के लिए, इस कोड में:टेक्स्ट। प्रीटीप्रिंट: बाएं मार्जिन से इंडेंटेशन शुरू करना

import Text.PrettyPrint 

fun :: Doc 
fun = vcat [ text "function" <+> lbrace 
      , nest 4 $ vcat $ replicate 5 $ text "// foo" 
      , rbrace 
      ] 

var :: Doc 
var = text "var" <+> text "x" 

test :: Doc 
test = var <+> equals <+> fun <> semi 

fun (यह के बाईं ओर var <+> equals <> empty की वजह से) test में स्तंभ 9 पर शुरू होता है, और इस तरह इसके बाद लाइनों 9 + 4 = 13 कॉलम द्वारा इंडेंट रहे हैं:

var x = function { 
      // foo 
      // foo 
      // foo 
      // foo 
      // foo 
     }; 

वहाँ बाईं मार्जिन से indentations रेंडर करने के लिए एक रास्ता है, ताकि ऊपर

var x = function { 
    // foo 
    // foo 
    // foo 
    // foo 
    // foo 
}; 

के रूप में प्रदान की गई बजाय किया जाएगा?

+2

दान Leijen बहुत प्रिंटर 'WL-pprint' ह्यूजेस Peyton जोन्स सुंदर प्रिंटर से इंडेंट के लिए और अधिक लचीला से निपटने है। आप इसके बजाय इसका उपयोग करने पर विचार करना चाहेंगे। दस्तावेज के लिए मैनुअल देखें, यह हैडॉक दस्तावेज़ों से कहीं अधिक विस्तृत है। –

+1

मुझे लगता है कि 'wl-pprint' सही समाधान साबित होगा - यदि आप इसे पोस्ट करते हैं तो मैं इसे उत्तर के रूप में स्वीकार करने के लिए तैयार हूं। – Cactus

+0

@ कैक्टस क्या आपने कभी यह 'wl-pprint' के साथ काम किया है? यदि हां, तो आप इसके लिए उत्तर क्यों नहीं जोड़ते? – Alec

उत्तर

2

समाधान wl-pprint उपयोग करने के लिए (और indent साथ nest की जगह) वास्तव में है। फिर, दिया गया कोड

var x = function { 
    // foo 
    // foo 
    // foo 
    // foo 
    // foo 
}; 

वांछित के रूप में उपज देता है। किसी को अब भी pretty पर हैक करने का प्रयास के साथ कुछ काम कर रहा पर आमादा के लिए, ध्यान दें कि यद्यपि Doc के लिए निर्माताओं के संपर्क में नहीं कर रहे हैं, तब भी आप उन पर Generic के माध्यम से -XPatternSynonyms साथ प्राप्त कर सकते हैं:

-- | Means of exposing the data constructors of `Doc` from `pretty` 
pattern GEmpty    = M1 (L1 (L1 (L1 (M1 U1)))) 
pattern GNilAbove doc  = M1 (L1 (L1 (R1 (M1 (M1 (K1 doc)))))) 
pattern GTextBeside d doc = M1 (L1 (R1 (L1 (M1 (M1 (K1 d) :*: M1 (K1 doc)))))) 
pattern GNest n doc   = M1 (L1 (R1 (R1 (M1 (M1 (K1 n) :*: M1 (K1 doc)))))) 
pattern GUnion ldoc rdoc = M1 (R1 (L1 (L1 (M1 (M1 (K1 ldoc) :*: M1 (K1 rdoc)))))) 
pattern GNoDoc    = M1 (R1 (L1 (R1 (M1 U1)))) 
pattern GBeside ldoc s rdoc = M1 (R1 (R1 (L1 (M1 (M1 (K1 ldoc) :*: M1 (K1 s) :*: M1 (K1 rdoc)))))) 
pattern GAbove ldoc b rdoc = M1 (R1 (R1 (R1 (M1 (M1 (K1 ldoc) :*: M1 (K1 b) :*: M1 (K1 rdoc)))))) 

समस्या ज्यादातर का उल्लंघन नहीं कर रहा है पुस्तकालय के हुड के नीचे कई आविष्कार हैं।


एक तरफ ध्यान दें के रूप में, मैं भी wl-pprint-annotated पाया, wl-pprint का एक आधुनिक पुनर्लेखन का, जिसके साथ (मन में शामिल अपरिवर्तनशीलताओं रखने के लिए की आवश्यकता होगी, की कीमत पर) अंतर्निहित डेटा कंस्ट्रक्टर्स की पहुंच है। यह वास्तव में पैकेज है जिसका उपयोग मैं समाप्त कर दूंगा।

-- | Asserts a 'Doc a' cannot render on multiple lines. 
oneLine :: Doc a -> Bool 
oneLine (WL.FlatAlt d _) = oneLine d 
oneLine (WL.Cat a b) = oneLine a && oneLine b 
oneLine (WL.Union a b) = oneLine a && oneLine b 
oneLine (WL.Annotate _ d) = oneLine d 
oneLine WL.Line = False 
oneLine _ = True 

-- | Make a curly-brace delimited block. When possible, permit fitting everything on one line 
block :: Doc a -> Doc a 
block b | oneLine b = hsep ["{", b, "}"] `WL.Union` vsep [ "{", indent 2 b, "}" ] 
     | otherwise = vsep [ "{", indent 2 b, "}" ] 

तब मैं अच्छा परिणाम है कि स्वचालित रूप से करते हैं या नहीं मिलती है:

विशेष रूप से, यह मेरे ब्रेस ब्लॉक ऐसी है कि अगर यह काफी छोटा है यह केवल एक लाइन पर जाना होगा की इस तरह की सुविधा देता है अवधि कई पंक्तियों:

ghci> "function" <> parens "x" <+> block ("return" <+> "x" <> semi) 
function(x) { return x; } 
ghci> "function" <> parens "x" <+> block ("x" <> "++" <> semi <#> "return" <+> "x" <> semi) 
function(x) { 
    x++; 
    return x; 
} 
2
 
offset = 1 + length (render $ var <+> equals) 
hang empty (negate offset) test 
+0

काम नहीं कर रहा है; वास्तव में, यह उस अतिरिक्त 'लटका' के बिना दिखता है। इसके अलावा, क्या इसका कोई भयानक प्रदर्शन प्रभाव नहीं होगा? – Cactus

+0

@ कैक्टस - जीआरआर, मार्कडाउन ने मेरा '<+>' ऑपरेटर खा लिया। फिक्स्ड –

+0

नहीं, यह '<+> 'की कमी नहीं है, मैंने पाया कि वह हिस्सा स्वयं बाहर है। लेकिन मुझे एक ही आउटपुट मिलता है। – Cactus

1

आप एक सूची जहां पहला आइटम भी चर परिभाषा और काम भी शामिल करने के लिए vcat लगाने से वांछित परिणाम प्राप्त कर सकते हैं।

उदाहरण:

fun :: Doc 
fun = vcat [ var <+> equals <+> text "function" <+> lbrace 
      , nest 4 $ vcat $ replicate 5 $ text "// foo" 
      , rbrace 
      ] 

var :: Doc 
var = text "var" <+> text "x" 

test :: Doc 
test = fun <> semi 
+1

बेशक मैं यह कर सकता हूं - समस्या यह है कि मैं अभी भी एक 'डॉक्टर' (लाइनों की सूची नहीं) के लिए पूरा 'फ़ंक्शन {...}' चाहता हूं। इस तरह, 'सुंदर' अभी भी मेरे लिए एक अच्छा लेआउट चुन सकता है (यानी 'फ़ंक्शन {..}' को कई लाइनों को भी विस्तारित करने की आवश्यकता है)। – Alec

+0

ठीक है, लेकिन मुझे ऐसा करने का एक और (अधिक सुरुचिपूर्ण) तरीका नहीं मिला। यहां मुख्य मुद्दा यह है कि आप 'var'' Doc' _beside_ 'मजेदार' 'Doc' डाल रहे हैं, यह उस दस्तावेज़ की लंबाई के अनुसार 'मजेदार' का इंडेंटेशन ऑफ़सेट सेट करेगा जो कि समेकित किया गया है। इसके विपरीत दो दस्तावेज़ _above_ एक दूसरे को सम्मिलित करने से इंडेंटेशन ऑफसेट को दस्तावेज़ में अनलर्टेड रखा जाएगा जब तक कि दो दस्तावेज़ों में से कोई एक 'Nest' न हो। –

संबंधित मुद्दे