Last active
August 29, 2015 14:06
-
-
Save zr-tex8r/6c1eabe4f8cf1a012d23 to your computer and use it in GitHub Desktop.
LaTeX: An extension to easylist, where an arbitrary symbol can be used as list starters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
% | |
% tceasylist.sty | |
% | |
%% package declaratoin | |
\NeedsTeXFormat{LaTeX2e} | |
\ProvidesPackage{tceasylist}[2014/09/15 v0.2] | |
%% preparations | |
\def\tcel@pkgname{tceasylist} | |
\def\tcel@error{\PackageError\tcel@pkgname} | |
\def\tcel@warn{\PackageWarningNoLine\tcel@pkgname} | |
\newif\iftcel@ok | |
\newif\iftcel@unicode | |
\providecommand*\bxDebug[1]{} | |
%--------------------------------------- helpers | |
%% unique toens | |
\def\tcel@mt{\tcel@mt@} | |
\def\tcel@mark{\tcel@mark@} | |
\def\tcel@end{\tcel@end@} | |
%% Set switch tcel@unicode, which means whether Unicode codespace | |
% is available. | |
\begingroup | |
\def\tcel@check#1#2{% | |
\edef\tcel@tmpa{\string#1}% | |
\edef\tcel@tmpb{\meaning#1}% | |
\ifx\tcel@tmpa\tcel@tmpb #2\fi | |
} | |
\tcel@check\XeTeXversion{\global\tcel@unicodetrue} | |
\tcel@check\luatexversion{\global\tcel@unicodetrue} | |
\endgroup | |
%% \tcel@bs : a backslash | |
\edef\tcel@bs{\expandafter\@gobble\string\\} | |
%% \tcel@detokenize\CS | |
% Update a token-list macro \CS with the detokenized list. | |
\def\tcel@detokenize#1{% | |
\expandafter\tcel@detokenize@a\meaning#1\tcel@end#1% | |
} | |
\def\tcel@detokenize@a#1->#2\tcel@end#3{\def#3{#2}} | |
%% \tcel@check@single{<arg>}\CSa\CSb | |
% If <arg> is a single char then call \CSa with that char; | |
% if <arg> is a single cs then call \CSb with that cs; | |
% otherwise do nothing. | |
\def\tcel@check@single#1#2#3{% | |
\def\tcel@tmpa{#1}% | |
\let\tcel@next\tcel@tmpa \tcel@detokenize\tcel@next | |
\def\tcel@tmpb{#2}% | |
\def\tcel@tmpc{#3}% | |
\expandafter\tcel@check@single@a\tcel@next\relax\relax\tcel@end | |
} | |
\def\tcel@check@single@a#1#2#3\tcel@end{% | |
\if#1\tcel@bs % starting with a cs | |
\expandafter\tcel@check@single@b\tcel@tmpa\tcel@end | |
\else\ifx#1\relax % no-op | |
\else\ifx#2\relax % single char | |
\tcel@tmpb#1% | |
\fi\fi\fi | |
} | |
\def\tcel@check@single@b#1#2\tcel@end{% | |
\ifx\tcel@mt#2\tcel@mt % single cs | |
\tcel@tmpc#1% | |
\fi | |
} | |
%% \tcel@check@hexnum{<arg>} | |
% Parse <arg> as a hex number and set the result to \@tempcnta; | |
% if failed the result is negative. | |
\def\tcel@check@hexnum#1{% | |
\def\tcel@tmpa{#1}\tcel@detokenize\tcel@tmpa | |
\ifx\tcel@tmpa\@empty\else | |
\edef\tcel@next{% | |
\uppercase{\noexpand\tcel@check@hexnum@a{\tcel@tmpa}}}% | |
\tcel@next | |
\fi | |
} | |
\def\tcel@check@hexnum@a#1{% | |
\afterassignment\tcel@check@hexnum@b | |
\@tempcnta\string"0#1\relax | |
} | |
\def\tcel@check@hexnum@b#1\relax{% | |
\ifx\tcel@mt#1\tcel@mt\else | |
\@tempcnta\m@ne | |
\fi | |
} | |
%% \tcel@get@char@tokens{<number>} | |
% Make char token with the given code value and assign them | |
% to token-list macros; \tcel@char@A holds an active char | |
% and \tcel@char@N holds a non-active char. | |
\def\tcel@get@char@tokens#1{% | |
\lccode`\~=#1\relax \lccode`\:=#1\relax | |
\lowercase{\def\tcel@char@A{~}\def\tcel@char@N{:}}% | |
} | |
%--------------------------------------- option handling | |
%% \tcel@promise | |
% Process that will be done at the end of the package. | |
\let\tcel@promise\relax | |
%% \tcel@check@istart{<string>} | |
% Check an option string, and if it is of the form 'item=X' then | |
% update \tcel@promise with an invocation of \SetItemStarter. | |
\def\tcel@check@istart#1{% | |
\tcel@okfalse | |
\tcel@check@istart@a#1\tcel@mark item=\tcel@mark\tcel@end | |
} | |
\def\tcel@check@istart@a#1item=#2\tcel@mark#3\tcel@end{% | |
\ifx\tcel@mt#1\tcel@mt | |
\tcel@check@single{#2}\tcel@check@istart@b\tcel@check@istart@b | |
\iftcel@ok\else | |
\tcel@error | |
{Option value of 'item' must be a single character}% | |
\@ehc | |
\tcel@oktrue % not pass the option anyway | |
\fi | |
\fi | |
} | |
\def\tcel@check@istart@b#1{% | |
\tcel@oktrue | |
\def\tcel@promise{\SetItemStarter{#1}}% | |
} | |
%% option handler | |
\DeclareOption{snowman}{% | |
\def\tcel@promise{\SetItemStarter{2603}}% | |
} | |
\DeclareOption*{% | |
\expandafter\tcel@decl@opt@a\expandafter{\CurrentOption}% | |
} | |
\def\tcel@decl@opt@a#1{% | |
\tcel@check@istart{#1}% | |
\iftcel@ok\else | |
\PassOptionsToPackage{#1}{easylist}% | |
\fi | |
} | |
%% process it | |
\ProcessOptions\relax | |
%% load the package | |
\RequirePackage{easylist} | |
%--------------------------------------- patch to easylist | |
%% Check consistency | |
\def\tcel@next{% | |
\endgroup\par} | |
\ifx\tcel@next\endeasylist\else | |
\tcel@error | |
{Cannot patch to easylist code} | |
{Package loading is aborted.} | |
\expandafter\endinput\fi\relax | |
%% Redefine '\easylist' | |
\tcel@okfalse | |
\begingroup | |
\def\tcel@patch{% | |
\expandafter\tcel@patch@a\easylist\tcel@mark | |
\begingroup\tcel@mark\tcel@end | |
} | |
\def\tcel@patch@a#1\begingroup#2\tcel@mark#3\tcel@end{% | |
\ifx\tcel@mt#3\tcel@mt\else | |
\aftergroup\tcel@oktrue | |
\gdef\tcel@reset@item@starter{#1}% | |
\gdef\easylist{% | |
\let\SetItemStarter\tcel@invalid@SetItemStarter | |
\tcel@reset@item@starter | |
\begingroup #2}% | |
\fi | |
} | |
\tcel@patch | |
\endgroup | |
\iftcel@ok\else | |
\tcel@error | |
{Cannot patch to easylist code} | |
{Package loading is aborted.} | |
\expandafter\endinput\fi\relax | |
%% Patch to '\elCreateItem' (not mandatory) | |
\ifx\detokenize\@undefined\else | |
\begingroup | |
% messages after replacement | |
\def\tcel@msga{% | |
Too many item-start tokens.} | |
\def\tcel@msgb{% | |
You can't use more than \the\el@CounterTotal\space | |
item-start tokens} | |
% patch process | |
\edef\tcel@patch{% | |
\noexpand\tcel@patch@a | |
\detokenize{Too many:.:You can't:'s:}% | |
{\detokenize\expandafter{\elCreateItem}}} | |
\def\tcel@patch@a#1:#2:#3:#4:#5{% | |
\def\tcel@next##1#1##2#2##3#3##4#4##5\tcel@mark{% | |
\tcel@patch@c{##1\tcel@msga##3\tcel@msgb##5}}% | |
\tcel@next#5\tcel@mark#1#2#3#4\tcel@mark\tcel@end} | |
\def\tcel@patch@c#1#2\tcel@end{% | |
\ifx\tcel@mt#2\tcel@mt | |
\tcel@warn{Cannot apply patch}% | |
\else | |
\edef\tcel@next{\noexpand\tcel@patch@d{#1}}% | |
\tcel@next | |
\fi} | |
\def\tcel@patch@d#1{% | |
\scantokens{\toks@{#1}}% | |
\edef\elCreateItem{\the\toks@}} | |
\tcel@patch | |
\endgroup | |
\fi | |
%%<+>\ItemStarter | |
% The item-starter function, which is normally assigned to | |
% 'the active char' in easylist. | |
\newcommand*\ItemStarter{% | |
\futurelet\elNextToken\elCreateItem | |
} | |
%%<+>\ItemStarterUpdated\CS | |
% Must be called when the specification of item-starter token | |
% is updated, where the argument \CS is a macro that activates | |
% the token specified. | |
\newcommand*\ItemStarterUpdated[1]{% | |
\global\let\tcel@reset@item@starter#1% | |
} | |
%% \tcel@invalid@SetItemStarter | |
% In easylist environments, \SetItemStarter is overwritten by | |
% this macro. | |
\def\tcel@invalid@SetItemStarter#1{% | |
\tcel@error | |
{Cannot change item starter here} | |
\@eha | |
} | |
%--------------------------------------- all done | |
%% \tcel@g@char : codepoint of item-starter char | |
\let\tcel@g@char\relax | |
%% \tcel@char : for local use | |
\let\tcel@char\relax | |
%% \tcel@cmd : item-starter command | |
\let\tcel@g@cmd\relax | |
%%<*>\SetItemStarter{<some>} | |
\newcommand*\SetItemStarter[1]{% | |
\tcel@okfalse \let\tcel@char\relax | |
\tcel@check@single{#1}\tcel@set@is@char\tcel@set@is@cmd | |
\iftcel@ok\else | |
\tcel@check@hexnum{#1}% | |
\ifnum\@tempcnta<\z@ | |
\tcel@error | |
{Invalid argument given to \string\SetItemStarter}% | |
\@ehc | |
\else\ifnum | |
\iftcel@unicode "10FFFF \else "FF \fi | |
<\@tempcnta | |
\tcel@error | |
{The code value given is too big}% | |
\@ehc | |
\else | |
\chardef\tcel@char\@tempcnta | |
\fi\fi | |
\fi | |
\ifx\tcel@char\relax\else | |
\tcel@okfalse | |
\ifnum`\#=\tcel@char \tcel@oktrue \fi | |
\ifnum`\@=\tcel@char \tcel@oktrue \fi | |
\ifnum`\&=\tcel@char \tcel@oktrue \fi | |
\ifnum\tcel@char>"7F | |
\ifnum\catcode\tcel@char=11 \tcel@oktrue \fi | |
\ifnum\catcode\tcel@char=12 \tcel@oktrue \fi | |
\fi | |
\tcel@get@char@tokens\tcel@char | |
\iftcel@ok | |
\expandafter\tcel@set@is@char@a\tcel@char@A | |
\else | |
\tcel@error | |
{Cannot use '\tcel@char@N' as item starter}% | |
\@eha | |
\fi | |
\fi | |
} | |
\def\tcel@set@is@char#1{% | |
\chardef\tcel@char`#1\relax | |
\tcel@oktrue | |
} | |
\def\tcel@set@is@char@a#1{% | |
\global\let\tcel@g@char\tcel@char | |
\global\let\Activate\tcel@Activate@char | |
\global\let\Deactivate\tcel@Deactivate@char | |
\def\tcel@next{% | |
\catcode\tcel@g@char\active | |
\let#1\ItemStarter}% | |
\ItemStarterUpdated\tcel@next | |
} | |
\def\tcel@set@is@cmd#1{% | |
\ifx#1\tcel@ltx@star | |
\gdef\tcel@g@cmd{#1}% | |
\global\let\Activate\relax | |
\global\let\Deactivate\relax | |
\def\tcel@next{\let#1\tcel@switch@star}% | |
\ItemStarterUpdated\tcel@next | |
\else | |
\@ifdefinable{#1}{% | |
\gdef\tcel@g@cmd{#1}% | |
\global\let\Activate\relax | |
\global\let\Deactivate\relax | |
\def\tcel@next{\let#1\ItemStarter}% | |
\ItemStarterUpdated\tcel@next | |
}% | |
\fi | |
\tcel@oktrue | |
} | |
\def\tcel@ltx@star{% | |
\discretionary{\thinspace\the\textfont2\char2}{}{}% | |
} | |
\def\tcel@switch@star{% | |
\ifmmode \tcel@ltx@star \expandafter\@gobble \fi | |
\ItemStarter | |
} | |
%% \tcel@Activate@char | |
\let\tcel@deactivate\relax | |
\def\tcel@Activate@char{% | |
\ifx\tcel@deactivate\relax | |
\edef\tcel@deactivate{% | |
\catcode\tcel@g@char=\the\catcode\tcel@g@char\relax}% | |
\fi | |
\catcode\tcel@g@char\active | |
} | |
\def\tcel@Deactivate@char{% | |
\tcel@deactivate | |
\let\tcel@deactivate\relax | |
} | |
%--------------------------------------- all done | |
%% do the promise | |
\tcel@promise | |
%% done | |
\endinput | |
%% EOF |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
% XeLaTeX document, encoded in UTF-8 | |
\documentclass[a4paper]{article} | |
\usepackage[snowman]{tceasylist}% '☃' starts a list item | |
\begin{document} | |
\begin{easylist} | |
☃ Blah. | |
☃ Blahblah. | |
☃☃ Blah, blahblah blah blah. | |
☃☃☃ Blah. | |
☃☃ Blahblah, `blah' blah? | |
☃☃☃ Blahblahblah\ldots. | |
☃ Blah, \emph{blahblah blah} blah blahblah. | |
\end{easylist} | |
\end{document} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
% XeLaTeX document, encoded in UTF-8 | |
\documentclass[a4paper]{article} | |
\usepackage[item=☺]{tceasylist}% '☺' starts a list item | |
\begin{document} | |
\begin{easylist} | |
☺ Blah. | |
☺ Blahblah. | |
☺☺ Blah, blahblah blah blah. | |
☺☺☺ Blah. | |
☺☺ Blahblah, `blah' blah? | |
☺☺☺ Blahblahblah\ldots. | |
☺ Blah, \emph{blahblah blah} blah blahblah. | |
\end{easylist} | |
\end{document} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment