ЛаТеX/Обичан ТеХ
Док сe играте ЛаТеХ макроом, приметићете да је прилично ограничен. Можда се питате како сви су ови пакети које користите сваки дан спроведени са тако мало. У ствари, ЛаТеХ је скуп макроа Обичног ТеХ-а и већина пакета користи Обичан ТеХ код. Обичан ТеХ је много ниског нивоа, има много више могућности по цени стрме криве учења и сложеног програмирања.
До неколико изузетака, можете користити пун језик Обичног ТеХ-а оквиру важећег документа ЛаТеХ док је супротно нетачно.
Вокабулар
[уреди]Да би се избегла конфузија, неопходно је објаснити неке термине.
- Група је све након отварања брејса и после поређења затварања брејса.
- Токен је карактер, контролна секвенца, или група.
- Контролна секвенца је нешто што почиње са
\
. Не штампа се као што јесте, она се проширила по ТеХу мотора према својој врсти. - Команда (или функција или макро ) је контролна секвенца која се може проширити и на текста, (поновно) дефинисање контролних секвенци, итд.
- Примитива је команда која је тешко кодирана у ТеХ мотору, односно није записана у Обичном ТеХ-у.
- Регистар је ТеХ начин да се рукује променљивама. Они су ограничени у бројкама (256 за сваку врсту регистра у класичном ТеХу, 32767 у е-ТеХу).
- Дужина је контролна секвенца која садржи дужину (број затим следи јединица). Погледајте Дужина.
- Фонт је контролна секвенца који се односи на фонт фајл. Погледајте Фонтови.
- Кутија је објекат који је направљен за штампање. Све што се завршава на папиру је кутија: писма, ставови, странице ... Погледајте Кутије.
- Лепак је одређена количина простора који се ставља између кутија када су спојене.
- Бројач је регистар који садржи број. Погледајте Бројачи.
Може постојати више термина, али се надамо да ће ово бити довољно за сада.
Кеткодови
[уреди]У ТеХу неки карактери имају посебно значење које није за штампање повезано са глифом.
На пример, \
се користи за увођење контролне секвенце, а неће штампати косу црту подразумевано.
За разлику између различитих значења карактера, ТеХ ће их поделити у категорије кодова , или кеткодове за кратко. Постоји 16 категорија кодова у ТеХу.
Снажна карактеристика ТеХа је његова способност да редефинише свој језик, јер постоји \catcode
функција која ће вам омогућити да промените категоријски код било ког знака.
Међутим, то се не препоручује, јер може учинити да се код тешко чита. Уколико редефинишете било који кеткод у класи или у стил датотеци, уверите се да је вратити на крају фајла.
Ако редефинишете кеткодове у документу, уверите се да то урадите после преамбуле да спречите сукобе са учитавањем пакета.
Код | Опис | Уобичајени код |
---|---|---|
0 | Излазак карактера и контролне секвенце | \
|
1 | Почетак групе | {
|
2 | Крај групе | }
|
3 | Математичка смена | $
|
4 | Картица поравнања | &
|
5 | Крај линије | ^^M (АСЦИИ врати)
|
6 | Макро параметар | #
|
7 | Експонент | ^ и ^^K
|
8 | Потписан знак | _ и ^^A
|
9 | Игнорисан карактер | ^^@ (АСЦИИ нула)
|
10 | Размак | ␣ и ^^I (АСЦИИ хоризонтални таб)
|
11 | Слово | A...Z и a...z
|
12 | Други карактери | све што није наведено у другим кеткодовима. Најчешће, @. |
13 | Активни карактер | ~ и ^^L (АСЦИИ облик извора)
|
14 | Коментар карактер | %
|
15 | Неважећи карактер | ^^? (АСЦИИ брисање)
|
Активни знакови
[уреди]Активни знакови личе на макрое: они су самохрани карактери који ће се проширити пре било које друге команде.
\catcode`| = 13
\def|{\TeX}
...
Ово је глуп пример |.
|
Ово је глуп пример ТеХа. |
Имајте на уму да активни карактер треба да буде директно слеђен од стране дефиниције, у супротном компилација неће успети.
Примери
[уреди]- Техинфо
Техинфо користи синтаксу сличну ТеХ-у са једном главном разликом: све функције се уводе са @ уместо са \
. Ово није случајно: заправо користи ТеХ за штампање ПДФ верзије датотеке. Шта у основи ради је унос texinfo.tex који редефинише карактер контролне секвенце. Могућа имплементација:
\catcode`\@=0
@def@@{@char64} % За писање '@' знака.
\catcode`\\=13 @def\{{@tt @char92}}
@ТеХ команда је претходно написана '\ТеХ'. Сада је написана као '@@ТеХ'.
|
ТеХ команда је претходно написана као '\ТеХ'. Сада је написана као '@ТеХ'. |
Овим редефинисањем, '@' би требало да уведе сваку команду, док '\' will заправо штампа обрнуту косу црту карактера.
- Набројавање
Некима се може учинити ЛаТеХ синтакса листе окружења мало гломазном. Овде је брз начин да се дефинише вики налик набројавање:
\catcode`| = 13
\def|{\item {--}}
\def\itemize#1{{\leftskip = 40 pt #1 \par}}
\itemize{
| Прва ставка
| Друга ставка
}
|
- Долар и математика
Ако имате много долар симбола за штампање, можда боље да промените математички знак за промену.
\catcode`$ = 11
\catcode`| = 3
It costs $100.
Хајде да радимо математику: |50+50=100|. Хајде да ово истакнемо:
||50+50=100||
|
\makeatletter и \makeatother
[уреди]Ако сте урадили мало ЛаТеХ хаковања, мора да сте се сусрели са ове две команде,
\makeatletter
и \makeatother
.
У ТеХу '@' знакови припадају кеткод 11 словима подазумевано. То значи да можете да га користите за макро имена. ЛаТеХу чини употребу кеткода тако да наведете правило: све не за јавност, унутрашње макрое којима не би требало да приступе крајњи корисници који садрже најмање један '@' знак у свом имену. У документу, ЛаТеХ мења кеткод од '@'до 12, других.
Зато, када вам је потребан приступ ЛаТеХ унутрашњости, морате приложити све команде приступајући приватним функцијама са \makeatletter
и \makeatother
. Све што оне раде је само мењају кеткод:
\def\makeatletter{\catcode`@ = 11}
\def\makeatother{\catcode`@ = 12}
|
Макрои Обичног ТеХ-а
[уреди]\newcommand
и \renewcommand
су специфичне контролне секвенце ЛаТеХа. Они проверавају да ниједна од постојећих команди не буде у сенци нове дефиниције
У Обичном ТеХ-у, примитиве за макро дефиницију не проверавају могуће сенчење. То је до вас да се уверите да се не разбије ништа.
Синтакса је
\def<macroname>#1<sep1>#2<sep2>{макро садржај, коришћење аргумената #1, бла, #2 ...}
|
Можете користити (скоро) све секвенце карактера између аргумената. На пример хајде да напишемо једноставни макро који ће претворити децимални сепаратор од тачке до зареза. Први покушај:
\def\pointtocomma #1.#2{(#1,#2)}
%%...
\pointtocomma 123.456
|
Ово ће штампати (123,4)56. Додали смо заграде само да бисмо истакли проблем. Сваки параметар је најкраћи могући улаз секвенце која одговара макро дефиницији, укључујући и сепараторе. Тако #1
одговара свим карактерима до прве тачке, и#2
одговара једино првом жетону, тј је први карактер, јер нема сепаратора након тога.
Решење: Додати други сепаратор. Размак може деловати убедљиво:
\def\pointtocomma #1.#2 {(#1,#2)}
|
По правилу, сваки пут када очекујете неколико параметара са посебним сепараторима, смислите последњи сепаратор. Ако не желите да се играте са сепараторима, онда се макрои Обичног ТеХ-а користе као ЛаТеХ макрои (без подразумеваног параметра):
\def\mymacro#1#2#3{{\bf #1}#2{\bf #3}}
%% ...
\mymacro{реч1}{реч2 реч3}{!!!}
|
Проширене дефиниције
[уреди]ТеХ има још једну команду дефиниције: \edef
, која важи за expanded def. Синтакса остаје иста:
\edef<macroname><argumentslist>{<проширени садржај>}
|
Садржај бива проширен (али не и извршен, тј штампан) на месту где је \edef
коришћен, уместо где је коришћен дефинисан макро. Макро експанзија није увек очигледна ...
Пример:
\def\intro{Пример}
\edef\example#1{\intro~---~#1}
\def\intro{Вежба}
\example{Ово је пример}
|
Овде редефинисање \intro
неће утицати на \example
.
Глобалне дефиниције
[уреди]Дефиниције су ограничене својим опсегом. Међутим, било би згодно понекад да се дефинише макро унутар групе која остаје на снази изван групе, а до краја документа. То је оно што ми зовемо глобална дефиниција .
{
\def\LocalTeX{Локално\TeX}
\global\def\GlobalTeX{Глобално\TeX}
}
Још увек можемо приступити \GlobalTeX{} макроу овде.
|
Такође можете користити и \global
команду са \edef
.
Обе команде имају скраћеницу:
\gdef
за\global\def
\xdef
за\global\edef
Дуге дефиниције
[уреди]Команде претходне дефиниције неће дозволити да их користите током више ставова, тј текст садржи \par
команду -- или двоструки прелом реда.
Можете убацити испред дефиниције \long
команду да бисте дозволили више аргумената.
Пример:
\long\def\dummy#1{#1}
\dummy{Први параграф\par Други параграф}
|
Спољашње дефиниције
[уреди]Овај макро префикс спречава дефиниције из које се користе у неком контексту. To je корисно да се консолидују макрои и чини их мање склоним грешкама због лоших контекста. Спољашњи макрои су намењени да се користе ван било ког контекста, отуда њихово име.
На пример следећи код неће радити:
\outer\def\test{тест}
\def\failure{\test}
|
Спољшњи макрои се не смеју појавити у:
- макро параметри
- прескочени услов
- ...
let и futurelet
[уреди]\let<csname><token>
је исти као \expandafter\def\expandafter<csname>\expandafter{<content>}
. Дефинише име нове контролне секвенце која је еквивалентна наведеној token. token је обично друга контролна секвенца.
Приметимо да ће \let
проширити token само једном, насупрот \edef
која ће рекурсивноширити док је то могуће.
Пример[1]:
Коришћење let:\par
\def\txt{a}
\def\foo{\txt}
\let\bar\foo
\bar % Штампа а
\def\txt{b}
\bar % Штампа б
Коришћење edef:\par
\def\txt{a}
\def\foo{\txt}
\edef\bar{\foo}
\bar % Штампа а
\def\txt{b}
\bar % Штампа а
|
\futurelet<csname><token1><token2>...
ради мало другачије. token2 је додељен csname; након тога ТеХ процесира <token1><token2>...
секвенцу. Тако вам \futurelet
омогућава да доделите знак док га користите одмах после.
Име специјалне контролне секвенце
[уреди]Неки макрои могу имати име које није могуће написати какав јесте. Ово је случај макроа чије име се састоји од макро имена.
Пример:
\def\status{пуно}
\def\varempty{Ово је празно}
\def\varfull{Ово је пуно}
\csname var\status \endcsname
|
Последња линија ће штампати реченицу у зависности од \status
.
Команда заправо ради супротно од \string
који штампа име контролне секвенце без проширивања:
{\tt \string\TeX}
|
\TeX |
Контролна експанзија
[уреди]\expandafter{token1}{token2}
ће проширити token2 пре token1. То је некад потребно када проширење token2 жељено, али није могуће због token1.
{\tt \expandafter\string\csname ТеХ\endcsname}
|
\ТеХ |
\noexpand
корисно је имати мало контроле над оним што се проширило у \edef
. Пример:
\def\intro{Пример}
\def\separator{~---~}
\edef\example#1{\intro\noexpand\separator#1}
\example{непроширивање чини сепаратор динамичним у {\tt \string\edef}.}
\def\intro{На пример}
\def\separator{~:~}
\example{сепаратор се променио, али није прва реч.}
|
\the
контрола секвенце ће вам омогућити да видите садржај разних врста ТеХа:
- кеткодови
- чардеф
- параметри фонта
- унутрашњи параметри
- дужине
- регистри
- ...
Пример:
Димензије текста: $ \the\hsize \times \the\vsize $
|
Регистри
[уреди]Регистри су врста откуцаних вариабли. Они у ограничени брјевима, од 0 до 255. Постоји 6 различитих врста:
Врста | Опис |
---|---|
кутија | једна кутија |
рачун | цели бројеви |
димен | дужина |
мускип | глу (у му јединици) |
скип | глу |
токс | низ токена |
ТеХ користи неке регистре интерно, тако да би било боље да их не користите.
Листа резервисаних регистрара:
- \box255 се користи за садржај странице
- \count0-\count9 се користе за нумерисање страница
Стреч регистар (бесплатни):
- \box0-\box254
- \count255
- \dimen0-\dimen9
- \muskip0-\muskip9
- \skip0-\skip9
Додељени регистар коришћењем '=' контролног караткера.За кутије регистре, користи се \setbox
команда.
\count255=17
\setbox\mybox=\hbox{бла}
|
Можете користити један од следећих резервисаних макроа да спречите сукоб:
\newbox
\newcount
\newdimen
\newmuskip
\newskip
\newtoks
|
Ови макрои користе следећу синтаксу: \new*<csname>
.
Пример:
\newbox\mybox
\setbox\mybox=\hbox{бла}
|
Ове команде се не могу користити унутар макроа, иначе сваки позив макроа ће резервисати други регистар.
Можете штампати регистар користећи \the
команду. За рачун користите \number
команду. За кутије користите \box
команду.
\the\hsize
\number\count255
\box\mybox
|
Аритметика
[уреди]Аритметичке могућности ТеХа су веома ограничене, мада ова база може довољно да се прошири до неких занимљивих функција. Три главне функције:
\advance <регистар> <број>
\multiply <регистар> <број>
\divide <регистар> <број>
|
register може бити тип рачун, димен, мускип или скип. Али нема смисла за кутију или токс.
Услови
[уреди]Основна синтакса је:
\if* <тест><тачна акција>\fi
\if* <тест><тачна акција>\else<нетачна акција>\fi
|
где је \if*
једна наредба од следећих.
Контролна секвенца | Опис |
---|---|
\if <a><b>
|
Тачно ако су два карактера кода једнака. |
\ifcat <a><b>
|
Тачно ако су две категорија кода једнаке. |
\ifdim <a><rel><b>
|
Димензија везе, било <, > или =. |
\ifeof
|
Тачно ако је крај фајла или не постоји фајл. |
\iffalse
|
Увек нетачно. |
\ifhbox <reg>
|
Тачно ако регистар кутија садржи хоризонталну кутију. |
\ifhmode
|
Тачно у хоризонталном режиму. |
\ifinner
|
Тачно у унутрашњем режиму. |
\ifmmode
|
Тачно ако је у математичком режиму. |
\ifnum <a><rel><b>
|
Број везе, било <, > или =. |
\ifodd <num>
|
Тачно ако је број непаран. |
\iftrue
|
Увек тачно. |
\ifvbox <reg>
|
Тачно ако регистар кутија садржи вертикалну кутију. |
\ifvmode
|
Тачно у вертикалном режиму. |
\ifvoid <reg>
|
Тачно ако је регистар кутија празан. |
\ifx <a><b>
|
Тачно ако се два макроа шире у један исти, или ако су два кода једнака, или ако су две категорије кодова једнаке. |
Пример:
\ifnum 5>6
Ово је тачно
\else
Ово је нетачно
\fi
|
Ово је нетачно |
Самодефинисани услови
[уреди]Можете створити нове услове (као врста булеан варијабли) помоћу \newif
команде. Помоћу овог самодефинисања услова, можете контролисате излаз вашег кода на елегантан начин.
Најбољи начн илустрације коришћења услова је смислити пример.
Две верзије документа морају бити генерисане. Једна верзија за групу А, друга за остатак људи (тј. оне који не припадају групи А):
1. Користимо \newif
да дефинишемо наш услов (тј. булеан варијаблу).
\newif\ifgroupA
|
2. На следећи начин додељујемо вредност (тачно или нетачно) за наш услов
\groupAtrue % or
\groupAfalse
|
то је:
\<conditionalsname>true
\<conditionalsname>false
|
у зависности од тога коју вредност желимо да поставимо у наш услов.
3. Сада можемо да користимо услов било где након у ако контролна стуктура.
\ifgroupA
% Овде пишемо код документа који је
% намењен за групу А
\else
% Овде пишемо код документа који је
% намењен за остале људе
\fi
|
Цео пример је:
\newif\ifdirector
% Постављамо да је услов нетачан
\directorfalse
\ifdirector
Пишемо нешто за директоријум.
\else
Пишемо нешто за људе.
\fi
|
Пишемо нешто за људе |
Изјава случаја
[уреди]Синтакса је \ifcase <number><case0>\or<case1>\or...\else<defaultcase>\fi
. Ако је number једнак броју случаја, његов садржај ће бити штампан. Приметимо да почиње од 0.
\ifcase 2 a\or b\or c\or d\else e\fi
|
c |
\else
се користи да одреди подразумевани случај (кадгод се ниједан од претходних случајева није поклопио).
Петље
[уреди]Основна синтакса је
\loop <садржај> \if*<услов><тачна акција>\repeat
|
Као увек, content и true action су произвољни ТеХ садржаји. \if*
се односи на било који од услови. Приметимо да нема false action, не можете ставити \else
између \if*
и \repeat
. У неким случајевима ово ће бити супротно од онога што желите; морате да промените услов или да дефинишете носи услов користећи \newif
.
Пример:
\count255 = 1
\loop
\ТеХ
\ifnum\count255 < 10
\advance\count255 by 1
\repeat
|
Овај код ће штампати ТеХ 10 пута.
Не радећи ништа
[уреди]Некад може бити користно рећи ТеХу да желите да не ради ништа.
Постове две команде за то: \relax
и \empty
.
Класичан пример:
\def\myspace{\hskip 25pt\relax}
\myspace{} plus 10pt
|
\relax
спречава нежељено понашање ако је plus
или minus
иза команде.
Разлика између \empty
и \relax
лежи у експанзији: \empty
нестаје након макро експанзије.
ТеХ карактери
[уреди]чар
[уреди]Можемо штампати све знакове користећи \char {charcode}
команду. Чаркод је заправо бајт вредност.
На пример
\char65 = \char `A = \char `\A
|
Већина знакова одговара АСЦИИ вредности (нпр. А-Ша-Ш), неки мењају знакове који не могу да се штампају из АСЦИИ.
chardef and mathchardef
[уреди]Можете дефинисати контролну секвенцу да проширите одређени чар.Синтакса је \chardef<control sequence>=<charcode>
.
Следеће секвенце раде исту ствар.
\chardef\myA=65
\chardef\myA=`A
\chardef\myA=`\A
|
Пример:
\mathchardef\alphachar = "010B
$\alphachar$
|
Мапа фонт кодирања
[уреди]Можемо користити горњи код да одштампамо мапу фонта кодирања.
\count255 = 0
\loop
[\number\count255 =\char\number\count255]
\ifnum\count255 < 127
\advance\count255 by 1
\repeat
|
Друга верзија, са различитим фонтовима, један унос по линији:
\count255 = 0
\loop
[\number\count255 =
\char\number\count255 \
{\tt \char\number\count255}
{\it \char\number\count255}
]
\hfil\break
\ifnum\count255 < 127
\advance\count255 by 1
\repeat
|
Вербатим линије и размаци
[уреди]Прилично је збуњујуће открити како (Ла)ТеХ третира све празнина као исти тип размака глуа. Обичан ТеХ даје неке команде да се сачува размак и нове линије као када напишете:
\begingroup
\obeylines
\obeyspaces
Релевантни текст овде
\endgroup
|
што значи да ћете вероватно морати да комбинете своје окружење и своју команду:
\newenvironment{мојеокружење}{\begingroup \obeylines \obeyspaces}{\endgroup}
\newcommand{\mycommand}[n]{уради нешто са #1 .. #n}
|
а онда у свом тех фајлу:
\begin{мојеокружење}
\mycommand{
који год текст да је важно је
да сачувате размаке и нове линије
јер, као када желите да генерира
вербатим блок касније.
}
\end{мојеокружење}
|
Макрои дефинишу макрое
[уреди]Ово је корисно у неким случајевима, на пример за дефнисање команди језика као што је објашњено на Multilingual versions, где крајњи корисник може да напише
\en{неки енглески текст}
\de{неки немачки текст}
|
и да буде сигуран да је замењн у одговарајући бабел језик.
Хајде да дефинишемо макрое који ће дефинисати команду језике на пример. Ове команде су једноставне: ако је аргумент у вредности \locale
варијабле, онда одговарајући макро штампа његов садржај директно. У супротном, не ради ништа.
У суштини, оно што ми желимо да урадимо је крајње једноставно: дефинисање гомиле макроа овако:
\newcommand{\de}[1]{#1}
\newcommand{\en}[1]{}
\newcommand{\fr}[1]{}
|
У претходном фрагмент коду, само \de
команда иде ка излазу свог садржаја, \en
и \fr
неће ништа штампати.. То је оно што желимо. Проблем настаје када желите да аутоматизујете задатак, или ако имате пуно језика, а желите да промените избор језика. Потребно је само да преместите #1
, али то није згодно и чини немогућим да изаберете бабел језик из командне линије. Размислите о овоме ...
Оно што ћемо да урадимо је да дефинишемо команду језика следећи вредност \locale
варијабле (или неке варијабле по вашем избору). Отуда употреба \equal
команде из ifthen пакета.
Пошто је скоро немогуће написати то у ЛаТеХу, користићемо Обичан ТеХ.
\def\locale{de}
\def\localedef#1{
\ifthenelse{ \equal{\locale}{#1} }{
%% Поставља бабел језик.
%% Дефинише команду за штампање садржаја.
}{
%% Дефинише команду да не штампа ништа.
}
}
|
Појављује се други проблем: како дефинисати команду чије је име варијабла? У многим програмским језицима то није могуће. Оно што бисмо били у искушењу да напишемо је:
\def\#1 #1{#1}
|
Ово неће радити из два разлога.
- Два последња '#1' треба да се односе на аргументе новог макроа, али они бивају проширени до
\localedef
макроа првог аргумента јер су у телу тог макроа. \#1
бива проширен на два токена: '#' и '1', а\def
команда неће радити јер захтева валидно име контролне секвенце.
Решење за проблем 1 је једноставно: користите '##1', што ће проширити до '#1' када је макро извршен.
За пробмел 2, постоји трик. Могуће је рећи tex да је одређени токен контролна секвенца. То је намена \csname...\endcsname
Било како било
\def\csname#1\endcsname ##1{##1}
|
неће радити јер ће редефинисати \csname
у '#1', што ми не желимо, онда ће tex срести \endcsname
, што ће бити грешка.
Морамо одложити експанзију \def
, тј. да кажемо tex да прошири \csname
прво, а онда да примени \def
на то. Постоји команда за то: \expandafter{token1}{token2}
. То ће проширити {token2} пре {token1}.
Коначно, ако желимо да поставимо језик из командне линије, морамо бити у могућности да поставимо \locale
варијаблу тако да је она у изворном коду подразумеване вредности која се може преватићи оном у командној линији. Ово се може извршити помоћу \provdecommand
:
\providecommand\locale{fr}
|
Коначан код је
%% Required package.
\usepackage{ifthen}
%% ТеХ функција која генерише команду језика.
\def\localedef#1#2{
\ifthenelse{ \equal{\locale}{#1} }{
\selectlanguage{#2}
\expandafter\def\csname#1\endcsname ##1{##1}
}{
\expandafter\def\csname#1\endcsname ##1{}
}
}
%% Одабрани језик. Може бити постављен било где пре команде језика.
\providecommand\locale{fr}
%% Команде језика.
\localedef{de}{немачки}
\localedef{en}{енглески}
\localedef{fr}{француски}
%% ...
|
И ви можете саставити са
latex '\providecommand\locale{en}\input{mydocument.tex}'
Белешке и референце
[уреди]- ↑ From tex.stackexchange.com: What is the difference between \let and \edef?
- Додатна литература
- The TeXbook, Donald Knuth
- TeX by Topic, Victor Eijkhout
- TeX for the Impatient, Paul W. Abrahams, Karl Berry and Kathryn A. Hargreaves