Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

关于简化 xtemplate 用法的一些想法 #235

Open
atxy-blip opened this issue Jan 24, 2022 · 6 comments · May be fixed by #236
Open

关于简化 xtemplate 用法的一些想法 #235

atxy-blip opened this issue Jan 24, 2022 · 6 comments · May be fixed by #236

Comments

@atxy-blip
Copy link
Contributor

这两天在重新拜读关于封面部分的代码。fduthesis 使用了 xtemplate 进行此部分的实现,但在实际阅读代码的时候,我并没有感到抽象化起到了简化的作用,反而是大量的嵌套导致直观上艰深难懂(也有很大可能是因为我菜)。仔细阅读这一宏包的使用手册后我发现了一个华点,简言之就是:Instance 不应当是对整个页面内容的描述,而是对单个页面部件的描述。

原文是这样写的:

There are three distinct layers in the definition of “a document” at this level

  1. semantic elements such as the ideas of sections and lists;
  2. a set of design solutions for representing these elements visually;
  3. specific variations for these designs that represent the elements in the document.

In the parlance of the template system, these are called object types, templates, and instances

具体来讲:根据我的理解,目前 fduthesis 将整个页面作为一个对象处理,规定了其中各种元素的属性。这就导致 Template 的定义异常复杂,Instance 的定义中各种元素的属性混合在一起。这一切只为创建一个实例,不免有头重脚轻的感觉。

另一方面,当我们把页面部件而不是整个页面考虑为一个对象时,它天然地只具备有限数量的属性:上下边距、对齐方式、字形字号、文字内容等,使得 Template 的定义也是有限的。而具体的页面是这些对象的实例的集合,创建页面只需传入一个列表调用各个 Instance 即可。我个人认为这种做法更符合 xtemplate 的初衷,也能极大优化代码的可读性。

为了更好地说明观点,下面准备了一个 MWE。

其中,由于对齐方式取决于头尾的控制命令,其实也可以不用单独新建控制序列。这也能简化原本复杂的展开控制。

\documentclass{article}
\usepackage{expl3,xtemplate,kantlipsum}

\ExplSyntaxOn
% contents to produce on the page
\cs_new_protected:Npn \__mytest_cover_title:
  { testcovertemplate }
\cs_new_protected:Npn \__mytest_cover_img:
  { \parbox {5cm} { \kant[42][1-3] } }

\tl_new:N   \l__mytest_content_tl
\tl_new:N   \l__mytest_begin_align_tl
\tl_new:N   \l__mytest_end_align_tl
\skip_new:N \l__mytest_top_skip

% creates an object type “nju” XD
\DeclareObjectType { nju } { \c_zero_int }

% defines several properties of a single page element
\DeclareTemplateInterface { nju } { page-element } { \c_zero_int }
  {
    align    : choice { l, r, c, n } = c,
    top-skip : skip = \c_zero_skip,
    content  : tokenlist
  }

\DeclareTemplateCode { nju } { page-element } { \c_zero_int }
  {
    align =
      {
        l =
          { \tl_set_eq:NN \l__mytest_begin_align_tl \flushleft
            \tl_set_eq:NN \l__mytest_end_align_tl   \endflushleft  },
        r =
          { \tl_set_eq:NN \l__mytest_begin_align_tl \flushright
            \tl_set_eq:NN \l__mytest_end_align_tl   \endflushright },
        c =
          { \tl_set_eq:NN \l__mytest_begin_align_tl \center
            \tl_set_eq:NN \l__mytest_end_align_tl   \endcenter     },
        n =
          { \tl_clear:N   \l__mytest_begin_align_tl
            \tl_clear:N   \l__mytest_end_align_tl                  }
      },
    top-skip = \l__mytest_top_skip,
    content  = \l__mytest_content_tl
  }
  {
    \AssignTemplateKeys
    \null \skip_vertical:N \l__mytest_top_skip
    \group_begin:
    \l__mytest_begin_align_tl
    \l__mytest_content_tl
    \l__mytest_end_align_tl
    \group_end:
  }

% the title example
\DeclareInstance { nju } { cover / title } { page-element }
  {
    align = r,
    top-skip = 5cm,
    content = \__mytest_cover_title:
  }

% the img example
\DeclareInstance { nju } { cover / img } { page-element }
  {
    content = \__mytest_cover_img:
  }

% user interface
\NewDocumentCommand \MakeTestCover { }
  {
    \thispagestyle { empty }
    \clist_map_inline:nn { title, img }
      { \UseInstance { nju } { cover / ##1 } }
  }
\ExplSyntaxOff

\begin{document}
\MakeTestCover
\end{document}
@stone-zeng
Copy link
Owner

使用 xtemplate 最初的目的是为了能够支持不同样式的封面,因为我们很多院系没有按照学校的模板,而是另起炉灶各搞各的(尤其是本科,比如我们物理系的就不长这样,所以才会有 phys 分支)。但在相当的时间内这个模板的用户并不多,而且往往只需要应付学校的模板,所以这个需求实际上就变成了伪需求。

@atxy-blip
Copy link
Contributor Author

支持不同样式的封面

原来如此……你南情况也差不多,研究生院给了个语焉不详的 Word 材料包,然后说具体规定听院系的(苦笑)。

请允许我重复一下此处的观点:xtemplate 本不应该写得像当前这般复杂。面向对象本来就是要找尽可能多的共通属性,因此对于封面页,它的共同属性其实是包含页面部件,是页面的 Instance 套着页面部件的 Instance。这是我理解到的优势。

今天上午我把这个想法成功套到了 njuthesis 上面,不如我晚上加班,明天提个 PR 看看效果?

@stone-zeng
Copy link
Owner

这种比较大的重构暂时不太想做,issue 先放着,之后再说吧(

@zepinglee
Copy link

我之前看了 xtemplate 的文档,但是一直没搞懂用在什么场景下最合适。刚刚看完这篇分析后,我的理解是像 tuna/thuthesis/thuthesis.dtx#L4483-L4535 比较适合用 xtemplate,其主要优势在于 key-value 的接口比较清晰?

@atxy-blip
Copy link
Contributor Author

@stone-zeng 这种比较大的重构暂时不太想做

我重构完了(捂脸)目前正在补说明文字。

@zepinglee 主要优势在于 key-value 的接口比较清晰?

对!这样子就可以很方便地创建具有相似外观的组件;更广义地,是可以创建具有相似行为的组件。我还没仔细研究过 thuthesis ,但已经保上你校了,之后有很多机会看(

@zepinglee
Copy link

对!这样子就可以很方便地创建具有_相似外观_的组件;更广义地,是可以创建具有_相似行为_的组件。

嗯,所以这个 issue 的改进主要是在 page-element 这样更细的粒度上进行封装。

但已经保上你校了

欢迎欢迎!

atxy-blip added a commit to atxy-blip/fduthesis that referenced this issue Jan 24, 2022
atxy-blip added a commit to atxy-blip/fduthesis that referenced this issue Jan 24, 2022
atxy-blip added a commit to atxy-blip/fduthesis that referenced this issue Jan 25, 2022
@atxy-blip atxy-blip linked a pull request Jan 25, 2022 that will close this issue
@stone-zeng stone-zeng linked a pull request Jan 25, 2022 that will close this issue
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants