2

Consider the following MWE:

enter image description here

\documentclass[letterpaper,11pt]{article}
\usepackage{l3draw}

\ExplSyntaxOn

\dim_new:N \l__pencil_dim
\fp_new:N \l__pencil_linethickness_fp

\cs_new_protected:Nn \pencil_diagram:n
 {
  \dim_set:Nn \l__pencil_dim { #1 }
  \draw_begin:
  \draw_transform_rotate:n { 110 } %rotation
  \draw_linewidth:n { \l__pencil_linethickness_fp }
  \draw_cap_round:
  \draw_join_round:
  \draw_path_moveto:n { 0.0\l__pencil_dim , 0.125\l__pencil_dim }
  \draw_path_lineto:n { 0.125\l__pencil_dim , 0.0\l__pencil_dim }
  \draw_path_lineto:n { 1.0\l__pencil_dim , 0.0\l__pencil_dim }
  \draw_path_lineto:n { 1.0\l__pencil_dim , 0.25\l__pencil_dim }
  \draw_path_lineto:n { 0.125\l__pencil_dim , 0.25\l__pencil_dim }
  \draw_path_close:
  \color_fill:n { black } %color
  \draw_path_use_clear:n { fill, stroke }
  \draw_path_moveto:n { 1.125\l__pencil_dim , 0.0\l__pencil_dim }
  \draw_path_lineto:n { 1.25\l__pencil_dim , 0.0\l__pencil_dim }
  \draw_path_curveto:nn
    { 1.35\l__pencil_dim , 0.125\l__pencil_dim } 
    { 1.25\l__pencil_dim , 0.25\l__pencil_dim }
  \draw_path_lineto:n { 1.125\l__pencil_dim , 0.25\l__pencil_dim }
  \draw_path_close:
  \color_fill:n { black } %color
  \draw_path_use_clear:n { fill, stroke }
  \draw_end:
 }
\NewDocumentCommand{\explpencil}{ O{1ex} }
 {
    \fp_set:Nn \l__pencil_linethickness_fp { 0.08ex }
    \pencil_diagram:n { #1 }
 } 
\ExplSyntaxOff
\begin{document}
\explpencil[2ex] sample text
\end{document}

In @egreg solution he used l3keys values to define the inputs a user can have and notably the usage of tl_if_empty:NTF. I like the fact that the inputs are not mandatory and dependent on the user.

How can I create similar key values focusing on the colour (\l__pencil_color), dimension (\l__pencil_dim) and rotation (\l__pencil_rotation). The names in the parenthesis are just suggested names.

I am looking for possibilities like

  • \explpencil,
  • \explpencil[2ex],
  • \explpencil[2ex,30],
  • \explpencil[red][2ex][30]

preferably if the order of the input does not matter but could generate the expected results; say \explpencil[red][2ex][30]=\explpencil[2ex][red][30].

1
  • I'd suggest to not use multiple optional arguments, but instead one in which you give a comma separated list. And while we could make guesses as to which value should belong to which variable (certainly possible), it might be a better idea to really choose l3keys and have an interface like \explpencil[dim=2ex, color=red, rot=30].
    – Skillmon
    Commented Nov 16, 2020 at 7:18

1 Answer 1

2

One optional argument is good, two can be remembered; more than two always require to look at the manual for their relative order.

Using a key-value syntax is much better when there are many options to set.

\documentclass[letterpaper,11pt]{article}
\usepackage{l3draw}

\ExplSyntaxOn

% user interface
\NewDocumentCommand{\explpencil}{ O{} }
 {
  \group_begin:
  \aze_pencil_diagram:n { #1 }
  \group_end:
 } 

% variables and variants
\cs_generate_variant:Nn \color_fill:n { V }

\dim_new:N \l__aze_pencil_size_dim
\fp_new:N \l__aze_pencil_linethickness_fp

\keys_define:nn { aze/pencil }
 {
  size  .dim_set:N = \l__aze_pencil_size_dim,
  color .tl_set:N  = \l__aze_pencil_color_tl,
  color .initial:n = black,
  angle .fp_set:N  = \l__aze_pencil_angle_fp,
  angle .initial:n = 110,
  thick .dim_set:N  = \l__aze_pencil_thick_dim,
 }

% internal implementation
\cs_new_protected:Nn \aze_pencil_diagram:n
 {
  \keys_set:nn { aze/pencil } { size=1ex, thick=0.08ex, #1 }
  \draw_begin:
  \draw_transform_rotate:n { \l__aze_pencil_angle_fp } % angle
  \draw_linewidth:n { \l__aze_pencil_thick_dim }
  \draw_cap_round:
  \draw_join_round:
  \draw_path_moveto:n { 0.000\l__aze_pencil_size_dim , 0.125\l__aze_pencil_size_dim }
  \draw_path_lineto:n { 0.125\l__aze_pencil_size_dim , 0.000\l__aze_pencil_size_dim }
  \draw_path_lineto:n { 1.000\l__aze_pencil_size_dim , 0.000\l__aze_pencil_size_dim }
  \draw_path_lineto:n { 1.000\l__aze_pencil_size_dim , 0.250\l__aze_pencil_size_dim }
  \draw_path_lineto:n { 0.125\l__aze_pencil_size_dim , 0.250\l__aze_pencil_size_dim }
  \draw_path_close:
  \color_fill:V \l__aze_pencil_color_tl %color
  \draw_path_use_clear:n { fill, stroke }
  \draw_path_moveto:n { 1.125\l__aze_pencil_size_dim , 0.0\l__aze_pencil_size_dim }
  \draw_path_lineto:n { 1.250\l__aze_pencil_size_dim , 0.0\l__aze_pencil_size_dim }
  \draw_path_curveto:nn
    { 1.35\l__aze_pencil_size_dim , 0.125\l__aze_pencil_size_dim } 
    { 1.25\l__aze_pencil_size_dim , 0.250\l__aze_pencil_size_dim }
  \draw_path_lineto:n { 1.125\l__aze_pencil_size_dim , 0.25\l__aze_pencil_size_dim }
  \draw_path_close:
  \color_fill:V \l__aze_pencil_color_tl %color
  \draw_path_use_clear:n { fill, stroke }
  \draw_end:
 }

\ExplSyntaxOff

\begin{document}

\explpencil{} sample text

\explpencil[size=2ex] sample text

\explpencil[size=1ex,color=red,angle=50,thick=0.01ex] sample text

\end{document}

The possible options are size, color, angle and thick. The last one is mostly irrelevant for black pencils, it becomes important for colored ones.

Why do color and angle have initial values while size and thick don't? Because we'd like tha size to be in terms of ex, so that the drawing adapts to the context. If we set size initially to 1ex, this would be the dimension at the time the setting is done, so in the document preamble. Similarly for thick, so the values are set at call time, maybe to be overridden by an explicit option.

enter image description here

5
  • Why is the \group_begin: and \group_end: not inside the difinition of \aze_pencil_diagram:n? I'd say that two consecutive direct calls of \aze_pencil_diagram:n with different arguments shouldn't be able to affect each other.
    – Skillmon
    Commented Nov 16, 2020 at 9:52
  • @Skillmon No particular reason; I believe that the internal function should not do a group and this is the job of the user interface, that's all.
    – egreg
    Commented Nov 16, 2020 at 11:20
  • Why do you use the notation aze/pencil?
    – azetina
    Commented Nov 16, 2020 at 16:05
  • I forgot to say thanks :)
    – azetina
    Commented Nov 16, 2020 at 22:59
  • @azetina aze is for “azetina”. The prefix for this code is aze and the functions and variables are about pencil.
    – egreg
    Commented Nov 16, 2020 at 23:14

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .