2013-03-27 35 views
7

Tôi đang sử dụng công cụ mẫu FreeMarker để tạo một số lớp học php từ mô tả trừu tượng về dịch vụ web. Vấn đề của tôi là, khi tôi gọi một macro trong một mẫu FreeMarker, macro chèn văn bản mà không có khoảng trắng bên trái trước cuộc gọi macro.FreeMarker: giữ thông tin nhận dạng khi sử dụng macro

exampleTemplate.ftl:

<?php 
    class ${class.name} { 
     <@docAsComment class.doc/> 

     <#list class.fields as field> 
     $${field.name}; 
     </#list> 
     <#-- ... --> 
    } 
?> 

<#macro docAsComment doc> 
/* 
<#if doc.title != ""> 
* ${doc.title} 
</#if> 
<#list doc.content as content> 
<#if content != ""> * ${content}</#if> 
</#list> 
*/ 
</#macro> 

này sẽ tạo ra một cái gì đó như thế này:

<?php 
    class foo { 
/* 
* foo 
* bar foo, bla 
*/   

    $a; 
    $b; 
    } 
?> 

Một giải pháp sẽ được, để nộp khoảng trắng hàng đầu như một cuộc tranh cãi đến vĩ mô, nhưng điều đó làm cho chỉ mẫu không thể đọc được. Có giải pháp nào tốt hơn không?

Trả lời

4

Dường như docAsComment luôn được gọi ở cùng một mức thụt lề trong mã tạo ra. Bạn có thể nướng thụt đầu dòng đó vào macro.

Nếu thụt đầu dòng của nhận xét thay đổi, bạn phải vượt qua ở cấp thụt đầu dòng. Tôi không hiểu nhận xét của bạn về việc làm cho mẫu khó đọc hơn. Nó không làm cho macro phức tạp hơn một chút.

Các invocation sẽ trông như thế này:

<@docAsComment class.doc 1/> 

Macro sẽ thay đổi một cái gì đó như thế này:

<#macro docAsComment doc indent=1> 
    <#local spc>${""?left_pad(indent * 4)}</#local> 
${spc}/* 
<#if doc.title != ""> 
${spc}* ${doc.title} 
</#if> 
<#list doc.content as content> 
<#if content != "">${spc} * ${content}</#if> 
</#list> 
${spc}*/ 
</#macro> 

Không quá xấu, thực sự. Bạn có thể làm cho vĩ mô dễ dàng hơn một chút để đọc bằng cách thụt lề nó:

<#macro docAsComment doc indent=1> 
    <#local spc>${""?left_pad(indent * 4)}</#local> 
    ${spc}/*<#lt> 
    <#if doc.title != ""> 
     ${spc}* ${doc.title}<#lt> 
    </#if> 
    <#list doc.content as content> 
     <#if content != "">${spc} * ${content}</#if><#lt> 
    </#list> 
    ${spc}*/<#lt> 
</#macro> 
+1

Cảm ơn câu trả lời! Với "làm cho các mẫu khó đọc", tôi có nghĩa là gần như những gì bạn đã nghĩ, nó làm cho các macro phức tạp hơn và ít tự giải thích. Dường như việc gửi cấp thụt lề là cách hợp lý nhất để giải quyết vấn đề. –

+0

Bạn luôn có thể thêm tiêu đề nhận xét trên macro của mình để giúp làm rõ tiêu đề nhận xét. –

+0

Có một loại trong đoạn mã của bạn, nó phải là: '...' '<#local spc> $ {" "? Left_pad (indent * 4)}' '...' –

1

Các giải pháp chung của các loại của các vấn đề (thụt đầu dòng động) là một bộ lọc, mà (thô sơ) hiểu được ngôn ngữ mà bạn tạo ra (PHP) và lại thụt lề mã. Bộ lọc đó bạn có thể triển khai dưới dạng Writer kết thúc tốt nhất đầu ra thực tế Writer. Có thể nó đủ tốt nếu nó xem các mã số {, }, /**/ là gì (Tôi không chắc chắn). Một giải pháp khác, dễ thực hiện hơn, là tạo ra một chỉ thị FreeMarker tùy chỉnh thông qua việc thực hiện TemplateDirectiveModel để lọc đầu ra được tạo ra trong nội dung lồng nhau của nó bằng cách thêm hoặc loại bỏ số lượng khoảng trắng được cung cấp làm tham số cho nó, ngay từ đầu của mỗi dòng. Sau đó, bạn có thể làm một cái gì đó như:

<@indent spaces=4> 
    ... 
</@indent> 

Sử dụng điều này sẽ làm cho mẫu phức tạp hơn, nhưng nó vẫn ít ồn hơn như chèn thụt lề trong mỗi dòng.

+0

Bạn đề nghị phá vỡ các đường dây <#nested> như thế nào? –

+0

Chỉ thị 'indent' sẽ được triển khai thông qua' TemplateDirectiveModel', không thông qua '# macro'. Nếu bạn nhìn vào API 'TemplateDirectiveModel', bạn sẽ thấy cách thực hiện nó. – ddekany

+0

Đó là gian lận. :-) –

0

Hôm nay, bạn có thể sử dụng <#nt>. Các whitespace documentation nói sau đây về nó:

Tách trắng không gian có thể được vô hiệu hóa cho một dòng với chỉ thị nt (không cắt).

Theo V2.3 changelog, trong các phiên bản trước đó, dòng chỉ chứa thẻ FTL được tỉa, với ngoại lệ của <#include> và tùy chỉnh các chỉ thị (như <@macroname>). Nhưng trong V2.3 họ đã thay đổi hành vi này để LUÔN LUÔN cắt các đường như vậy. Vì vậy, khi sử dụng macro của mình, bạn có thể đặt <#nt> trên đường kẻ để ngăn trang trí và vì vậy, hãy giữ thụt đầu dòng.

<#macro test> 
...<#t> 
</#macro> 

Example: 
    - <@test /><#nt> 

cho kết quả:

Example: 
    - ... 

Bạn có thể thấy, trong vĩ mô, tôi đã xác định <#t>, điều này là do các dòng sản phẩm mới từ bên trong macro, sẽ không được cắt, và sẽ luôn luôn cung cấp cho một dòng mới nơi bạn <@macro> nó, vì vậy trong một phần, chúng tôi cắt không gian trắng, và ở một phần khác, chúng tôi giữ nó!

Edit:

Nó phải là đáng nói rằng, đối với một số lý do, này chỉ hoạt động cho một dòng. Nếu bạn có nhiều dòng trong macro của mình, nó chỉ giữ được thụt đầu dòng cho dòng đầu tiên. Vì vậy, đến nay tôi đã tìm thấy không có sửa chữa cho điều này nhưng tôi tạo ra an issue in the Freemarker JIRA cho việc này.

Ví dụ:

<#macro test> 
... 
wow 
</#macro> 

Example: 
    - <@test><#nt> 

sẽ cho kết quả:

Example: 
    - ... 
wow 
Các vấn đề liên quan