├── .gitignore ├── .github ├── dependabot.yml ├── workflows │ ├── main.yaml │ ├── cache.yaml │ └── release.yaml ├── tl_packages └── FUNDING.yml ├── litetable-demo.tex ├── README.md ├── litetable.ins ├── litetable-zh-cn.tex ├── litetable-zh-hk.tex ├── LICENSE └── litetable.dtx /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | /build/ 3 | *.pdf 4 | *.tar.gz 5 | *.zip 6 | *.curlopt -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | 4 | - package-ecosystem: "github-actions" 5 | directory: "/" 6 | schedule: 7 | # Check for updates to GitHub Actions every week 8 | interval: "daily" 9 | -------------------------------------------------------------------------------- /.github/workflows/main.yaml: -------------------------------------------------------------------------------- 1 | name: Automated testing 2 | 3 | on: 4 | push: 5 | branches: 6 | - "**" 7 | pull_request: 8 | 9 | jobs: 10 | l3build: 11 | strategy: 12 | matrix: 13 | os: [ubuntu-latest, macos-latest, windows-latest] 14 | runs-on: ${{ matrix.os }} 15 | steps: 16 | - name: Checkout repository 17 | uses: actions/checkout@v6 18 | - name: Install TeX Live 19 | uses: zauguin/install-texlive@v4 20 | with: 21 | package_file: .github/tl_packages 22 | - name: Run l3build 23 | run: l3build ctan -q -H -------------------------------------------------------------------------------- /.github/tl_packages: -------------------------------------------------------------------------------- 1 | # The test framework itself 2 | l3build 3 | # 4 | # Base 5 | latex 6 | latex-bin 7 | # 8 | # For the doc target and testing l3doc 9 | alphalph 10 | amsfonts 11 | bookmark 12 | booktabs 13 | catchfile 14 | cm-super 15 | colortbl 16 | csquotes 17 | ctex 18 | dvips 19 | ec 20 | enumitem 21 | epstopdf 22 | epstopdf-pkg 23 | everysel 24 | fancyvrb 25 | framed 26 | hologo 27 | hypdoc 28 | hyperref 29 | latexmk 30 | libertine 31 | lipsum 32 | listings 33 | makeindex 34 | mathpazo 35 | metalogo 36 | oberdiek 37 | pdflscape 38 | pdfpages 39 | pgf 40 | psnfss 41 | ragged2e 42 | siunitx 43 | times 44 | twemojis 45 | underscore 46 | units -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] 4 | patreon: # Replace with a single Patreon username 5 | open_collective: # Replace with a single Open Collective username 6 | ko_fi: myhsia 7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel 8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry 9 | liberapay: # Replace with a single Liberapay username 10 | issuehunt: # Replace with a single IssueHunt username 11 | lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry 12 | polar: # Replace with a single Polar username 13 | buy_me_a_coffee: # Replace with a single Buy Me a Coffee username 14 | thanks_dev: # Replace with a single thanks.dev username 15 | custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] 16 | -------------------------------------------------------------------------------- /.github/workflows/cache.yaml: -------------------------------------------------------------------------------- 1 | # This workflow makes sure that there is always a cache present for the main branch. 2 | # This cache can be picked up by all other branches, so it ensures that even new 3 | # branches and tags don't have to download a complete copy of TeX Live. 4 | # 5 | # Since GitHub keeps unused caches for one week, we need to run at least once a week 6 | # to ensure that the cache always stays around. To avoid timing issues and issues 7 | # when an update fails for some reason, we run twice per week. 8 | 9 | name: Keep TeX Live cache up-to-date 10 | on: 11 | schedule: 12 | # Runs at 09:41 UTC daily. 13 | - cron: '41 9 * * *' 14 | 15 | jobs: 16 | cache: 17 | strategy: 18 | matrix: 19 | os: [ubuntu-latest, macos-latest, windows-latest] 20 | runs-on: ${{ matrix.os }} 21 | name: Update TeX Live 22 | steps: 23 | # To use `.github/tl_packages`, main repo must be checked out first. 24 | - name: Checkout repository 25 | uses: actions/checkout@v6 26 | - name: Install TeX Live 27 | uses: zauguin/install-texlive@v4 28 | with: 29 | # List the required TeX Live packages in a separate file to allow reuse in 30 | # different workflows. 31 | package_file: .github/tl_packages -------------------------------------------------------------------------------- /litetable-demo.tex: -------------------------------------------------------------------------------- 1 | \documentclass[svgnames, a4paper]{article} 2 | 3 | \usepackage{litetable, twemojis} 4 | \usepackage[osf, mono = false]{libertine} 5 | \usepackage[T1]{fontenc} 6 | 7 | \begin{document} 8 | 9 | \weeklist [ format = \bfseries \scshape, sep = \textbar ] 10 | { 11 | \texttwemoji{1f312} Mon -> 1.05, \texttwemoji{1f525} Tue -> 1.05, 12 | \texttwemoji{1f30a} Wed -> 1.1, \texttwemoji{1f332} Thu -> .9, 13 | \texttwemoji{1fa99} Fri -> .9 14 | } 15 | \timelist [ numformat = \ttfamily \bfseries, timeformat = \ttfamily ] 16 | { 17 | 08:05 -> 08:50, 08:55 -> 09:40, 10:00 -> 10:45, 10:50 -> 11:35, 18 | 11:40 -> 12:25, 13:30 -> 14:15, 14:20 -> 15:05, 15:15 -> 16:00, 19 | 16:05 -> 16:50, 18:30 -> 19:15, 19:20 -> 20:05, 20:10 -> 20:55 20 | } 21 | \begin{litetable} [ DarkBlue, sem = SEM 7, hline = dashed ] 22 | {Course Schedule} 23 | \course [ subject = interface3, comment = \TeX~Live 2025, 24 | lecture = The \LaTeX\ Project, DarkBlue ] {4} {5} 25 | \newday 26 | \course [ subject = expl3, lecture = The \LaTeX\ Project ] {8} {8} 27 | \newday 28 | \course [ subject = Keep on \TeX ing, lecture = Donald E. Knuth, 29 | location = Stanford University, Purple ] {10} {11} 30 | \newday 31 | \course [ subject = Ti\textit k\/Z, lecture = \textsc{pgf}, 32 | Crimson, comment = Version 3.1.10 ] {3} {5} 33 | \more {Programme Duration: 09 / 2021 -- 07 / 2025} 34 | \end{litetable} 35 | 36 | \end{document} -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![CTAN Version](https://img.shields.io/ctan/v/litetable)](https://ctan.org/pkg/litetable) 2 | [![GitHub Release](https://img.shields.io/github/v/release/myhsia/litetable)](https://github.com/myhsia/litetable/releases/latest) 3 | [![GitHub Last Commit](https://img.shields.io/github/last-commit/myhsia/litetable)](https://github.com/myhsia/litetable/commits) 4 | [![Actions Status](https://github.com/myhsia/litetable/actions/workflows/main.yaml/badge.svg?branch=main)](https://github.com/myhsia/litetable/actions) 5 | [![GitHub Repo stars](https://img.shields.io/github/stars/myhsia/litetable)](https://github.com/myhsia/litetable) 6 | 7 | The `litetable` Package 8 | ======================= 9 | 10 | The `litetable` package (conducted with LaTeX3) provides a colorful design 11 | of timetable. 12 | 13 | Overview 14 | -------- 15 | 16 | The package provides the `\course` macro 17 | 18 | \course [] {} [] {} [] 19 | 20 | to add colorful custom course block. 21 | 22 | See `litetable.pdf` for more. Happy TeXing! 23 | 24 | Issues 25 | ------ 26 | 27 | The issue tracker for `litetable` is currently located 28 | [on GitHub](https://github.com/myhsia/litetable/issues). 29 | 30 | Build status 31 | ------------ 32 | 33 | This project uses [GitHub Actions](https://github.com/features/actions) 34 | as a hosted continuous integration service. For each commit, the build status 35 | is tested using the current release of TeX Live. 36 | 37 | _Current build status:_ ![build status](https://github.com/myhsia/litetable/actions/workflows/main.yaml/badge.svg?branch=main) 38 | 39 | Copyright and License 40 | --------------------- 41 | 42 | Copyright (C) 2023-2025 by Mingyu Xia 43 | 44 | This work may be distributed and/or modified under the conditions 45 | of the LaTeX Project Public License (LPPL), either version 1.3c of 46 | this license or (at your option) any later version. 47 | The latest version of this license is in 48 | 49 | http://www.latex-project.org/lppl.txt 50 | 51 | and version 1.3c or later is part of all distributions of LaTeX 52 | version 2008 or later. 53 | 54 | This work has the LPPL maintenance status `maintained'. 55 | 56 | The Current Maintainer of this work is **Mingyu Xia**. 57 | -------------------------------------------------------------------------------- /.github/workflows/release.yaml: -------------------------------------------------------------------------------- 1 | name: Publish New Release 2 | 3 | on: 4 | push: 5 | paths: 6 | - "build.lua" 7 | workflow_dispatch: 8 | 9 | jobs: 10 | create-release: 11 | permissions: 12 | contents: write 13 | runs-on: ubuntu-latest 14 | steps: 15 | - name: Checkout repository 16 | uses: actions/checkout@v6 17 | - name: Install TeX Live 18 | uses: zauguin/install-texlive@v4 19 | with: 20 | package_file: .github/tl_packages 21 | - name: tag 22 | run: | 23 | l3build tag 24 | git config --global user.name "GitHub Actions" 25 | git config --global user.email "actions@github.com" 26 | if [[ -n $(git status --porcelain) ]]; then 27 | git add . 28 | git commit -m "Automatic tagging by l3build" 29 | git push origin main 30 | else 31 | echo "No changes to commit." 32 | fi 33 | - name: Run l3build and Upload to CTAN 34 | run: | 35 | l3build ctan 36 | yes y | l3build upload 37 | - name: Read version from build.lua 38 | run: | 39 | MODULE=${GITHUB_REPOSITORY##*/} 40 | VERSION=$(perl -nle 'print $1 if /version\s*=\s*"([^"]+)"/' build.lua) 41 | DATE=$(perl -nle 'print $1 if /date\s*=\s*"([^"]+)"/' build.lua) 42 | echo "MODULE=$MODULE" >> $GITHUB_ENV 43 | echo "VERSION=$VERSION" >> $GITHUB_ENV 44 | echo "DATE=$DATE" >> $GITHUB_ENV 45 | perl -0777 -ne 'print $1 if /announcement\s*=\s*\[\[(.*?)\]\]/s' build.lua > ANNOUNCEMENT 46 | - name: Create date tag 47 | run: | 48 | TAG_NAME="${{ env.DATE }}" 49 | ZIP_NAME="${{ env.MODULE }}.zip" 50 | RLS_NAME="${{ env.MODULE }} ${{ env.VERSION }}" 51 | echo "TAG_NAME=$TAG_NAME" >> $GITHUB_ENV 52 | echo "ZIP_NAME=$ZIP_NAME" >> $GITHUB_ENV 53 | echo "RLS_NAME=$RLS_NAME" >> $GITHUB_ENV 54 | git fetch --tags 55 | if git rev-parse "$TAG_NAME" >/dev/null 2>&1; then 56 | echo "Tag $TAG_NAME already exists. Skipping tag creation." 57 | else 58 | git tag $TAG_NAME 59 | git push origin $TAG_NAME 60 | fi 61 | - name: Create and Publish Release 62 | uses: softprops/action-gh-release@v2 63 | with: 64 | tag_name: ${{ env.TAG_NAME }} 65 | name: ${{ env.RLS_NAME }} 66 | files: ${{ env.ZIP_NAME }} 67 | body_path: ANNOUNCEMENT 68 | env: 69 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} -------------------------------------------------------------------------------- /litetable.ins: -------------------------------------------------------------------------------- 1 | \iffalse meta-comment 2 | 3 | File: litetable.ins 4 | ----------------------------------------------------------------------- 5 | Copyright (C) 2023-2025 by Mingyu Xia * 6 | * 7 | This work may be distributed and/or modified under the conditions * 8 | of the LaTeX Project Public License (LPPL), either version 1.3c of * 9 | this license or (at your option) any later version. * 10 | The latest version of this license is in * 11 | * 12 | http://www.latex-project.org/lppl.txt * 13 | * 14 | and version 1.3c or later is part of all distributions of LaTeX * 15 | version 2008 or later. * 16 | * 17 | This work has the LPPL maintenance status `maintained'. * 18 | * 19 | The Current Maintainer of this work is Mingyu Xia. * 20 | * 21 | This work consists of the files litetable.dtx, * 22 | litetable.ins, * 23 | the derived files litetable.sty, * 24 | the documentation files litetable.pdf, * 25 | and README.md. * 26 | ----------------------------------------------------------------------- 27 | 28 | Any modification of this file should ensure that the copyright and 29 | license information is placed in the derived files. 30 | 31 | ----------------------------------------------------------------------- 32 | 33 | \fi 34 | 35 | \input docstrip % 36 | \askforoverwritefalse 37 | 38 | \preamble 39 | ----------------------------------------------------------------------- 40 | Copyright (C) 2023-2025 by Mingyu Xia * 41 | * 42 | This work may be distributed and/or modified under the conditions * 43 | of the LaTeX Project Public License (LPPL), either version 1.3c of * 44 | this license or (at your option) any later version. * 45 | The latest version of this license is in * 46 | * 47 | http://www.latex-project.org/lppl.txt * 48 | * 49 | and version 1.3c or later is part of all distributions of LaTeX * 50 | version 2008 or later. * 51 | * 52 | This work has the LPPL maintenance status `maintained'. * 53 | * 54 | The Current Maintainer of this work is Mingyu Xia. * 55 | ----------------------------------------------------------------------- 56 | \endpreamble 57 | 58 | \postamble 59 | ----------------------------------------------------------------------- 60 | This work consists of the files litetable.dtx, * 61 | litetable.ins, * 62 | the derived files litetable.sty, * 63 | the documentation files litetable.pdf, * 64 | and README.md. * 65 | ----------------------------------------------------------------------- 66 | \endpostamble 67 | 68 | \keepsilent 69 | 70 | \generate{ 71 | \usedir{tex/latex/litetable} 72 | \file{\jobname.sty} {\from{\jobname.dtx}{package}} 73 | \usedir{doc/latex/litetable} 74 | \nopreamble\nopostamble 75 | \file{README.md} {\from{\jobname.dtx}{readme}} 76 | } 77 | 78 | \endbatchfile 79 | \endinput 80 | %% 81 | %% End of file `litetable.ins' 82 | -------------------------------------------------------------------------------- /litetable-zh-cn.tex: -------------------------------------------------------------------------------- 1 | \documentclass[svgnames]{l3doc} 2 | \usepackage{pdfpages, twemojis} 3 | \usepackage[osf, mono = false]{libertine} 4 | \usepackage[fontset = fandol, linespread = 1.2, autoindent = 0pt]{ctex} 5 | \AddToHook{env/function/before}{\vspace*{-.5\baselineskip}} 6 | \ExplSyntaxOn \makeatletter 7 | \DeclareDocumentCommand \key { s m } 8 | { 9 | \IfBooleanTF {#1} { \textcolor{red}{\ttfamily \bfseries #2} } 10 | { 11 | \ttfamily 12 | \seq_set_from_clist:Nn \l_tmpa_seq {#2} 13 | \seq_set_map:NNn \l_tmpb_seq \l_tmpa_seq 14 | { \exp_not:n { \textcolor{red}{\bfseries ##1} } } 15 | \seq_use:Nn \l_tmpb_seq { ,~ } \:=\: 16 | } 17 | } 18 | \DeclareCommandCopy \val \meta 19 | \def \TFF {true\textup{\textbar\underline{\textbf{false}}}} 20 | \def \TTF {\textup{\underline{\textbf{true}}\textbar}false} 21 | \def \HoLogo@ApLaTeX #1{ 22 | \HOLOGO@mbox {A\kern -.05em p\kern -.05em \hologo{LaTeX}}} 23 | \makeatother \ExplSyntaxOff 24 | \newlist{keyval}{itemize}{10} 25 | \setlist[keyval]{leftmargin = 0pt, labelsep = 0pt} 26 | \makeindex 27 | \title{^^A 28 | \bfseries \cls{litetable} 宏包 --- 多彩的课程表\thanks{^^A 29 | \url{https://github.com/myhsia/litetable}, 30 | \url{https://ctan.org/pkg/litetable}^^A 31 | }^^A 32 | } 33 | \author{^^A 34 | 夏明宇 \texttt{<^^A 35 | \href{mailto:xiamingyu@westlake.edu.cn}{xiamingyu@westlake.edu.cn}>^^A 36 | }\thanks{^^A 37 | \href{https://github.com/ljguo1020}{郭李军}^^A 38 | 开发了解析 \meta{left} \texttt{->} \meta{right} 型数据结构的接口.^^A 39 | }^^A 40 | } 41 | \date{Released 2025-11-15\quad \texttt{v3.8C}} 42 | 43 | \begin{document} 44 | 45 | \maketitle 46 | 47 | \begin{documentation} 48 | 49 | \section{介绍} 50 | 51 | \pkg{litetable} 宏包提供了一个多彩的课程表设计, 52 | 基于 Ti\textit k\/Z 53 | 由 \pkg{expl3} 开发. 54 | 支持 \hologo{pdfLaTeX},\hologo{XeLaTeX},\hologo{ApLaTeX} 和 55 | \hologo{LuaLaTeX} 等多种编译方式. 点击跳转 56 | \href{http://mirrors.ctan.org/macros/latex/contrib/litetable/litetable.pdf}{[\textsf{English}]} 57 | \href{http://mirrors.ctan.org/macros/latex/contrib/litetable/litetable-zh-hk.pdf}{[\textsf{繁体粤語}]} 手册. 58 | 59 | \section{用户接口} 60 | 61 | 要加载此宏包,只需写下 62 | \begin{quote} 63 | |\usepackage{litetable}| 64 | \end{quote} 65 | 66 | \DescribeEnv{litetable} 67 | 环境 \env{litetable} 可生成空白课程表, 68 | 需在命令 \cs{timelist} 和 \cs{weeklist} 后执行 69 | \begin{quote} 70 | |\begin{litetable}| 71 | \oarg{keys} \marg{title} \oarg{keys}| ... |% 72 | |\end{litetable}| 73 | \end{quote} 74 | 强制参数用于设定课程表标题, 75 | 可选参数接受以下键 76 | \begin{keyval} 77 | \item [\key{scale}] \textcolor{gray}{\val{float} 可设置课程表的缩放比例(默认值: |1.0|).} 78 | \item [\key{color}] \val{color} 可设置课程表框架的背景色 79 | (默认值:|gray|),键名可省略. 80 | \item [\key{sem}] \val{string} 81 | 可设置页面右上角的学期信息. 82 | \item [\key{hline}] \val{string} 可设置水平线的样式 83 | (默认值:|solid|). 84 | \end{keyval} 85 | 86 | \begin{function}{\weeklist} 87 | \begin{syntax} 88 | \cs{weeklist} \oarg{keys} \marg{list} \oarg{keys} 89 | \end{syntax} 90 | 强制参数接收数组, 91 | 用于设置课程表顶部的工作日列表和列宽. 92 | 可选参数接受以下键 93 | \begin{keyval} 94 | \item [\key{format}] \val{format commands} 95 | 可设置工作日列表格式(默认值:|\bfseries|). 96 | \item [\key{sep}] \val{string} 97 | 可设置工作日列表的分隔符. 98 | \end{keyval} 99 | \begin{verbatim} 100 | \weeklist [ format = \bfseries \scshape, sep = \textbar ] 101 | { Mon -> 1.05, Tue -> 1.05, Wed -> 1.1, Thu -> 1.1, Fri -> .9 } 102 | \end{verbatim} 103 | \end{function} 104 | 105 | \begin{function}{\timelist} 106 | \begin{syntax} 107 | \cs{timelist} \oarg{keys} \marg{list} \oarg{keys} 108 | \end{syntax} 109 | 强制参数均接收数组,用于设置课程表的左侧的时间列表. 110 | 可选参数接受以下键 111 | \begin{keyval} 112 | \item [\key{numformat}] \val{format} 113 | 可设置时间列表的序号字体 114 | (默认值:|\ttfamily \bfseries|). 115 | \item [\key{timeformat}] \val{format} 可设置时间列表的时间字体 116 | (默认值:|\ttfamily|). 117 | \item [\key{hidetime}] \val\TFF 用于隐藏时间列表中的时间,只保留序号. 118 | (初始值:|false|). 119 | \end{keyval} 120 | \begin{verbatim} 121 | \timelist [ numformat = \bfseries, timeformat = \ttfamily ] 122 | { 08:30 -> 10:00, 10:30 -> 12:00, 13:00 -> 14:30, 15:00 -> 16:30 } 123 | \end{verbatim} 124 | \end{function} 125 | 126 | \begin{function}{\course} 127 | \begin{syntax} 128 | \cs{course} \oarg{keys} \marg{start} \oarg{keys} \marg{end} \oarg{keys} 129 | \end{syntax} 130 | 用于在当前工作日添加课程盒子, 131 | 需在 \env{litetable} 环境中执行. 132 | 两个强制参数分别用于设置课程的开始和结束序号. 133 | 可选参数接收下列键 134 | \begin{keyval} 135 | \item [\key{color}] \val{color} 用于设置课程盒子的颜色 136 | (默认值:|teal|). 键名可省略. 137 | \item [\key{subject}] \val{string} 用于设置课程名称. 138 | \item [\key{location}] \val{string} 用于设置课程地点. 139 | \item [\key{lecture}] \val{string} 用于设置授课教师. 140 | \item [\key{comment}] \val{string} 用于给课程添加脚注. 141 | \end{keyval} 142 | \begin{texnote} 143 | \begin{itemize}[leftmargin = 2em] 144 | \item 若 \meta{start} |=| \meta{end}(课程盒子的高度为 $1$), 145 | 则 \key*{location} 和 \key*{lecture} 将输出在同一行, 146 | 并且 \key*{comment} 将隐藏. 147 | \item 即使误将 \meta{start} 和 \meta{end} 写反, 148 | 模板也会自动纠正. 149 | \item 若 \key*{location} 和 \key*{lecture} 均未使用, 150 | 则 \key*{subject} 将输出在课程盒子的 151 | 竖直方向中心. 152 | \item 超出课程表范围的课程盒子将不显示, 153 | 并会返回警告. 154 | 输入用例见 Appendix \ref{mwe}. 155 | \end{itemize} 156 | \end{texnote} 157 | \end{function} 158 | 159 | \begin{function}{\newday} 160 | \begin{syntax} 161 | \cs{newday} \oarg{integral value} 162 | \end{syntax} 163 | 使其后面添加的课程盒子后移 \meta{intergal value} 个工作日. 164 | 可选参数的默认值为 |1|. 165 | \end{function} 166 | 167 | \begin{function}{\more} 168 | \begin{syntax} 169 | \cs{more} \marg{comment} 170 | \end{syntax} 171 | 在课程表的右下角添加备注. 172 | \end{function} 173 | 174 | \clearpage \linespread{1.25} 175 | 176 | \section{工作示例} \label{mwe} 177 | 178 | \verbatiminput{litetable-demo.tex} 179 | 180 | \includepdf{litetable-demo.pdf} 181 | 182 | \end{documentation} 183 | 184 | \appendix \pagenumbering{Roman} 185 | 186 | \includepdf[pages = 5-13, link]{./litetable.pdf} 187 | 188 | \IndexPrologue{% 189 | \part*{索引} 190 | \markboth{索引}{索引} 191 | \addcontentsline{toc}{part}{索引} 192 | 意大利体的数字表示描述对应索引项的页码; 193 | 带下划线的数字表示定义对应索引项的代码行号; 194 | 罗马字体的数字表示使用对应索引项的代码行号. 195 | } 196 | 197 | \PrintIndex 198 | 199 | \end{document} 200 | -------------------------------------------------------------------------------- /litetable-zh-hk.tex: -------------------------------------------------------------------------------- 1 | \documentclass[svgnames]{l3doc} 2 | \usepackage{pdfpages, twemojis} 3 | \usepackage[osf, mono = false]{libertine} 4 | \usepackage[fontset = fandol, linespread = 1.2, autoindent = 0pt]{ctex} 5 | \AddToHook{env/function/before}{\vspace*{-.5\baselineskip}} 6 | \ExplSyntaxOn \makeatletter 7 | \DeclareDocumentCommand \key { s m } 8 | { 9 | \IfBooleanTF {#1} { \textcolor{red}{\ttfamily \bfseries #2} } 10 | { 11 | \ttfamily 12 | \seq_set_from_clist:Nn \l_tmpa_seq {#2} 13 | \seq_set_map:NNn \l_tmpb_seq \l_tmpa_seq 14 | { \exp_not:n { \textcolor{red}{\bfseries ##1} } } 15 | \seq_use:Nn \l_tmpb_seq { ,~ } \:=\: 16 | } 17 | } 18 | \DeclareCommandCopy \val \meta 19 | \def \TFF {true\textup{\textbar\underline{\textbf{false}}}} 20 | \def \TTF {\textup{\underline{\textbf{true}}\textbar}false} 21 | \def \HoLogo@ApLaTeX #1{ 22 | \HOLOGO@mbox {A\kern -.05em p\kern -.05em \hologo{LaTeX}}} 23 | \makeatother \ExplSyntaxOff 24 | \newlist{keyval}{itemize}{10} 25 | \setlist[keyval]{leftmargin = 0pt, labelsep = 0pt} 26 | \makeindex 27 | \title{^^A 28 | \bfseries \cls{litetable} 宏包 --- 多彩的課程表\thanks{^^A 29 | \url{https://github.com/myhsia/litetable}, 30 | \url{https://ctan.org/pkg/litetable}^^A 31 | }^^A 32 | } 33 | \author{^^A 34 | 夏明宇 \texttt{<^^A 35 | \href{mailto:xiamingyu@westlake.edu.cn}{xiamingyu@westlake.edu.cn}>^^A 36 | }\thanks{^^A 37 | \href{https://github.com/ljguo1020}{郭李軍}^^A 38 | 開發了解析 \meta{left} \texttt{->} \meta{right} 型數據結構的接口.^^A 39 | }^^A 40 | } 41 | \date{Released 2025-11-15\quad \texttt{v3.8C}} 42 | 43 | \begin{document} 44 | 45 | \maketitle 46 | 47 | \begin{documentation} 48 | 49 | \section{介紹} 50 | 51 | \pkg{litetable} 宏包提供了一個多彩的課程表設計, 52 | 基於 Ti\textit k\/Z 53 | 由 \pkg{expl3} 開發. 54 | 支援 \hologo{pdfLaTeX},\hologo{XeLaTeX},\hologo{ApLaTeX} 同 55 | \hologo{LuaLaTeX} 等多種編譯方式. 點擊跳轉 56 | \href{http://mirrors.ctan.org/macros/latex/contrib/litetable/litetable.pdf}{[\textsf{English}]} 57 | \href{http://mirrors.ctan.org/macros/latex/contrib/litetable/litetable-zh-cn.pdf}{[\textsf{简体中文}]} 手册. 58 | 59 | \section{用户接口} 60 | 61 | 要加載此宏包,只需寫下 62 | \begin{quote} 63 | |\usepackage{litetable}| 64 | \end{quote} 65 | 66 | \DescribeEnv{litetable} 67 | 環境 \env{litetable} 可生成空白課程表, 68 | 需在命令 \cs{timelist} 同 \cs{weeklist} 後執行 69 | \begin{quote} 70 | |\begin{litetable}| 71 | \oarg{keys} \marg{title} \oarg{keys}| ... |% 72 | |\end{litetable}| 73 | \end{quote} 74 | 强制參數用於設定課程表標題, 75 | 可選參數接受以下鍵 76 | \begin{keyval} 77 | \item [\key{scale}] \textcolor{gray}{\val{float} 可設定課程表的縮放比例(默認值: |1.0|).} 78 | \item [\key{color}] \val{color} 可設定課程表框架的背景色 79 | (默認值:|gray|),鍵名可省略. 80 | \item [\key{sem}] \val{string} 81 | 可設定頁面右上角的學期信息. 82 | \item [\key{hline}] \val{string} 可設定水平线的樣式 83 | (默認值:|solid|). 84 | \end{keyval} 85 | 86 | \begin{function}{\weeklist} 87 | \begin{syntax} 88 | \cs{weeklist} \oarg{keys} \marg{list} \oarg{keys} 89 | \end{syntax} 90 | 强制參數接收數組, 91 | 用於設定課程表頂部的工作日列表同列寬. 92 | 可選參數接受以下鍵 93 | \begin{keyval} 94 | \item [\key{format}] \val{format commands} 95 | 可設置工作日列表格式(默認值:|\bfseries|). 96 | \item [\key{sep}] \val{string} 97 | 可設定工作日列表的分隔符. 98 | \end{keyval} 99 | \begin{verbatim} 100 | \weeklist [ format = \bfseries \scshape, sep = \textbar ] 101 | { Mon -> 1.05, Tue -> 1.05, Wed -> 1.1, Thu -> 1.1, Fri -> .9 } 102 | \end{verbatim} 103 | \end{function} 104 | 105 | \begin{function}{\timelist} 106 | \begin{syntax} 107 | \cs{timelist} \oarg{keys} \marg{list} \oarg{keys} 108 | \end{syntax} 109 | 强制參數均接收數組,用於設置課程表的左側的時間列表. 110 | 可選參數接受以下鍵 111 | \begin{keyval} 112 | \item [\key{numformat}] \val{format} 113 | 可設定時間列表的序號字體 114 | (默認值:|\ttfamily \bfseries|). 115 | \item [\key{timeformat}] \val{format} 可設定時間列表的時間字體 116 | (默認值:|\ttfamily|). 117 | \item [\key{hidetime}] \val\TFF 用於隱藏時間列表中的時間,只保留序號 118 | (初始值:|false|). 119 | \end{keyval} 120 | \begin{verbatim} 121 | \timelist [ numformat = \bfseries, timeformat = \ttfamily ] 122 | { 08:30 -> 10:00, 10:30 -> 12:00, 13:00 -> 14:30, 15:00 -> 16:30 } 123 | \end{verbatim} 124 | \end{function} 125 | 126 | \begin{function}{\course} 127 | \begin{syntax} 128 | \cs{course} \oarg{keys} \marg{start} \oarg{keys} \marg{end} \oarg{keys} 129 | \end{syntax} 130 | 用於在當前工作日添加課程盒子, 131 | 需在 \env{litetable} 環境中執行. 132 | 兩個强制參數分别用於設置課程的開始同結束序號. 133 | 可選參數接收下列鍵 134 | \begin{keyval} 135 | \item [\key{color}] \val{color} 用於設置課程盒子的颜色 136 | (默認值:|teal|). 鍵名可省略. 137 | \item [\key{subject}] \val{string} 用於設置課程名稱. 138 | \item [\key{location}] \val{string} 用於設置課程地點. 139 | \item [\key{lecture}] \val{string} 用於設置授課教師. 140 | \item [\key{comment}] \val{string} 用於給課程添加脚注. 141 | \end{keyval} 142 | \begin{texnote} 143 | \begin{itemize}[leftmargin = 2em] 144 | \item 若 \meta{start} |=| \meta{end}(課程盒子的高度为 $1$), 145 | 若 \key*{location} 和 \key*{lecture} 會輸出在同一行, 146 | 而且 \key*{comment} 將隱藏. 147 | \item 即使誤將 \meta{start} 同 \meta{end} 寫反, 148 | 模板也會自動糾正. 149 | \item 若 \key*{location} 同 \key*{lecture} 均未使用, 150 | 則 \key*{subject} 將輸出在課程盒子的 151 | 竖直方向中心. 152 | \item 超出課程表範圍的課程盒子將唔顯示, 153 | 并會返回警告. 154 | 輸入用例見 Appendix \ref{mwe}. 155 | \end{itemize} 156 | \end{texnote} 157 | \end{function} 158 | 159 | \begin{function}{\newday} 160 | \begin{syntax} 161 | \cs{newday} \oarg{integral value} 162 | \end{syntax} 163 | 使其後面添加的課程盒子後移 \meta{intergal value} 個工作日. 164 | 可選參數的默認值为 |1|. 165 | \end{function} 166 | 167 | \begin{function}{\more} 168 | \begin{syntax} 169 | \cs{more} \marg{comment} 170 | \end{syntax} 171 | 在課程表的右下角添加備注. 172 | \end{function} 173 | 174 | \clearpage \linespread{1.25} 175 | 176 | \section{工作範例} \label{mwe} 177 | 178 | \verbatiminput{litetable-demo.tex} 179 | 180 | \includepdf{litetable-demo.pdf} 181 | 182 | \end{documentation} 183 | 184 | \appendix \pagenumbering{Roman} 185 | 186 | \includepdf[pages = 5-13, link]{./litetable.pdf} 187 | 188 | \IndexPrologue{% 189 | \part*{索引} 190 | \markboth{索引}{索引} 191 | \addcontentsline{toc}{part}{索引} 192 | 意大利體的數字表示描述對應索引項的頁碼; 193 | 帶下劃綫的數字表示定義對應索引項的代碼行號; 194 | 羅馬字體的數字表示使用對應索引項的代碼行號. 195 | } 196 | 197 | \PrintIndex 198 | 199 | \end{document} 200 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The LaTeX Project Public License 2 | =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- 3 | 4 | LPPL Version 1.3c 2008-05-04 5 | 6 | Copyright 1999 2002-2008 LaTeX3 Project 7 | Everyone is allowed to distribute verbatim copies of this 8 | license document, but modification of it is not allowed. 9 | 10 | 11 | PREAMBLE 12 | ======== 13 | 14 | The LaTeX Project Public License (LPPL) is the primary license under 15 | which the LaTeX kernel and the base LaTeX packages are distributed. 16 | 17 | You may use this license for any work of which you hold the copyright 18 | and which you wish to distribute. This license may be particularly 19 | suitable if your work is TeX-related (such as a LaTeX package), but 20 | it is written in such a way that you can use it even if your work is 21 | unrelated to TeX. 22 | 23 | The section `WHETHER AND HOW TO DISTRIBUTE WORKS UNDER THIS LICENSE', 24 | below, gives instructions, examples, and recommendations for authors 25 | who are considering distributing their works under this license. 26 | 27 | This license gives conditions under which a work may be distributed 28 | and modified, as well as conditions under which modified versions of 29 | that work may be distributed. 30 | 31 | We, the LaTeX3 Project, believe that the conditions below give you 32 | the freedom to make and distribute modified versions of your work 33 | that conform with whatever technical specifications you wish while 34 | maintaining the availability, integrity, and reliability of 35 | that work. If you do not see how to achieve your goal while 36 | meeting these conditions, then read the document `cfgguide.tex' 37 | and `modguide.tex' in the base LaTeX distribution for suggestions. 38 | 39 | 40 | DEFINITIONS 41 | =========== 42 | 43 | In this license document the following terms are used: 44 | 45 | `Work' 46 | Any work being distributed under this License. 47 | 48 | `Derived Work' 49 | Any work that under any applicable law is derived from the Work. 50 | 51 | `Modification' 52 | Any procedure that produces a Derived Work under any applicable 53 | law -- for example, the production of a file containing an 54 | original file associated with the Work or a significant portion of 55 | such a file, either verbatim or with modifications and/or 56 | translated into another language. 57 | 58 | `Modify' 59 | To apply any procedure that produces a Derived Work under any 60 | applicable law. 61 | 62 | `Distribution' 63 | Making copies of the Work available from one person to another, in 64 | whole or in part. Distribution includes (but is not limited to) 65 | making any electronic components of the Work accessible by 66 | file transfer protocols such as FTP or HTTP or by shared file 67 | systems such as Sun's Network File System (NFS). 68 | 69 | `Compiled Work' 70 | A version of the Work that has been processed into a form where it 71 | is directly usable on a computer system. This processing may 72 | include using installation facilities provided by the Work, 73 | transformations of the Work, copying of components of the Work, or 74 | other activities. Note that modification of any installation 75 | facilities provided by the Work constitutes modification of the Work. 76 | 77 | `Current Maintainer' 78 | A person or persons nominated as such within the Work. If there is 79 | no such explicit nomination then it is the `Copyright Holder' under 80 | any applicable law. 81 | 82 | `Base Interpreter' 83 | A program or process that is normally needed for running or 84 | interpreting a part or the whole of the Work. 85 | 86 | A Base Interpreter may depend on external components but these 87 | are not considered part of the Base Interpreter provided that each 88 | external component clearly identifies itself whenever it is used 89 | interactively. Unless explicitly specified when applying the 90 | license to the Work, the only applicable Base Interpreter is a 91 | `LaTeX-Format' or in the case of files belonging to the 92 | `LaTeX-format' a program implementing the `TeX language'. 93 | 94 | 95 | 96 | CONDITIONS ON DISTRIBUTION AND MODIFICATION 97 | =========================================== 98 | 99 | 1. Activities other than distribution and/or modification of the Work 100 | are not covered by this license; they are outside its scope. In 101 | particular, the act of running the Work is not restricted and no 102 | requirements are made concerning any offers of support for the Work. 103 | 104 | 2. You may distribute a complete, unmodified copy of the Work as you 105 | received it. Distribution of only part of the Work is considered 106 | modification of the Work, and no right to distribute such a Derived 107 | Work may be assumed under the terms of this clause. 108 | 109 | 3. You may distribute a Compiled Work that has been generated from a 110 | complete, unmodified copy of the Work as distributed under Clause 2 111 | above, as long as that Compiled Work is distributed in such a way that 112 | the recipients may install the Compiled Work on their system exactly 113 | as it would have been installed if they generated a Compiled Work 114 | directly from the Work. 115 | 116 | 4. If you are the Current Maintainer of the Work, you may, without 117 | restriction, modify the Work, thus creating a Derived Work. You may 118 | also distribute the Derived Work without restriction, including 119 | Compiled Works generated from the Derived Work. Derived Works 120 | distributed in this manner by the Current Maintainer are considered to 121 | be updated versions of the Work. 122 | 123 | 5. If you are not the Current Maintainer of the Work, you may modify 124 | your copy of the Work, thus creating a Derived Work based on the Work, 125 | and compile this Derived Work, thus creating a Compiled Work based on 126 | the Derived Work. 127 | 128 | 6. If you are not the Current Maintainer of the Work, you may 129 | distribute a Derived Work provided the following conditions are met 130 | for every component of the Work unless that component clearly states 131 | in the copyright notice that it is exempt from that condition. Only 132 | the Current Maintainer is allowed to add such statements of exemption 133 | to a component of the Work. 134 | 135 | a. If a component of this Derived Work can be a direct replacement 136 | for a component of the Work when that component is used with the 137 | Base Interpreter, then, wherever this component of the Work 138 | identifies itself to the user when used interactively with that 139 | Base Interpreter, the replacement component of this Derived Work 140 | clearly and unambiguously identifies itself as a modified version 141 | of this component to the user when used interactively with that 142 | Base Interpreter. 143 | 144 | b. Every component of the Derived Work contains prominent notices 145 | detailing the nature of the changes to that component, or a 146 | prominent reference to another file that is distributed as part 147 | of the Derived Work and that contains a complete and accurate log 148 | of the changes. 149 | 150 | c. No information in the Derived Work implies that any persons, 151 | including (but not limited to) the authors of the original version 152 | of the Work, provide any support, including (but not limited to) 153 | the reporting and handling of errors, to recipients of the 154 | Derived Work unless those persons have stated explicitly that 155 | they do provide such support for the Derived Work. 156 | 157 | d. You distribute at least one of the following with the Derived Work: 158 | 159 | 1. A complete, unmodified copy of the Work; 160 | if your distribution of a modified component is made by 161 | offering access to copy the modified component from a 162 | designated place, then offering equivalent access to copy 163 | the Work from the same or some similar place meets this 164 | condition, even though third parties are not compelled to 165 | copy the Work along with the modified component; 166 | 167 | 2. Information that is sufficient to obtain a complete, 168 | unmodified copy of the Work. 169 | 170 | 7. If you are not the Current Maintainer of the Work, you may 171 | distribute a Compiled Work generated from a Derived Work, as long as 172 | the Derived Work is distributed to all recipients of the Compiled 173 | Work, and as long as the conditions of Clause 6, above, are met with 174 | regard to the Derived Work. 175 | 176 | 8. The conditions above are not intended to prohibit, and hence do not 177 | apply to, the modification, by any method, of any component so that it 178 | becomes identical to an updated version of that component of the Work as 179 | it is distributed by the Current Maintainer under Clause 4, above. 180 | 181 | 9. Distribution of the Work or any Derived Work in an alternative 182 | format, where the Work or that Derived Work (in whole or in part) is 183 | then produced by applying some process to that format, does not relax or 184 | nullify any sections of this license as they pertain to the results of 185 | applying that process. 186 | 187 | 10. a. A Derived Work may be distributed under a different license 188 | provided that license itself honors the conditions listed in 189 | Clause 6 above, in regard to the Work, though it does not have 190 | to honor the rest of the conditions in this license. 191 | 192 | b. If a Derived Work is distributed under a different license, that 193 | Derived Work must provide sufficient documentation as part of 194 | itself to allow each recipient of that Derived Work to honor the 195 | restrictions in Clause 6 above, concerning changes from the Work. 196 | 197 | 11. This license places no restrictions on works that are unrelated to 198 | the Work, nor does this license place any restrictions on aggregating 199 | such works with the Work by any means. 200 | 201 | 12. Nothing in this license is intended to, or may be used to, prevent 202 | complete compliance by all parties with all applicable laws. 203 | 204 | 205 | NO WARRANTY 206 | =========== 207 | 208 | There is no warranty for the Work. Except when otherwise stated in 209 | writing, the Copyright Holder provides the Work `as is', without 210 | warranty of any kind, either expressed or implied, including, but not 211 | limited to, the implied warranties of merchantability and fitness for a 212 | particular purpose. The entire risk as to the quality and performance 213 | of the Work is with you. Should the Work prove defective, you assume 214 | the cost of all necessary servicing, repair, or correction. 215 | 216 | In no event unless required by applicable law or agreed to in writing 217 | will The Copyright Holder, or any author named in the components of the 218 | Work, or any other party who may distribute and/or modify the Work as 219 | permitted above, be liable to you for damages, including any general, 220 | special, incidental or consequential damages arising out of any use of 221 | the Work or out of inability to use the Work (including, but not limited 222 | to, loss of data, data being rendered inaccurate, or losses sustained by 223 | anyone as a result of any failure of the Work to operate with any other 224 | programs), even if the Copyright Holder or said author or said other 225 | party has been advised of the possibility of such damages. 226 | 227 | 228 | MAINTENANCE OF THE WORK 229 | ======================= 230 | 231 | The Work has the status `author-maintained' if the Copyright Holder 232 | explicitly and prominently states near the primary copyright notice in 233 | the Work that the Work can only be maintained by the Copyright Holder 234 | or simply that it is `author-maintained'. 235 | 236 | The Work has the status `maintained' if there is a Current Maintainer 237 | who has indicated in the Work that they are willing to receive error 238 | reports for the Work (for example, by supplying a valid e-mail 239 | address). It is not required for the Current Maintainer to acknowledge 240 | or act upon these error reports. 241 | 242 | The Work changes from status `maintained' to `unmaintained' if there 243 | is no Current Maintainer, or the person stated to be Current 244 | Maintainer of the work cannot be reached through the indicated means 245 | of communication for a period of six months, and there are no other 246 | significant signs of active maintenance. 247 | 248 | You can become the Current Maintainer of the Work by agreement with 249 | any existing Current Maintainer to take over this role. 250 | 251 | If the Work is unmaintained, you can become the Current Maintainer of 252 | the Work through the following steps: 253 | 254 | 1. Make a reasonable attempt to trace the Current Maintainer (and 255 | the Copyright Holder, if the two differ) through the means of 256 | an Internet or similar search. 257 | 258 | 2. If this search is successful, then enquire whether the Work 259 | is still maintained. 260 | 261 | a. If it is being maintained, then ask the Current Maintainer 262 | to update their communication data within one month. 263 | 264 | b. If the search is unsuccessful or no action to resume active 265 | maintenance is taken by the Current Maintainer, then announce 266 | within the pertinent community your intention to take over 267 | maintenance. (If the Work is a LaTeX work, this could be 268 | done, for example, by posting to comp.text.tex.) 269 | 270 | 3a. If the Current Maintainer is reachable and agrees to pass 271 | maintenance of the Work to you, then this takes effect 272 | immediately upon announcement. 273 | 274 | b. If the Current Maintainer is not reachable and the Copyright 275 | Holder agrees that maintenance of the Work be passed to you, 276 | then this takes effect immediately upon announcement. 277 | 278 | 4. If you make an `intention announcement' as described in 2b. above 279 | and after three months your intention is challenged neither by 280 | the Current Maintainer nor by the Copyright Holder nor by other 281 | people, then you may arrange for the Work to be changed so as 282 | to name you as the (new) Current Maintainer. 283 | 284 | 5. If the previously unreachable Current Maintainer becomes 285 | reachable once more within three months of a change completed 286 | under the terms of 3b) or 4), then that Current Maintainer must 287 | become or remain the Current Maintainer upon request provided 288 | they then update their communication data within one month. 289 | 290 | A change in the Current Maintainer does not, of itself, alter the fact 291 | that the Work is distributed under the LPPL license. 292 | 293 | If you become the Current Maintainer of the Work, you should 294 | immediately provide, within the Work, a prominent and unambiguous 295 | statement of your status as Current Maintainer. You should also 296 | announce your new status to the same pertinent community as 297 | in 2b) above. 298 | 299 | 300 | WHETHER AND HOW TO DISTRIBUTE WORKS UNDER THIS LICENSE 301 | ====================================================== 302 | 303 | This section contains important instructions, examples, and 304 | recommendations for authors who are considering distributing their 305 | works under this license. These authors are addressed as `you' in 306 | this section. 307 | 308 | Choosing This License or Another License 309 | ---------------------------------------- 310 | 311 | If for any part of your work you want or need to use *distribution* 312 | conditions that differ significantly from those in this license, then 313 | do not refer to this license anywhere in your work but, instead, 314 | distribute your work under a different license. You may use the text 315 | of this license as a model for your own license, but your license 316 | should not refer to the LPPL or otherwise give the impression that 317 | your work is distributed under the LPPL. 318 | 319 | The document `modguide.tex' in the base LaTeX distribution explains 320 | the motivation behind the conditions of this license. It explains, 321 | for example, why distributing LaTeX under the GNU General Public 322 | License (GPL) was considered inappropriate. Even if your work is 323 | unrelated to LaTeX, the discussion in `modguide.tex' may still be 324 | relevant, and authors intending to distribute their works under any 325 | license are encouraged to read it. 326 | 327 | A Recommendation on Modification Without Distribution 328 | ----------------------------------------------------- 329 | 330 | It is wise never to modify a component of the Work, even for your own 331 | personal use, without also meeting the above conditions for 332 | distributing the modified component. While you might intend that such 333 | modifications will never be distributed, often this will happen by 334 | accident -- you may forget that you have modified that component; or 335 | it may not occur to you when allowing others to access the modified 336 | version that you are thus distributing it and violating the conditions 337 | of this license in ways that could have legal implications and, worse, 338 | cause problems for the community. It is therefore usually in your 339 | best interest to keep your copy of the Work identical with the public 340 | one. Many works provide ways to control the behavior of that work 341 | without altering any of its licensed components. 342 | 343 | How to Use This License 344 | ----------------------- 345 | 346 | To use this license, place in each of the components of your work both 347 | an explicit copyright notice including your name and the year the work 348 | was authored and/or last substantially modified. Include also a 349 | statement that the distribution and/or modification of that 350 | component is constrained by the conditions in this license. 351 | 352 | Here is an example of such a notice and statement: 353 | 354 | %% pig.dtx 355 | %% Copyright 2008 M. Y. Name 356 | % 357 | % This work may be distributed and/or modified under the 358 | % conditions of the LaTeX Project Public License, either version 1.3 359 | % of this license or (at your option) any later version. 360 | % The latest version of this license is in 361 | % https://www.latex-project.org/lppl.txt 362 | % and version 1.3c or later is part of all distributions of LaTeX 363 | % version 2008 or later. 364 | % 365 | % This work has the LPPL maintenance status `maintained'. 366 | % 367 | % The Current Maintainer of this work is M. Y. Name. 368 | % 369 | % This work consists of the files pig.dtx and pig.ins 370 | % and the derived file pig.sty. 371 | 372 | Given such a notice and statement in a file, the conditions 373 | given in this license document would apply, with the `Work' referring 374 | to the three files `pig.dtx', `pig.ins', and `pig.sty' (the last being 375 | generated from `pig.dtx' using `pig.ins'), the `Base Interpreter' 376 | referring to any `LaTeX-Format', and both `Copyright Holder' and 377 | `Current Maintainer' referring to the person `M. Y. Name'. 378 | 379 | If you do not want the Maintenance section of LPPL to apply to your 380 | Work, change `maintained' above into `author-maintained'. 381 | However, we recommend that you use `maintained', as the Maintenance 382 | section was added in order to ensure that your Work remains useful to 383 | the community even when you can no longer maintain and support it 384 | yourself. 385 | 386 | Derived Works That Are Not Replacements 387 | --------------------------------------- 388 | 389 | Several clauses of the LPPL specify means to provide reliability and 390 | stability for the user community. They therefore concern themselves 391 | with the case that a Derived Work is intended to be used as a 392 | (compatible or incompatible) replacement of the original Work. If 393 | this is not the case (e.g., if a few lines of code are reused for a 394 | completely different task), then clauses 6b and 6d shall not apply. 395 | 396 | 397 | Important Recommendations 398 | ------------------------- 399 | 400 | Defining What Constitutes the Work 401 | 402 | The LPPL requires that distributions of the Work contain all the 403 | files of the Work. It is therefore important that you provide a 404 | way for the licensee to determine which files constitute the Work. 405 | This could, for example, be achieved by explicitly listing all the 406 | files of the Work near the copyright notice of each file or by 407 | using a line such as: 408 | 409 | % This work consists of all files listed in manifest.txt. 410 | 411 | in that place. In the absence of an unequivocal list it might be 412 | impossible for the licensee to determine what is considered by you 413 | to comprise the Work and, in such a case, the licensee would be 414 | entitled to make reasonable conjectures as to which files comprise 415 | the Work. 416 | -------------------------------------------------------------------------------- /litetable.dtx: -------------------------------------------------------------------------------- 1 | % \iffalse meta-comment 2 | % 3 | % File: litetable.dtx 4 | % ----------------------------------------------------------------------- 5 | % Copyright (C) 2023-2025 by Mingyu Xia * 6 | % * 7 | % This work may be distributed and/or modified under the conditions * 8 | % of the LaTeX Project Public License (LPPL), either version 1.3c of * 9 | % this license or (at your option) any later version. * 10 | % The latest version of this license is in * 11 | % * 12 | % http://www.latex-project.org/lppl.txt * 13 | % * 14 | % and version 1.3c or later is part of all distributions of LaTeX * 15 | % version 2008 or later. * 16 | % * 17 | % This work has the LPPL maintenance status `maintained'. * 18 | % * 19 | % The Current Maintainer of this work is Mingyu Xia. * 20 | % * 21 | % This work consists of the files litetable.dtx, * 22 | % litetable.ins, * 23 | % the derived files litetable.sty, * 24 | % the documentation files litetable.pdf, * 25 | % and README.md. * 26 | % ----------------------------------------------------------------------- 27 | % 28 | % Any modification of this file should ensure that the copyright and 29 | % license information is placed in the derived files. 30 | % 31 | % ----------------------------------------------------------------------- 32 | % 33 | %<*internal> 34 | \iffalse 35 | % 36 | % 37 | %<*readme> 38 | [![CTAN Version](https://img.shields.io/ctan/v/litetable)](https://ctan.org/pkg/litetable) 39 | [![GitHub Release](https://img.shields.io/github/v/release/myhsia/litetable)](https://github.com/myhsia/litetable/releases/latest) 40 | [![GitHub Last Commit](https://img.shields.io/github/last-commit/myhsia/litetable)](https://github.com/myhsia/litetable/commits) 41 | [![Actions Status](https://github.com/myhsia/litetable/actions/workflows/main.yaml/badge.svg?branch=main)](https://github.com/myhsia/litetable/actions) 42 | [![GitHub Repo stars](https://img.shields.io/github/stars/myhsia/litetable)](https://github.com/myhsia/litetable) 43 | 44 | The `litetable` Package 45 | ======================= 46 | 47 | The `litetable` package (conducted with LaTeX3) provides a colorful design 48 | of timetable. 49 | 50 | Overview 51 | -------- 52 | 53 | The package provides the `\course` macro 54 | 55 | \course [] {} [] {} [] 56 | 57 | to add colorful custom course block. 58 | 59 | See `litetable.pdf` for more. Happy TeXing! 60 | 61 | Issues 62 | ------ 63 | 64 | The issue tracker for `litetable` is currently located 65 | [on GitHub](https://github.com/myhsia/litetable/issues). 66 | 67 | Build status 68 | ------------ 69 | 70 | This project uses [GitHub Actions](https://github.com/features/actions) 71 | as a hosted continuous integration service. For each commit, the build status 72 | is tested using the current release of TeX Live. 73 | 74 | _Current build status:_ ![build status](https://github.com/myhsia/litetable/actions/workflows/main.yaml/badge.svg?branch=main) 75 | 76 | Copyright and License 77 | --------------------- 78 | 79 | Copyright (C) 2023-2025 by Mingyu Xia 80 | 81 | This work may be distributed and/or modified under the conditions 82 | of the LaTeX Project Public License (LPPL), either version 1.3c of 83 | this license or (at your option) any later version. 84 | The latest version of this license is in 85 | 86 | http://www.latex-project.org/lppl.txt 87 | 88 | and version 1.3c or later is part of all distributions of LaTeX 89 | version 2008 or later. 90 | 91 | This work has the LPPL maintenance status `maintained'. 92 | 93 | The Current Maintainer of this work is **Mingyu Xia**. 94 | % 95 | % 96 | %<*internal> 97 | \fi 98 | % 99 | % 100 | %<*driver> 101 | \documentclass[svgnames]{l3doc} 102 | \usepackage{pdfpages, twemojis} 103 | \usepackage[osf, mono = false]{libertine} 104 | \ExplSyntaxOn \makeatletter 105 | \DeclareDocumentCommand \key { s m } 106 | { 107 | \IfBooleanTF {#1} { \textcolor{red}{\ttfamily \bfseries #2} } 108 | { 109 | \ttfamily 110 | \seq_set_from_clist:Nn \l_tmpa_seq {#2} 111 | \seq_set_map:NNn \l_tmpb_seq \l_tmpa_seq 112 | { \exp_not:n { \textcolor{red}{\bfseries ##1} } } 113 | \seq_use:Nn \l_tmpb_seq { ,~ } \:=\: 114 | } 115 | } 116 | \DeclareCommandCopy \val \meta 117 | \def \TFF {true\textup{\textbar\underline{\textbf{false}}}} 118 | \def \TTF {\textup{\underline{\textbf{true}}\textbar}false} 119 | \makeatother \ExplSyntaxOff 120 | \newlist{keyval}{itemize}{10} 121 | \setlist[keyval]{leftmargin = 0pt, labelsep = 0pt} 122 | \makeindex 123 | \begin{document} 124 | \DocInput{\jobname.dtx} 125 | \end{document} 126 | % 127 | % \fi 128 | % 129 | % \title{^^A 130 | % The \cls{litetable} Package --- Colorful Timetable\thanks{^^A 131 | % \url{https://github.com/myhsia/litetable}, 132 | % \url{https://ctan.org/pkg/litetable}^^A 133 | % }^^A 134 | % } 135 | % 136 | % \author{^^A 137 | % Mingyu Xia \texttt{<^^A 138 | % \href{mailto:xiamingyu@westlake.edu.cn}{xiamingyu@westlake.edu.cn}>^^A 139 | % }\thanks{^^A 140 | % \href{https://github.com/ljguo1020}{Lijun Guo} developed an interface 141 | % to parse \meta{left} \texttt{->} \meta{right} data structures.^^A 142 | % }^^A 143 | % } 144 | % 145 | % \date{Released 2025-11-15\quad \texttt{v3.8C}} 146 | % 147 | % \maketitle 148 | % 149 | % \begin{documentation} 150 | % 151 | % \section{Introduction} 152 | % 153 | % The \cls{litetable} package provides a colorful design of timetable, developed 154 | % by \pkg{expl3} based on Ti\textit k\/Z. 155 | % It supports various compilation methods, 156 | % such as \hologo{pdfLaTeX}, \hologo{XeLaTeX}, \hologo{ApLaTeX}, 157 | % \hologo{LuaLaTeX}, etc. Click to jump to the manual's 158 | % \href{http://mirrors.ctan.org/macros/latex/contrib/litetable/litetable-zh-cn.pdf}{[\textsf{Chinese Version}]} 159 | % \href{http://mirrors.ctan.org/macros/latex/contrib/litetable/litetable-zh-hk.pdf}{[\textsf{Cantonese Version}]}. 160 | % 161 | % \section{Usage} 162 | % 163 | % To load this package, write the line 164 | % \begin{quote} 165 | % |\usepackage{litetable}| 166 | % \end{quote} 167 | % 168 | % \DescribeEnv{litetable} 169 | % The \env{litetable} environment can create a blank timetable frame, and it 170 | % should be executed after commands \cs{timelist} and \cs{weeklist}. 171 | % \begin{quote} 172 | % |\begin{litetable}| 173 | % \oarg{keys} \marg{title} \oarg{keys}| ... | 174 | % |\end{litetable}| 175 | % \end{quote} 176 | % The mandatory argument can set the title of the timetable, and the 177 | % optional argument accepts the following keys 178 | % \begin{keyval} 179 | % \item [\key{scale}] \textcolor{gray}{\val{float} can set the scale of the timetable (Default: |1.0|).} 180 | % \item [\key{color}] \val{string} can set the background color 181 | % (Default: |gray|), this key's name could be omitted. 182 | % \item [\key{sem}] \val{string} can set the semester information at the 183 | % northeast corner of the page. 184 | % \item [\key{hline}] \val{string} can set style of the horizontal lines 185 | % (Default: |solid|). 186 | % \end{keyval} 187 | % 188 | % \begin{function}{\weeklist} 189 | % \begin{syntax} 190 | % \cs{weeklist} \oarg{keys} \marg{list} \oarg{keys} 191 | % \end{syntax} 192 | % The mandatory argument accepts an array to set a list of working days and 193 | % the width of each column at the top of the timetable. 194 | % The optional argument accepts the following keys 195 | % \begin{keyval} 196 | % \item [\key{format}] \val{format commands} can set the font for the list 197 | % of working days (Default: |\bfseries|). 198 | % \item [\key{sep}] \val{dim} can set the separator of 199 | % the list of working days. 200 | % \end{keyval} 201 | % \begin{verbatim} 202 | % \weeklist [ format = \bfseries \scshape, sep = \textbar ] 203 | % { Mon -> 1.05, Tue -> 1.05, Wed -> 1.1, Thu -> 1.1, Fri -> .9 } 204 | % \end{verbatim} 205 | % \end{function} 206 | % 207 | % \begin{function}{\timelist} 208 | % \begin{syntax} 209 | % \cs{timelist} \oarg{keys} \marg{list} \oarg{keys} 210 | % \end{syntax} 211 | % The mandatory argument accepts an array to set the time list on the left 212 | % side of the timetable. The optional argument accepts the following keys 213 | % \begin{keyval} 214 | % \item [\key{numformat}] \val{format commands} can set the font for the 215 | % sequence number of the time list 216 | % (Default: |\ttfamily \bfseries|). 217 | % \item [\key{timeformat}] \val{format commands} can set the font for the 218 | % time of the time list. (Default: |\ttfamily|). 219 | % \item [\key{hidetime}] \val{\TFF} hide the time in the time list and only 220 | % retain the sequence number. The initial value is |false|. 221 | % \end{keyval} 222 | % \begin{verbatim} 223 | % \timelist [ numformat = \bfseries, timeformat = \ttfamily ] 224 | % { 08:30 -> 10:00, 10:30 -> 12:00, 13:00 -> 14:30, 15:00 -> 16:30 } 225 | % \end{verbatim} 226 | % \end{function} 227 | % 228 | % \begin{function}{\course} 229 | % \begin{syntax} 230 | % \cs{course} \oarg{keys} \marg{start} \oarg{keys} \marg{end} \oarg{keys} 231 | % \end{syntax} 232 | % It's used to add course boxes on the current workday, and needs to be 233 | % executed within the \env{litetable} environment. 234 | % The two mandatory arguments can set the start and ends of the course 235 | % respectively, the optional argument accepts the following keys 236 | % \begin{keyval} 237 | % \item [\key{color}] \val{string} can set the color of the course box 238 | % (Default: |teal|), this key's name could be omitted. 239 | % \item [\key{subject}] \val{string} can set the name of the course. 240 | % \item [\key{location}] \val{string} can set the location of the course. 241 | % \item [\key{lecture}] \val{string} can set the lecture of the course. 242 | % \item [\key{comment}] \val{string} can add footnote to the course. 243 | % \end{keyval} 244 | % \begin{texnote} 245 | % \begin{itemize}[leftmargin = 2em] 246 | % \item If \meta{start} |=| \meta{end} (the height of the 247 | % course box is $1$ unit), then \key*{location} and \key*{lecture} will be 248 | % outputted in the same line and \key*{comment} will be hidden. 249 | % \item The template will correct automatically if \meta{start} and 250 | % \meta{end} were misplaced. 251 | % \item If neither \key*{location} nor \key*{lecture} is assigned value, 252 | % then \key*{subject} will be outputted in the vertical center of the 253 | % course box. 254 | % \item Course boxes that exceed the range of the timetable won't 255 | % display and it will return a warning. 256 | % The input example refers to Appendix \ref{mwe}. 257 | % \end{itemize} 258 | % \end{texnote} 259 | % \end{function} 260 | % 261 | % \begin{function}{\newday} 262 | % \begin{syntax} 263 | % \cs{newday} \oarg{integral value} 264 | % \end{syntax} 265 | % It can move the next course boxes right \meta{integral value} working days. 266 | % The default value of the optional argument is |1|. 267 | % \end{function} 268 | % 269 | % \begin{function}{\more} 270 | % \begin{syntax} 271 | % \cs{more} \marg{comment} 272 | % \end{syntax} 273 | % It can add a comment at the southwest corner of the timetable. 274 | % \end{function} 275 | % 276 | % \clearpage \linespread{1.3} 277 | % 278 | % \section{Working Example} \label{mwe} 279 | % 280 | % \verbatiminput{litetable-demo.tex} 281 | % 282 | % \includepdf{litetable-demo.pdf} 283 | % 284 | % \end{documentation} 285 | % 286 | % \appendix \pagenumbering{Roman} 287 | % 288 | % \begin{implementation} 289 | % 290 | % \section{The Source Code} 291 | % 292 | % \begin{macrocode} 293 | %<*package> 294 | % \end{macrocode} 295 | % 296 | % \begin{macrocode} 297 | %<@@=ltbl> 298 | % \end{macrocode} 299 | % 300 | % \begin{macrocode} 301 | \ProvidesExplPackage {litetable} {2025-11-15} {v3.8C} 302 | {A Colorful Timetable Design} 303 | % \end{macrocode} 304 | % 305 | % \begin{macrocode} 306 | \RequirePackage{tikz} 307 | % \end{macrocode} 308 | % Warning Broadcast 309 | % \begin{macrocode} 310 | \cs_new_protected:Npn \@@_msg_new:nn #1#2 311 | { \msg_new:nnn { litetable } {#1} {#2} } 312 | \cs_new_protected:Npn \@@_msg_warning:n #1 313 | { \msg_warning:nn { litetable } {#1} } 314 | \@@_msg_new:nn { course } 315 | { \exp_not:N \course ~ box(s) ~ exceed ~ workdays ~ were ~ ignored } 316 | % \end{macrocode} 317 | % \begin{macro} 318 | % { 319 | % \@@_get_left:nN, \@@_get_right:nN, 320 | % \@@_get_left:eN, \@@_get_right:eN, 321 | % } 322 | % Handle \meta{left} |->| \meta{right} data structures 323 | % (by \href{https://github.com/ljguo1020}{Lijun Guo}) 324 | % \begin{macrocode} 325 | \cs_new_protected_nopar:Npn \@@_get_left:nN #1#2 326 | { 327 | \group_begin: \seq_set_split:Nnn \l_@@_tmpa_seq { -> } {#1} 328 | \exp_args:NNNe \group_end: 329 | \tl_set:Nn #2 { \seq_item:Nn \l_@@_tmpa_seq { 1 } } 330 | } 331 | \cs_new_protected_nopar:Npn \@@_get_right:nN #1#2 332 | { 333 | \group_begin: \seq_set_split:Nnn \l_@@_tmpa_seq { -> } {#1} 334 | \exp_args:NNNe \group_end: 335 | \tl_set:Nn #2 { \seq_item:Nn \l_@@_tmpa_seq { 2 } } 336 | } 337 | \cs_generate_variant:Nn \@@_get_left:nN { eN } 338 | \cs_generate_variant:Nn \@@_get_right:nN { eN } 339 | % \end{macrocode} 340 | % \end{macro} 341 | % 342 | % \subsection{User's Interface} 343 | % 344 | % \begin{macro}{\weeklist} 345 | % Set a list of working days and the width of each column at the top of the 346 | % timetable. 347 | % \begin{macrocode} 348 | \NewDocumentCommand \weeklist { O{} m O{} } 349 | { 350 | \keys_set:nn { litetable / weeklist } { #1, #3 } 351 | \@@_weeklist:n {#2} 352 | } 353 | % \end{macrocode} 354 | % \begin{variable}{\l_@@_weeklist_format_tl, \l_@@_weeklist_sep_tl} 355 | % Key--value definitions for the \cs{weeklist} command. 356 | % \begin{macrocode} 357 | \keys_define:nn { litetable / weeklist } 358 | { 359 | format .tl_set:N = \l_@@_weeklist_format_tl, 360 | format .initial:n = \bfseries, 361 | sep .tl_set:N = \l_@@_weeklist_sep_tl 362 | } 363 | % \end{macrocode} 364 | % \end{variable} 365 | % \end{macro} 366 | % \begin{macro}{\timelist} 367 | % Set the time list on the left side of the timetable. 368 | % \begin{macrocode} 369 | \NewDocumentCommand \timelist { O{} m O{} } 370 | { 371 | \keys_set:nn { litetable / timelist } { #1, #3 } 372 | \@@_timelist:n {#2} 373 | } 374 | % \end{macrocode} 375 | % \begin{variable} 376 | % { 377 | % \l_@@_timelist_numformat_tl, \l_@@_timelist_timeformat_tl, 378 | % \l_@@_timelist_hidetime_bool 379 | % } 380 | % Key--value definitions for the \cs{timelist} command. 381 | % \begin{macrocode} 382 | \keys_define:nn { litetable / timelist } 383 | { 384 | numformat .tl_set:N = \l_@@_timelist_numformat_tl, 385 | numformat .initial:n = \ttfamily \bfseries, 386 | timeformat .tl_set:N = \l_@@_timelist_timeformat_tl, 387 | timeformat .initial:n = \ttfamily, 388 | hidetime .bool_set:N = \l_@@_timelist_hidetime_bool, 389 | hidetime .initial:n = false, 390 | hidetime .default:n = true 391 | } 392 | % \end{macrocode} 393 | % \end{variable} 394 | % \end{macro} 395 | % \begin{variable}{\l_@@_textwidth_dim, \l_@@_textheight_dim} 396 | % Dimensions for the physical width and height of the timetable, 397 | % controlled by |\l_@@_scale_fp|. 398 | % \begin{macrocode} 399 | \dim_new:N \l_@@_textwidth_dim 400 | \dim_new:N \l_@@_textheight_dim 401 | % \end{macrocode} 402 | % \end{variable} 403 | % \begin{environment}{litetable} 404 | % Create a blank timetable frame. 405 | % \begin{macrocode} 406 | \NewDocumentEnvironment { litetable } { O{} m O{} } 407 | { 408 | \clearpage \thispagestyle{empty} 409 | \group_begin: 410 | \dim_gset:Nn \l_@@_textwidth_dim 411 | { \fp_eval:n { \l_@@_scale_fp } \paperwidth } 412 | \dim_gset:Nn \l_@@_textheight_dim 413 | { \fp_eval:n { \l_@@_scale_fp } \paperheight } 414 | \keys_set:nn { litetable / frame } { #1, #3 } 415 | \tikzpicture [ remember~picture, overlay ] 416 | \@@_maketable:n {#2} 417 | } { \endtikzpicture \group_end: \clearpage } 418 | % \end{macrocode} 419 | % \begin{variable} 420 | % { 421 | % \l_@@_scale_fp, \l_@@_bg_color_tl, 422 | % \l_@@_hline_type_tl, \l_@@_bg_sem_tl 423 | % } 424 | % Key--value definitions for the \env{litetable} command. 425 | % \begin{macrocode} 426 | \keys_define:nn { litetable / frame } 427 | { 428 | scale .fp_set:N = \l_@@_scale_fp, 429 | scale .initial:n = 1.0, 430 | color .tl_set:N = \l_@@_bg_color_tl, 431 | color .initial:n = gray, 432 | hline .tl_set:N = \l_@@_hline_type_tl, 433 | hline .initial:n = solid, 434 | sem .tl_set:N = \l_@@_bg_sem_tl, 435 | unknown .code:n = \tl_if_novalue:nF {#1} 436 | { \tl_set_eq:NN \l_@@_bg_color_tl \l_keys_key_tl } 437 | } 438 | % \end{macrocode} 439 | % \end{variable} 440 | % \end{environment} 441 | % \begin{macro}{\course} 442 | % Add course boxes on the current workday 443 | % \begin{macrocode} 444 | \NewDocumentCommand \course { O{} m O{} m O{} } 445 | { 446 | \group_begin: 447 | \bool_lazy_any:nTF 448 | { 449 | { 450 | \int_compare_p:nNn { \l_@@_weekday_int } > 451 | { \clist_count:N \l_@@_week_clist } 452 | } 453 | { \int_compare_p:nNn {#2} > { \clist_count:N \l_@@_time_clist } } 454 | { \int_compare_p:nNn {#4} > { \clist_count:N \l_@@_time_clist } } 455 | } { \@@_msg_warning:n { course } } 456 | { 457 | \keys_set:nn { litetable / course } { #1, #3, #5 } 458 | \int_compare:nNnTF {#2} < {#4} 459 | { \@@_course_box_aux:nn {#2} {#4} } 460 | { \@@_course_box_aux:nn {#4} {#2} } 461 | } 462 | \group_end: 463 | } 464 | % \end{macrocode} 465 | % \begin{variable} 466 | % { 467 | % \l_@@_course_color_tl , \l_@@_course_subject_tl, 468 | % \l_@@_course_lecture_tl , \l_@@_course_lecture_tl, 469 | % \l_@@_course_location_tl, \l_@@_course_comment_tl 470 | % } 471 | % Key--value definitions for the \cs{course} command. 472 | % \begin{macrocode} 473 | \keys_define:nn { litetable / course } 474 | { 475 | color .tl_set:N = \l_@@_course_color_tl, 476 | color .initial:n = black, 477 | subject .tl_set:N = \l_@@_course_subject_tl, 478 | lecture .tl_set:N = \l_@@_course_lecture_tl, 479 | location .tl_set:N = \l_@@_course_location_tl, 480 | comment .tl_set:N = \l_@@_course_comment_tl, 481 | unknown .code:n = \tl_if_novalue:nF {#1} 482 | { \tl_set_eq:NN \l_@@_course_color_tl \l_keys_key_tl } 483 | } 484 | % \end{macrocode} 485 | % \end{variable} 486 | % \end{macro} 487 | % \begin{macro}{\more} 488 | % Add a comment at the southwest corner of the timetable. 489 | % \begin{macrocode} 490 | \NewDocumentCommand \more { m } 491 | { 492 | \node [ yshift = .5\l_@@_time_vunit_dim, left = 1ex, 493 | darkgray, font = \small \bfseries 494 | ] at (current~page.south~east) {#1}; 495 | } 496 | % \end{macrocode} 497 | % \end{macro} 498 | % \begin{macro}{\newday} 499 | % Move the next course boxes right \meta{integral value} working days. 500 | % \begin{macrocode} 501 | \NewDocumentCommand \newday { O{1} } { \int_add:Nn \l_@@_weekday_int {#1} } 502 | \int_new:N \l_@@_weekday_int 503 | \int_set:Nn \l_@@_weekday_int { 1 } 504 | % \end{macrocode} 505 | % \end{macro} 506 | % 507 | % \subsection{Internal Auxiliary} 508 | % 509 | % \begin{variable} 510 | % { 511 | % \l_@@_week_ratio_clist, \l_@@_week_accum_clist, 512 | % \l_@@_week_num_fp , \l_@@_week_hunit_dim 513 | % } 514 | % The ratios of every working days, the accumulation of the ratios of every 515 | % working days, the sequence number of every working days, the horizontal 516 | % width unit of the timetable. 517 | % \begin{macrocode} 518 | \clist_new:N \l_@@_week_ratio_clist 519 | \clist_new:N \l_@@_week_accum_clist 520 | \fp_new:N \l_@@_week_num_fp 521 | \dim_new:N \l_@@_week_hunit_dim 522 | % \end{macrocode} 523 | % \end{variable} 524 | % \begin{macro}{\@@_weeklist:n} 525 | % Define the auxiliary command of \cs{weeklist}. 526 | % \begin{macrocode} 527 | \cs_new_protected_nopar:Npn \@@_weeklist:n #1 528 | { 529 | \clist_set:Nn \l_@@_week_clist {#1} 530 | \exp_args:NNf \clist_map_inline:Nn \l_@@_week_clist 531 | { 532 | \@@_get_right:eN {##1} \l_@@_tmpb_tl 533 | \clist_put_right:Ne \l_@@_week_ratio_clist { \l_@@_tmpb_tl } 534 | } 535 | \int_step_inline:nn { \clist_count:N \l_@@_week_clist } 536 | { 537 | \clist_clear:N \l_@@_week_accumtmp_clist 538 | \int_step_inline:nn {##1} 539 | { 540 | \clist_put_right:Ne \l_@@_week_accumtmp_clist 541 | { \clist_item:Nn \l_@@_week_ratio_clist {####1} } 542 | } 543 | \clist_put_right:Ne \l_@@_week_accum_clist 544 | { \fp_eval:n { \clist_use:Nn \l_@@_week_accumtmp_clist { + } } } 545 | } 546 | \fp_set:Nn \l_@@_week_num_fp 547 | { 548 | \clist_item:Nn \l_@@_week_accum_clist 549 | { \clist_count:N \l_@@_week_clist } 550 | } 551 | \dim_set:Nn \l_@@_week_hunit_dim 552 | { \fp_eval:n { 14/\l_@@_week_num_fp/15 } \paperwidth } 553 | } 554 | % \end{macrocode} 555 | % \end{macro} 556 | % \begin{variable}{\l_@@_time_num_int, \l_@@_time_vunit_dim} 557 | % The sequence number of the time list, and the vertical gap between the 558 | % start and end time. 559 | % \begin{macrocode} 560 | \int_new:N \l_@@_time_num_int 561 | \dim_new:N \l_@@_time_vunit_dim 562 | % \end{macrocode} 563 | % \end{variable} 564 | % \begin{macro}{\@@_timelist:n} 565 | % Define the auxiliary command of \cs{timelist}. 566 | % \begin{macrocode} 567 | \cs_new_protected_nopar:Npn \@@_timelist:n #1 568 | { 569 | \clist_set:Nn \l_@@_time_clist {#1} 570 | \int_set:Nn \l_@@_time_num_int { \clist_count:N \l_@@_time_clist } 571 | \dim_set:Nn \l_@@_time_vunit_dim 572 | { \fp_eval:n { 1/(2\l_@@_time_num_int + 3.5) } \paperheight } 573 | } 574 | % \end{macrocode} 575 | % \end{macro} 576 | % \begin{variable}{\l_@@_timelist_shift_dim} 577 | % Store the vertical shift of the sequence number of the time list. 578 | % \begin{macrocode} 579 | \dim_new:N \l_@@_timelist_shift_dim 580 | % \end{macrocode} 581 | % \end{variable} 582 | % \begin{macro}{\@@_maketable:n} 583 | % Define the auxiliary command of the \env{litetable} environment. 584 | % \begin{macrocode} 585 | \cs_new_protected_nopar:Npn \@@_maketable:n #1 586 | { 587 | \fill [ \l_@@_bg_color_tl!5 ] 588 | (current~page.north~west) rectangle + 589 | (\paperwidth, -1.5\l_@@_time_vunit_dim) 590 | node [ midway, black, font = \huge \bfseries ] {#1}; 591 | \tl_if_empty:NF \l_@@_bg_sem_tl 592 | { 593 | \node [ shift = {(-.02\paperwidth, -.75\l_@@_time_vunit_dim)}, 594 | left, rectangle, fill = DarkBlue!10, text = DarkBlue!60, 595 | inner~sep = 2ex, rounded~corners = 8pt, font = \large 596 | ] at (current~page.north~east) { \l_@@_bg_sem_tl }; 597 | } 598 | \int_step_inline:nnnn { 0 } { 2 } { \l_@@_time_num_int } 599 | { 600 | \filldraw [ fill = \l_@@_bg_color_tl!5, thick, 601 | draw = gray, \l_@@_hline_type_tl ] 602 | ([shift = 603 | {(-.4pt, \fp_eval:n { -2 * ##1 - 2.5 } \l_@@_time_vunit_dim)} 604 | ]current~page.north~west 605 | ) rectangle + (\paperwidth + .8pt, -2\l_@@_time_vunit_dim); 606 | } 607 | \bool_if:NTF \l_@@_timelist_hidetime_bool 608 | { 609 | \dim_set:Nn \l_@@_timelist_shift_dim 610 | { -1.5\l_@@_time_vunit_dim } 611 | } 612 | { 613 | \dim_set:Nn \l_@@_timelist_shift_dim 614 | { -\l_@@_time_vunit_dim } 615 | } 616 | \int_step_inline:nn { \l_@@_time_num_int } 617 | { 618 | \node [ darkgray!80, shift = 619 | {( 620 | \paperwidth/30, 621 | -2 * ##1 \l_@@_time_vunit_dim + 622 | \l_@@_timelist_shift_dim 623 | )}, font = \large \l_@@_timelist_numformat_tl 624 | ] at (current~page.north~west) {##1}; 625 | } 626 | \bool_if:NF \l_@@_timelist_hidetime_bool 627 | { 628 | \int_step_inline:nn { \clist_count:N \l_@@_time_clist } 629 | { 630 | \@@_get_left:eN { \clist_item:Nn \l_@@_time_clist {##1} } 631 | \l_@@_tmpa_tl 632 | \@@_get_right:eN { \clist_item:Nn \l_@@_time_clist {##1} } 633 | \l_@@_tmpb_tl 634 | \node [ gray, align = center, shift = 635 | {( 636 | \paperwidth/30, 637 | \fp_eval:n { -1.85 - 2 * ##1 } \l_@@_time_vunit_dim 638 | )}, font = \l_@@_timelist_timeformat_tl 639 | ] at (current~page.north~west) 640 | { \l_@@_tmpa_tl\\ \l_@@_tmpb_tl }; 641 | } 642 | } 643 | \int_step_inline:nn { \clist_count:N \l_@@_week_clist } 644 | { 645 | \int_compare:nNnF {##1} = { \clist_count:N \l_@@_week_clist } 646 | { 647 | \node [ shift = 648 | {(\fp_eval:n 649 | { 650 | 14 * \clist_item:Nn \l_@@_week_accum_clist {##1}/ 651 | \l_@@_week_num_fp/15 + 1/15 652 | } \paperwidth, -2\l_@@_time_vunit_dim 653 | )}, darkgray, font = \ttfamily 654 | ] at (current~page.north~west) { \l_@@_weeklist_sep_tl }; 655 | } 656 | \@@_get_left:eN { \clist_item:Nn \l_@@_week_clist {##1} } 657 | \l_@@_tmpa_tl 658 | \node [ shift = 659 | {(\fp_eval:n 660 | { 661 | 14( 662 | \clist_item:Nn \l_@@_week_accum_clist {##1} - 663 | \clist_item:Nn \l_@@_week_ratio_clist {##1}/2 664 | )/\l_@@_week_num_fp/15 + 1/15 665 | } \paperwidth, -2\l_@@_time_vunit_dim 666 | )}, font = \large \l_@@_weeklist_format_tl 667 | ] at (current~page.north~west) { \l_@@_tmpa_tl }; 668 | } 669 | } 670 | % \end{macrocode} 671 | % \end{macro} 672 | % \begin{variable}{\l_@@_course_shift_dim} 673 | % Store the vertical shift of the course subject in course box. 674 | % \begin{macrocode} 675 | \dim_new:N \l_@@_course_shift_dim 676 | % \end{macrocode} 677 | % \end{variable} 678 | % \begin{macro}{\@@_course_box_aux:nn} 679 | % Define the auxiliary command of \cs{course}. 680 | % \begin{macrocode} 681 | \cs_new_protected_nopar:Npn \@@_course_box_aux:nn #1#2 682 | { 683 | \begin{scope} 684 | \clip [ preaction = { draw, ultra~thick, \l_@@_course_color_tl!60 }, 685 | preaction = { fill, \l_@@_course_color_tl!10 }, 686 | rounded~corners = 8pt ] 687 | ([shift = 688 | {( 689 | \fp_eval:n 690 | { 691 | \clist_item:Nn \l_@@_week_accum_clist 692 | { \l_@@_weekday_int } - 693 | \clist_item:Nn \l_@@_week_ratio_clist 694 | { \l_@@_weekday_int } 695 | } \l_@@_week_hunit_dim + \paperwidth/15 + 1.2pt, 696 | \fp_eval:n { -.5 - 2 * #1 } \l_@@_time_vunit_dim - 1.2pt 697 | )}]current~page.north~west) rectangle + 698 | ( 699 | \clist_item:Nn \l_@@_week_ratio_clist 700 | { \l_@@_weekday_int } \l_@@_week_hunit_dim - 2.4pt, 701 | \fp_eval:n { 2(#1 - #2 - 1) } \l_@@_time_vunit_dim + 2.4pt 702 | ); 703 | \fill [ \l_@@_course_color_tl!60 ] 704 | ([shift = 705 | {( 706 | \fp_eval:n 707 | { 708 | \clist_item:Nn \l_@@_week_accum_clist 709 | { \l_@@_weekday_int } - 710 | \clist_item:Nn \l_@@_week_ratio_clist 711 | { \l_@@_weekday_int } 712 | } \l_@@_week_hunit_dim + \paperwidth/15, 713 | \fp_eval:n { -.5 - 2 * #1 } \l_@@_time_vunit_dim 714 | )}]current~page.north~west) rectangle + 715 | ( 716 | \clist_item:Nn \l_@@_week_ratio_clist 717 | { \l_@@_weekday_int } \l_@@_week_hunit_dim, 718 | -\l_@@_time_vunit_dim/2 719 | ); 720 | \end{scope} 721 | \int_compare:nNnTF {#1} = {#2} 722 | { 723 | \bool_lazy_and:nnTF 724 | { \tl_if_empty_p:N \l_@@_course_location_tl } 725 | { \tl_if_empty_p:N \l_@@_course_lecture_tl } 726 | { \tl_set:Nn \l_@@_course_anchor_tl { } } 727 | { \tl_set:Nn \l_@@_course_anchor_tl { above } } 728 | \node 729 | [ \l_@@_course_anchor_tl, \l_@@_course_color_tl!60, shift = 730 | {( 731 | \fp_eval:n 732 | { 733 | \clist_item:Nn \l_@@_week_accum_clist 734 | { \l_@@_weekday_int } - 735 | \clist_item:Nn \l_@@_week_ratio_clist 736 | { \l_@@_weekday_int }/2 737 | } \l_@@_week_hunit_dim + \paperwidth/15, 738 | \fp_eval:n { -1.75 - #1 - #2 } \l_@@_time_vunit_dim 739 | )}, align = center, font = \bfseries 740 | ] at (current~page.north~west) { \l_@@_course_subject_tl }; 741 | \bool_lazy_or:nnTF 742 | { \tl_if_empty_p:N \l_@@_course_location_tl } 743 | { \tl_if_empty_p:N \l_@@_course_lecture_tl } 744 | { \tl_set:Nn \l_@@_s@course_sep_tl { } } 745 | { \tl_set:Nn \l_@@_s@course_sep_tl { ,~ } } 746 | \node 747 | [ shift = 748 | {( 749 | \fp_eval:n 750 | { 751 | \clist_item:Nn \l_@@_week_accum_clist 752 | { \l_@@_weekday_int } - 753 | \clist_item:Nn \l_@@_week_ratio_clist 754 | { \l_@@_weekday_int }/2 755 | } \l_@@_week_hunit_dim + \paperwidth/15, 756 | \fp_eval:n { -1.75 - #1 - #2 } \l_@@_time_vunit_dim 757 | )}, below, \l_@@_course_color_tl!60, align = center 758 | ] at (current~page.north~west) 759 | { 760 | \l_@@_course_location_tl 761 | \l_@@_s@course_sep_tl 762 | \l_@@_course_lecture_tl 763 | }; 764 | } 765 | { 766 | \bool_lazy_and:nnTF 767 | { \tl_if_empty_p:N \l_@@_course_location_tl } 768 | { \tl_if_empty_p:N \l_@@_course_lecture_tl } 769 | { 770 | \tl_set:Nn \l_@@_course_anchor_tl { } 771 | \dim_set:Nn \l_@@_course_shift_dim { 0pt } 772 | } 773 | { 774 | \tl_set:Nn \l_@@_course_anchor_tl { above } 775 | \dim_set:Nn \l_@@_course_shift_dim { \l_@@_time_vunit_dim/8 } 776 | } 777 | \node 778 | [ \l_@@_course_color_tl!60, align = center, shift = 779 | {( 780 | \fp_eval:n 781 | { 782 | \clist_item:Nn \l_@@_week_accum_clist 783 | { \l_@@_weekday_int } - 784 | \clist_item:Nn \l_@@_week_ratio_clist 785 | { \l_@@_weekday_int }/2 786 | } \l_@@_week_hunit_dim + \paperwidth/15, 787 | \fp_eval:n { -1.5 - #1 - #2 } \l_@@_time_vunit_dim + 788 | \l_@@_course_shift_dim 789 | )}, font = \large \bfseries, \l_@@_course_anchor_tl 790 | ] at (current~page.north~west) { \l_@@_course_subject_tl }; 791 | \bool_lazy_or:nnTF 792 | { \tl_if_empty_p:N \l_@@_course_location_tl } 793 | { \tl_if_empty_p:N \l_@@_course_lecture_tl } 794 | { \tl_set:Nn \l_@@_course_sep_tl { } } 795 | { \tl_set:Nn \l_@@_course_sep_tl { \\ } } 796 | \node 797 | [ shift = 798 | {( 799 | \fp_eval:n 800 | { 801 | \clist_item:Nn \l_@@_week_accum_clist 802 | { \l_@@_weekday_int } - 803 | \clist_item:Nn \l_@@_week_ratio_clist 804 | { \l_@@_weekday_int }/2 805 | } \l_@@_week_hunit_dim + \paperwidth/15, 806 | \fp_eval:n { -1.625 - #1 - #2 } \l_@@_time_vunit_dim 807 | )}, below, \l_@@_course_color_tl!60, align = center 808 | ] at (current~page.north~west) 809 | { 810 | \l_@@_course_location_tl 811 | \l_@@_course_sep_tl 812 | \l_@@_course_lecture_tl 813 | }; 814 | \node 815 | [ shift = 816 | {( 817 | \clist_item:Nn \l_@@_week_accum_clist 818 | { \l_@@_weekday_int } \l_@@_week_hunit_dim + 819 | \paperwidth/15, 820 | \fp_eval:n { -2.5 - 2 * #2 } \l_@@_time_vunit_dim 821 | )}, above~left, \l_@@_course_color_tl!60, outer~sep = .5ex 822 | ] at (current~page.north~west) { \l_@@_course_comment_tl }; 823 | } 824 | } 825 | % \end{macrocode} 826 | % \end{macro} 827 | % 828 | % \begin{macrocode} 829 | \file_input_stop: 830 | % \end{macrocode} 831 | % 832 | % \begin{macrocode} 833 | % 834 | % \end{macrocode} 835 | % 836 | % \end{implementation} 837 | % \clearpage 838 | % \PrintIndex 839 | --------------------------------------------------------------------------------