【问题标题】:Repositioning the cursor with freemarker使用 freemarker 重新定位光标
【发布时间】:2012-08-04 18:35:09
【问题描述】:

我正在使用免费的标记和 java。我必须在 txt 文件中输出结果。假设我必须打印 3 列作为

`A     B      C`

类似的模式。所有三个属性都作为字符串。 条件是,如果引用 A 的字符串长度大于 3,则应该在下一行打印。也就是说,如果长度为 8,那么前 3 个字符将在第一行,4 到 6 在第二行,其余两个在第三行。现在,当我必须为 B 打印时,我将不得不回到第一行,但 A 的当前位置将是第 3 行。

我该怎么做?

例子

Hi,                          (required cursor position to print for B).
Hel
lo(current cursor position)

【问题讨论】:

    标签: java freemarker


    【解决方案1】:

    我查看了FreeMarker built-ins for strings,我认为没有直接解决此问题的功能,但您可以执行以下操作:

    我假设您有 3 个列表,其中包含您传递给模板的 Java 属性。在模板中创建另外 3 个列表,它们将用作存储剩余字符的缓冲区列表。

    使用函数string functionsubstring(0, 3),您可以计算可以直接为A列输出多少属性字符串,如果还有字符,则将它们添加到第一个缓冲区列表中。

    然后对 B 列和 C 列重复相同的过程。之后,A 列再次转动(这次是第二行)。这次你不查看 from Java 传递的列表,而是查看缓冲区列表:是否还有前一个属性的剩余字符或者可以使用传递的列表?

    如果还有剩余字符,则再次应用substring(0, 3) 并将可能的剩余字符再次推送到第一个缓冲区列表的前面。等等等等……

    我知道这很乏味,但我能想到的唯一解决方案。

    【讨论】:

      【解决方案2】:

      我不知道freemarker,这是一种仅使用字符串操作的方法:

      1. 参加StringBuilder
      2. 当 A、B 或 C 有剩余字符时
      3. 对于 A,追加提取最多 3 个字符
      4. 追加空格直到 8 个字符
      5. 对于 B,追加提取最多 3 个字符
      6. 追加空格直到 8 个字符
      7. 对于 C,追加提取最多 3 个字符
      8. 追加空格直到 8 个字符
      9. 添加换行符

      这里是代码示例,可能未优化但有效:

      public static void main(String[] args) {
        System.out.println(formatOutput("Hello", "How are you?", "Wassup"));
      }
      
      public static String formatOutput(String textA, String textB, String textC) {
          StringBuilder output = new StringBuilder("");
      
          int beginIndex = 0, endIndex = 3;
          String snippet;
          while (textA.length() > 0 || textB.length() > 0 || textC.length() > 0) {
              if (textA.length() > endIndex) {
                  snippet = textA.substring(beginIndex, endIndex);
                  textA = textA.substring(endIndex);
              } else {
                  snippet = textA.substring(beginIndex);
                  textA = "";
              }
              output.append(snippet);
              for (int i = snippet.length(); i <= 8; i++)
                  output.append(" ");
              ;
      
              if (textB.length() > endIndex) {
                  snippet = textB.substring(beginIndex, endIndex);
                  textB = textB.substring(endIndex);
              } else {
                  snippet = textB.substring(beginIndex);
                  textB = "";
              }
              output.append(snippet);
              for (int i = snippet.length(); i <= 8; i++)
                  output.append(" ");
      
      
              if (textC.length() > endIndex) {
                  snippet = textC.substring(beginIndex, endIndex);
                  textC = textC.substring(endIndex);
              } else {
                  snippet = textC.substring(beginIndex);
                  textC = "";
              }
              output.append(snippet);
              for (int i = snippet.length(); i <= 3; i++)
                  output.append(" ");
              output.append("\n");    
          }
          return output.toString();
      }
      

      输出:

      Hel      How      Was 
      lo        ar      sup 
               e y          
               ou?          
      

      【讨论】:

        【解决方案3】:

        纯粹在 FreeMarker 中实现有点尴尬,但它的完整语言足以做到这一点。假设这是在myutils.ftl:

        <#function safeSubstring s start end>
          <#if s?length < start><#return ''></#if>
          <#if s?length < end>
            <#return s?substring(start)>
          <#else>
            <#return s?substring(start, end)>
          </#if>
        </#function>
        
        <#macro printColumns cols>
            <#list 0..999999 as i>
              <#local start = i * 3>
              <#local printedSomething = false>
              <#list cols as col>
                <#if start < col?length>
                  <#local printedSomething = true>
                  <#lt><#list cols as col>${safeSubstring(col, start, start + 3)?right_pad(8)}</#list>
                  <#break>
                </#if>
              </#list>
              <#if !printedSomething><#break></#if>
            </#list>
        </#macro>
        

        然后你可以这样做:

        <#import "myutils.ftl" as u>
        ...
        <@u.printColumns ['Helo', "How are you?", "Wassup"] />
        

        如果您想要更高的性能,您可以考虑在 Java 中将其实现为 TemplateDirectiveModel(或 TemplateMethodModelEx),然后将 myutils.ftl 更改为 &lt;#assign printColumns = "com.whatever.PrintColumnsDirective"?new()&gt;

        【讨论】:

        • 我如何在 freemarker 中写while( a&lt; 4 &amp;&amp; b&lt;5){; }。也许你可以建议我一些我可以阅读的链接。谢谢。
        • 这应该又是一个单独的 stackoverflow 问题......无论如何。循环的唯一方法是#list(和递归)。因此,您只需获得足够大的范围,就像我在上面所做的那样,然后在其中添加一个 &lt;#if !(a &lt; 4 &amp;&amp; b &lt; 5)&gt;&lt;#break&gt;&lt;/#if&gt; 作为第一件事。
        猜你喜欢
        • 2020-05-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-07-14
        • 1970-01-01
        相关资源
        最近更新 更多