Key Management

Key Management из пакета pgfkeys, может использоваться самостоятельно или в составе пакета TIKZ, управляет ключами пользователя

Введение

В основном этот раздел описываю, так как его активно используют библиотеки TIKZ.

А в общем этот вопрос вполне удовлетворяет знание TEX и его внутренней кухни по созданию макросов и переменных.

Подключение пакета

\usepackage{pgfkeys}

Отличия pgfkeys от xkeyval

  • pgfkeys организует дерево ключей
  • pgfkeys не влияет на состояние стека
  • pgfkeys медленнее keyval
  • pgfkeys поддерживает стили (полезно для TIKZ)
  • pgfkeys поддерживает множественные аргументы
  • pgfkeys поддерживает обработчики обратного вызова и ошибок

Краткое описание механизма Key Management

Организован по принципу файловой системы Unix, корень и как дерево ветвление всех элементов

Можно указать полный путь к ключу или сокращенное наименование и путь будет подставлен автоматически.

Основная команда \pgfkeys берет пару ключ и значение.

Для каждого будет выполнен код с параметром, переданным в

\pgfkeys{/my key=hallo,/your keys/main key=something\strange,
        key name without path=something else}

Сначала установим код для ключа: стр.1 и затем выполним его с переданным параметром стр.2

\pgfkeys{/my key/.code=The value is '#1'.}
\pgfkeys{/my key=hi!}

В качестве параметров может быть несколько значений (ключевое слово /.code 2 args=)

\pgfkeys{/my key/.code 2 args=The values are '#1' and '#2'.}
\pgfkeys{/my key={a1}{a2}}

Может быть значение по умолчанию: \pgfkeys{/my key/.default=hello}

Можно указать обязательное значение /.value required или запрещенное значение /.value forbidden, т.е. не нужно вводить значение.

Ключ /.cd - изменит путь. Т.е. после этого ключа, все остальные будут выполнять команды с новым путем.

\pgfkeys{/tikz/.cd,line width=1cm,line cap=round}

т.е. все остальные команды будут начинаться с /tikz/

Ключи могут вызывать выполнение других ключей.

\pgfkeys{/a/.code=(a:#1)}
\pgfkeys{/b/.code=(b:#1)}
\pgfkeys{/my style/.style={/a=foo,/b=bar,/a=#1}}
\pgfkeys{/my style=wow}

получим (a:foo)(b:bar)(a:wow)

Еще пример с созданием стиля tikz

\pgfkeys{/tikz/.style=/tikz/.cd}
\pgfkeys{tikz,line width=1cm,draw=red}

Описание синтаксиса pgfkeys

Если ключ начинается с / — это ключ с полным путем, если без слеша, то это не полный путь.

\pgfkeyssetvalue{⟨full key⟩}{⟨token text⟩}

Эта команда сохраняет token text в full key

Это не может быть частичным ключом.

\pgfkeyssetvalue{/my family/my key}{Hello, world!}%установить ключ
\pgfkeysvalueof{/my family/my key}%вывести ключ

\pgfkeyssetevalue{⟨full key⟩}{⟨token text⟩} — это тоже, но \edef версия

\pgfkeyslet{⟨full key⟩}{⟨macro⟩}

\def\helloworld{Hello, world!}
\pgfkeyslet{/my family/my key}{\helloworld}
\pgfkeysvalueof{/my family/my key}

позволяет устанавливать для ключа значение макроса, в нашем случае будет подставлено значение \helloworld

Недопустимо,чтобы ключ совпадал с \relax — relax это пустышка

\pgfkeysgetvalue{⟨full key⟩}{⟨macro⟩}

Извлекает токены из ключа

Если ключ не установлен то токен будет равен \relax

\pgfkeysvalueof{⟨full key⟩}

Возвращает значение ключа и вставляет его в текст

\pgfkeysifdefined{⟨full key⟩}{⟨if⟩}{⟨else⟩}

\pgfkeyssetvalue{/my family/my key}{Hello, world!}
\pgfkeysifdefined{/my family/my key}{yes}{no}

проверяет, если ключ был определен, то выведет значение if, если не определен, то else

\pgfkeys

Ключи могут выполнять следующие действия:

  • выполняет команду,хранящуюся в key с аргументом value
  • сохраняет значение value в ключе key
  • если имя ключа известный обработчик,тогда обработчик все сделает
  • если ключ неизвестный, то вызовется обработчик неизвестных ключей

Синтаксис команд

\pgfkeys{key=value,key,key={val1}{val2}}

Возможно указать:

  • key=value,
  • key,
  • key={val1}{val2}

или просто значение в {} если оно содержит запятые или спецсимволы

\pgfqkeys{⟨default path⟩}{⟨key list⟩}

Эта команда имеет тот же эффект,что и \pgfkeys{⟨default path⟩/.cd,⟨key list⟩}

\pgfkeysalso{⟨key list⟩}

в этой команде путь не изменяется

\pgfqkeysalso{⟨default path⟩}{⟨key list⟩}

вызывает с изменением пути

Команда привязанная к 1 символу

Наверно это удобно.

Так работают во всех nodes кавычки " которые заменяются текстом \label={}

Для этого нужно:

  • Установить /handlers/first char syntax=〈true or false〉 в true
  • Привязать к волшебному слову the character <символ> макрос, который будет выполняться
  • Объявить привязанный макрос
\pgfkeys{ 
/handlers/first char syntax=true, 
/handlers/first char syntax/the character "/.initial=\myquotemacro, 
/handlers/first char syntax/the character </.initial=\mypointedmacro, 
}  

\def\myquotemacro#1{Quoted: #1. } 
\def\mypointedmacro#1{Pointed: #1. }  

\ttfamily \pgfkeys{"foo", <bar>}

Дальше все параметры в "" будут переданы в макрос myquotemacro, а в <> в макрос mypointedmacro

Значение по умолчанию 〈key〉/.@def

  • если не нужно вводить значения, то можно указать key=\pgfkeysnovalue
  • проверяется наличие ключа: 〈key〉/.@def
  • если ключ есть, то он замещается в токене

Для установки по умолчанию значения используем команду: \pgfkeys{/my key/.default=hello}

Команды выполняемые в ключах 〈key〉/.@cmd

Во всем макросах в \pgf параметры должны заканчиваться значением \pgfeov т.е. что сделает на самом деле пакет \pgf

\usepackage {shortvrb} \MakeShortVerb {\|}  
\def\mystore#1+#2\pgfeov{\def\a{#1}\def\b{#2}} 
\pgfkeyslet{/my key/.@cmd}{\mystore} 
\pgfkeys{/my key=hello+world}  

получим:
|\a| is `\a', |\b| is `\b'.
т.е. 
\a is ‘hello’, \b is ‘world’.

Что предлагает пакет взамен

  • \pgfkeysdef{〈key〉}{〈code〉} — Эта команда временно определяет TEX-макрос со списком аргументов #1\pgfeov, а затем позволяет 〈key〉/.@cmd быть равным этому макросу.
  • \pgfkeysedef{〈key〉}{〈code〉} — аналогично, но работает, как edef
  • \pgfkeysdefnargs{〈key〉}{〈argument count〉}{〈code〉} — Эта команда работает аналогично \pgfkeysdef, но позволяет вам указать произвольное «счетчик аргументов» от 0 до 9 (включительно).
\usepackage {shortvrb} \MakeShortVerb {\|}  
\pgfkeysdefnargs{/my key}{2}{\def\a{#1}\def\b{#2}} 
\pgfkeys{/my key= {hello} {world}} 

|\a| is `\a', |\b| is `\b'
  • \pgfkeysedefnargs{〈key〉}{〈argument count〉}{〈code〉} — аналогично, но edef
  • \pgfkeysdefargs{〈key〉}{〈argument pattern〉}{〈code〉} — Эта команда работает аналогично \pgfkeysdefnargs, но позволяет вам предоставить произвольный «шаблон аргумента», а не просто несколько аргументов. \pgfkeysdefargs{/my key}{#1+#2}{\def\a{#1}\def\b{#2}}
  • \pgfkeysedefargs{〈key〉}{〈argument pattern〉}{〈code〉} — это его edef версия

Хранение значений в ключах

Если у ключа не определен key/.@cmd, то он будет просто хранить значение которое может быть задано командой \pgfkeyssetvalue

Обработчики ключей

Обработчики — это дополнительная возможность выполнять некие действия над ключами сверх того, что предоставляется стандартной библиотекой.

\pgfkeysdef{/handlers/.my code}{\pgfkeysdef{\pgfkeyscurrentpath}{#1}}
  • Путь ключа, хранится в макросе \pgfkeyscurrentpath

  • Имя ключа, хранится в макросе \pgfkeyscurrentname

  • обработчик должен начинаться с .

  • /handler config=all|only existing|full or existing — Изменяет исходную конфигурацию использования обработчиков ключей.

  • /handler config/only existing/add exception={〈key handler name〉} — Позволяет добавлять исключения к существующей функции /handler config=only.

Обработка ключей, которые неизвестны

Для некоторых ключей не определен ни сам ключ, ни его подраздел .@cmd, ни обработчик. В этом случае проверяется, существует ли ключ 〈текущий путь〉/.unknown/.@cmd.

Т.к. он существует, то будет выполнена какая-то странная вещь, как он ее поймет.

Пути поиска и обрабатываемые ключи

Обработчики ключей

Теперь мы опишем, какие обработчики клавиш определены по умолчанию.

Обработчик пути

  • Key handler 〈key〉/.cd — Этот обработчик устанавливает путь по умолчанию 〈key〉. Обратите внимание, что путь по умолчанию сбрасывается в начале каждого вызова \pgfkeys и становится равным /.
\pgfkeys{/tikz/.cd,...}
  • Key handler 〈key〉/.is family — Этот обработчик настраивает такие вещи, что при выполнении 〈key〉 текущий путь устанавливается на 〈key〉.
\pgfkeys{/tikz/.is family} 
\pgfkeys{tikz,line width=1cm}

Установка по умолчанию

  • Key handler 〈key〉/.default=〈value〉 — Устанавливает значение по умолчанию 〈key〉 в 〈value〉. Это означает, что всякий раз, когда при вызове \pgfkeys не указывается значение, вместо него будет использоваться это 〈значение〉. \pgfkeys{/width/.default=1cm}
  • Key handler 〈key〉/.value required — Этот обработчик вызывает выдачу ключа /errors/value сообщения об ошибке всякий раз, когда 〈key〉 используется без значения. \pgfkeys{/width/.value required} Т.е. требует обязательно указать значение.
  • Key handler 〈key〉/.value forbidden — не будет выдавать сообщение об ошибке, если указано будет значение ключа

Определение кода ключа

  • Key handler 〈key〉/.code=〈code〉 — Этот обработчик выполняет \pgfkeysdef с параметрами 〈key〉 и 〈code〉.
  • Key handler 〈key〉/.ecode=〈code〉 — выполнит команду \pgfkeysedef
  • Key handler 〈key〉/.code 2 args=〈code〉 — с двумя аргументами
  • Key handler 〈key〉/.ecode 2 args=〈code〉 — с двумя аргументами edef
  • Key handler 〈key〉/.code n args={〈argument count〉}{〈code〉} — с n аргументами
  • Key handler 〈key〉/.ecode n args={〈argument count〉}{〈code〉} — с n аргументами edef
  • Key handler 〈key〉/.code args={〈argument pattern〉}{〈code〉} — с произвольным паттерном аргументов
  • Key handler 〈key〉/.ecode args={〈argument pattern〉}{〈code〉} — с произвольным паттерном аргументов edef
  • Key handler 〈key〉/.add code={〈prefix code〉}{〈append code〉} — Этот обработчик добавляет код к существующему ключу. 〈код префикса〉 добавляется к коду, хранящемуся в 〈key〉/.@cmd, в начале, 〈код добавления〉 добавляется к этому коду в конце.
\pgfkeys{/par indent/.code={\parindent=#1}} 
\newdimen\myparindent 
\pgfkeys{/par indent/.add code={}{\myparindent=#1}} 
...  
\pgfkeys{/par indent=1cm} % This will set both \p
  • Key handler 〈key〉/.prefix code=〈prefix code〉 — Этот обработчик является ярлыком для 〈key〉/.add code={〈prefix code〉}{}. То есть этот обработчик добавляет 〈префиксный код〉 в начало кода, хранящегося в 〈key〉/.@cmd.
  • Key handler 〈key〉/.append code=〈append code〉 — Этот обработчик является ярлыком для 〈key〉/.add code={}{〈append code〉}.

Определение стиля

  • Key handler 〈key〉/.style=〈key list〉 — Этот обработчик настраивает ситуацию таким образом, что всякий раз, когда 〈ключ〉=〈значение〉 встречается в списке ключей, вместо этого обрабатывается 〈список ключей〉, в котором каждое вхождение #1 заменено на 〈значение〉. Как всегда, если 〈значение〉 не указано, используется значение по умолчанию, если оно определено, или специальное значение \pgfkeysnovalue.
\pgfkeys{/par indent/.code={\parindent=#1}} 
\pgfkeys{/no indent/.style={/par indent=0pt}} 
\pgfkeys{/normal indent/.style={/par indent=2em}} 
\pgfkeys{/no indent} 
... 
\pgfkeys{/normal indent}
  • Key handler 〈key〉/.estyle=〈key list〉 — определяет стиль через edef
  • Key handler 〈key〉/.style 2 args=〈key list〉 — с двумя аргументами
  • Key handler 〈key〉/.estyle 2 args=〈key list〉 — с двумя аргументами edef
  • Key handler 〈key〉/.style n args={〈argument count〉}〈key list〉 — n аргументов
  • Key handler 〈key〉/.add style={〈prefix key list〉}{〈append key list〉} — добавить значение к стилю
  • Key handler 〈key〉/.style args={〈argument pattern〉}{〈key list〉} — стиль с произвольным паттерном
  • Key handler 〈key〉/.estyle args={〈argument pattern〉}{〈code〉} — стиль с произвольным паттерном edef
  • Key handler 〈key〉/.prefix style=〈prefix key list〉 — prefix style добавить
  • Key handler 〈key〉/.append style=〈append key list〉 — добавить стиль в конец

Определение ключей значений, макросов, if и выбора

Для некоторых клавиш код, который должен по ним выполняться, достаточно «специализирован».

  • Key handler 〈key〉/.initial=〈value〉 — Этот обработчик устанавливает значение 〈key〉 в 〈value〉. Обратите внимание, что никакие подразделы не задействованы. После использования этого обработчика, согласно правилам, регулирующим ключи, вы можете впоследствии изменить значение 〈key〉, просто написав 〈key〉=〈value〉. Таким образом, этот обработчик используется для установки начального значения ключа.
  • Key handler 〈key〉/.get=〈macro〉 — выведет содержимое ключа и поместит в \macro
  • Key handler 〈key〉/.add={〈prefix value〉}{〈append value〉} — добавит к ключу
  • Key handler 〈key〉/.prefix={〈prefix value〉} — добавит префикс
  • Key handler 〈key〉/.append={〈append value〉} — добавит суффикс
  • Key handler 〈key〉/.link=〈another key〉 — сделает ссылку на другой ключ
  • Key handler 〈key〉/.store in=〈macro〉 — это прямой аналог \def\macro{#1}
\pgfkeys{/text/.store in=\mytext}  
\def\a{world} \pgfkeys{/text=Hello \a!} 
\def\a{Gruffalo}
\mytext

выведет:
Hello Gruffalo!
  • Key handler 〈key〉/.estore in=〈macro〉 — тоже, только edef
  • Key handler 〈key〉/.is if=〈TEX-if name〉 — имитация if Tex
\newif\iftheworldisflat  
\pgfkeys{/flat world/.is if=theworldisflat} 
\pgfkeys{/flat world=false} 
\iftheworldisflat 
Flat \else Round? 
\fi
  • Key handler 〈key〉/.is choice — Этот обработчик настраивает ситуацию так, что запись 〈key〉=〈value〉 приведет к выполнению подраздела 〈key〉/〈value〉. Таким образом, каждый из возможных вариантов должен быть задан подразделом 〈key〉.
\pgfkeys{/line cap/.is choice} 
\pgfkeys{/line cap/round/.code={\pgfsetroundcap}} 
\pgfkeys{/line cap/butt/.code={\pgfsetbuttcap}} 
\pgfkeys{/line cap/rect/.code={\pgfsetrectcap}} 
\pgfkeys{/line cap/rectangle/.style={/line cap=rect}} 
... 
\draw [/line cap=butt] ...

Расширенные и множественные значения

  • Key handler 〈key〉/.expand once=〈value〉 — Этот обработчик расширяет 〈value〉 один раз (точнее, он выполняет команду \expandafter для первого токена 〈value〉), а затем обрабатывает полученный 〈result〉, как если бы вы написали 〈key〉=〈result〉.
  • Key handler 〈key〉/.expand twice=〈value〉 — дважды расширяет значение
  • Key handler 〈key〉/.expanded=〈value〉 — Этот обработчик полностью расширит 〈value〉 (с помощью \edef) перед обработкой 〈key〉=〈result〉.
  • Key handler 〈key〉/.evaluated=〈value〉 — Этот обработчик оценит 〈value〉 как математическое выражение с помощью \pgfmathparse и присвоит 〈key〉=\pgfmathresult.
  • Key handler 〈key〉/.list=〈comma-separated list of values〉 — Этот обработчик вызывает многократное использование ключа, а именно один раз для каждого элемента списка значений. Что-то вроде foreach

Обработчик с пересылкой значений

  • Key handler 〈key〉/.forward to=〈another key〉 — Этот обработчик заставляет 〈key〉 «пересылать» свой аргумент 〈другому ключу〉. При использовании 〈key〉 сначала будет выполнен ее обычный код. Затем значение (дополнительно) передается «другому ключу».
\pgfkeys{  
/a/.code=(a:#1), 
/b/.code=(b:#1), 
/b/.forward to=/a, 
/c/.forward to=/a 
}  
\pgfkeys{/b=1} \pgfkeys{/c=2}

выведет 
(b:1)(a:1) (a:2)
  • Key handler 〈key〉/.search also={〈path list〉} — Стиль, который устанавливает обработчик /.unknown в 〈key〉. Этот обработчик /.unknown затем будет искать неизвестные ключи по каждому пути, указанному в {〈списке путей〉}.

Обработчики для тестирования ключей

  • Key handler 〈key〉/.try=〈value〉 — Этот обработчик вызывает то же самое, как если бы вместо этого было написано 〈key〉=〈value〉. Однако если ни 〈key〉/.@cmd, ни сам ключ не определены, обработчики вызываться не будут. Вместо этого выполнение ключа просто останавливается. Таким образом, этот обработчик «пытается» использовать ключ, но никаких дальнейших действий не предпринимается, если ключ не определен.
  • Key handler 〈key〉/.retry=〈value〉 — Этот обработчик работает так же, как /.try, только он ничего не будет делать, если \ifpgfkeyssuccess имеет значение false. Таким образом, этот обработчик попытается установить ключ только в том случае, если «последняя попытка не удалась».
  • Key handler 〈key〉/.lastretry=〈value〉 — Этот обработчик работает как /.retry, только он будет вызывать обычные обработчики для неизвестных ключей, если \ifpgfkeyssuccess имеет значение false.

Обработчики для проверки ключей

  • Key handler 〈key〉/.show value — Этот обработчик выполняет команду \show для значения, хранящегося в 〈key〉. Это полезно в основном для отладки.
  • Key handler 〈key〉/.show code — Этот обработчик выполняет команду \show для кода, хранящегося в 〈key〉/.@cmd. Это полезно в основном для отладки.

Обработка ошибок

В определенных ситуациях могут возникнуть ошибки, например, при использовании неопределенного ключа. В таких ситуациях выполняются ключи ошибок. Они должны хранить макрос, который получает два аргумента: первый — это ключ-нарушитель (возможно, только после раскрытия макроса), второй — значение, которое было передано в качестве параметра (также возможно, только после раскрытия макроса).

Ключевая фильтрация

Обычно вызов \pgfkeys устанавливает все ключи, указанные в списке аргументов. Обычно именно этого ожидают пользователи. Однако реализации различных пакетов или pgf-библиотек могут нуждаться в большем контроле над процедурой установки ключей: библиотека A может захотеть установить свои параметры напрямую и передать все оставшиеся в библиотеку B.

Установить библиотеку фильтрации

\usepgfkeyslibrary{filtered} % LATEX and plain TEX 
\usepgfkeyslibrary[filtered] % ConTEXt