> For the complete documentation index, see [llms.txt](https://overleaf-pro.ayaka.space/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://overleaf-pro.ayaka.space/latex/id/artikel-mendalam/09-an-introduction-to-luatex-part-2-understanding-directlua.md).

# Pengantar LuaTeX (Bagian 2): Memahami \directlua

## Tujuan artikel ini

Pada bagian pertama artikel ini, [Pengantar LuaTeX (Bagian 1): Apa itu—dan apa yang membuatnya begitu berbeda?](/latex/id/artikel-mendalam/07-an-introduction-to-luatex-part-1-what-is-it-and-what-makes-it-so-different.md), kami secara singkat meninjau LuaTeX sebagai mesin TeX yang sangat serbaguna: sebuah sistem penyusunan huruf yang canggih dan dapat diprogram, yang menyediakan berbagai alat untuk membangun solusi rekayasa dokumen dan produksi.

Dalam bagian penutup ini, kita akan melihat lebih dekat komponen paling penting dari perangkat LuaTeX: `\directlua` perintah yang menyediakan “gerbang” ke kontrol programatik atas penyusunan huruf LuaTeX melalui bahasa skrip Lua.

Namun, memanfaatkan LuaTeX secara penuh melalui `\directlua` memerlukan pengetahuan dasar tentang beberapa topik TeX: token TeX, daftar token, dan mekanisme ekspansi. Tujuan artikel ini adalah mengeksplorasi dan menjelaskan konsep-konsep dasar TeX ini: merangkai bersama proses-proses terkait TeX di balik `\directlua` untuk mengembangkan pemahaman tentang cara kerjanya dan menyediakan fondasi untuk membangun solusi penyusunan huruf Anda sendiri menggunakan LuaTeX.

Artikel ini mencakup banyak contoh singkat untuk mendemonstrasikan dan menjelaskan aspek-aspek utama dari `\directlua`perilakunya, dengan sengaja menghindari kode yang terlalu kompleks demi potongan kode pendek. Jika diperlukan, contoh menggunakan TeX dasar (mentah/polos)—meskipun kebanyakan orang menggunakan dan lebih menyukai LaTeX (makro), perintah TeX dasar memiliki keunggulan kesederhanaan.

## Pengantar Lua dalam LuaTeX

[Lua](https://www.lua.org/about.html) adalah bahasa skrip yang [kode sumber](https://www.lua.org/download.html) sangat portabel dan mudah disematkan ke dalam aplikasi perangkat lunak, memungkinkan pengembang untuk memasukkan kemampuan skrip ke dalam program mereka. Lua telah disematkan dalam [banyak aplikasi](https://en.wikipedia.org/wiki/List_of_applications_using_Lua) dan merupakan pilihan populer di industri game perangkat lunak—mungkin contoh paling terkenal adalah [World of Warcraft](https://wowwiki.fandom.com/wiki/Lua_functions).

LuaTeX, sesuai namanya, adalah mesin TeX yang menyematkan bahasa skrip Lua, memberikan pengguna kemampuan untuk mengontrol perilaku penyusunan huruf LuaTeX dengan menyertakan program Lua (skrip) ke dalam dokumen mereka. Selain kontrol langsung atas LuaTeX, pengguna juga dapat memanfaatkan Lua murni sebagai bahasa pemrograman yang sangat mumpuni untuk melakukan tugas-tugas yang mungkin sangat sulit dicapai menggunakan bahasa TeX—yang, menurut ukuran apa pun yang adil, merupakan tantangan untuk dipelajari dan dikuasai. Melalui penambahan dan integrasi Lua, LuaTeX menjadi mesin TeX yang sangat serbaguna dan kuat yang secara langsung mendukung dua bahasa pemrograman.

### Menggunakan Lua dan TeX dalam dokumen Anda: masukkan \directlua

Lua dan TeX adalah dua *sangat berbeda* bahasa pemrograman: Lua jauh lebih dekat dengan apa yang kebanyakan orang anggap sebagai bahasa pemrograman, tetapi TeX, dengan kode kategori, token, makro, dan mekanisme ekspansinya, sangat jauh dari pengalaman/harapan kebanyakan orang tentang bahasa untuk menulis program. Namun, seperti yang ditunjukkan sejarah, bahasa TeX tetap bertahan karena ia baik dalam apa yang dirancang untuk dilakukan: mengendalikan penyusunan huruf, meskipun mode operasinya agak rumit.

Untuk mengatasi tantangan mencampur bahasa Lua dan TeX dalam satu dokumen TeX, para pengembang LuaTeX memperkenalkan perintah baru bernama `\directlua` yang merupakan jalan untuk menggunakan Lua—baik sebagai bahasa pemrograman mandiri yang berdiri sendiri maupun untuk mengendalikan perilaku penyusunan huruf LuaTeX.

Fitur `\directlua` perintah memungkinkan pengguna menyematkan kode Lua dalam dokumen TeX mereka; kode itu kemudian diteruskan ke interpreter bahasa Lua bawaan LuaTeX. Namun, `\directlua` juga memungkinkan Anda untuk *menggabungkan* kode Lua dan (La)TeX bersama-sama, dalam `\directlua` perintah—meskipun itu menimbulkan kompleksitas tambahan karena perbedaan mendasar dalam bahasa pemrograman berbasis Lua dan TeX. Tantangan utama saat menggunakan kombinasi kode (La)TeX dan Lua adalah memastikan kedua bahasa itu hidup berdampingan dengan damai dan tidak saling “mengganggu”.

`\directlua` paling cocok digunakan dengan potongan kode Lua yang lebih pendek di dalam dokumen, tetapi Anda bisa menggunakannya dengan program Lua yang lebih luas jika Anda mau. Umumnya, program Lua yang lebih besar, dan pustaka kode Lua, disimpan ke file eksternal yang dapat dimuat dengan menggunakan `dofile()` fungsi dalam sebuah `\directlua` perintah. Dari sudut pandang pemrosesan TeX, keuntungan signifikan dari penggunaan file kode Lua eksternal adalah terhindarnya komplikasi yang timbul dari mekanisme kode kategori TeX—topik yang dieksplorasi sepenuhnya dalam artikel ini.

### Deskripsi yang lebih formal tentang \directlua

Fitur [Manual Referensi LuaTeX](http://www.pragma-ade.com/general/manuals/luatex.pdf) mendeskripsikan `\directlua` sebagai berikut (sedikit dimodifikasi):

> Untuk menggabungkan kode Lua dengan input TeX, diperlukan beberapa primitif baru. Primitif `\directlua` digunakan untuk mengeksekusi kode Lua secara langsung. Sintaks dasarnya adalah `\directlua{⟨code⟩}`. Paket `⟨code⟩` diekspansi sepenuhnya, lalu dimasukkan ke interpreter Lua. Setelah pembacaan dan ekspansi diterapkan pada `⟨code⟩`, daftar token yang dihasilkan dikonversi menjadi string seolah-olah ditampilkan menggunakan `\the\toks`.

Tentu saja ini secara teknis akurat tetapi, mungkin, tidak begitu mudah dipahami tanpa pengetahuan tentang proses TeX tingkat bawah—seperti token dan ekspansi.

## Memahami \directlua: Topik apa yang akan kita bahas?

Dalam artikel ini kita akan melihat lebih dekat beberapa topik latar belakang utama dan menawarkan sejumlah contoh yang dirancang untuk menunjukkan bagaimana `\directlua` bekerja dan di mana (atau mengapa) Anda harus berhati-hati saat menggabungkan TeX dan Lua dalam `⟨code⟩`.

Kita akan mengeksplorasi topik-topik berikut secara cukup rinci untuk menyediakan dasar bagi pemahaman tentang `\directlua` dan “pra-pemrosesan” kode yang Anda gunakan di dalamnya:

* kode kategori dan token TeX: mengonversi teks menjadi token dan token menjadi teks;
* proses ekspansi TeX (dan mencegah ekspansi);
* mekanisme escape Lua untuk karakter dan string;
* menggunakan komentar bergaya Lua;
* pengantar singkat ke API Lua LuaTeX.

Jika Anda memahami bagaimana mesin TeX membuat dan menggunakan token serta mengembangkan kesadaran akan mekanisme ekspansi TeX maka Anda akan memiliki fondasi yang diperlukan untuk membuka versatilitas luar biasa dari `\directlua` perintah.

## Fondasi: dari teks ke token dan dari token ke teks

Overleaf telah menerbitkan beberapa artikel yang membahas secara mendalam token TeX dan konsep terkait, jadi kita tidak akan mengulangi semua materi itu di sini; sebagai gantinya, kami akan menguraikan area/topik yang relevan untuk mengembangkan pemahaman yang lebih baik tentang `\directlua`.

Berikut adalah daftar artikel yang telah diterbitkan sebelumnya yang mungkin menarik:

* [Apa itu token TeX?](/latex/id/artikel-mendalam/53-what-is-a-tex-token.md)
* [Apa itu daftar token TeX?](/latex/id/artikel-mendalam/54-what-is-a-tex-token-list.md)
* [Bagaimana \expandafter bekerja: Pengantar token TeX](/latex/id/artikel-mendalam/19-how-does-expandafter-work-an-introduction-to-tex-tokens.md)
* [Seri enam bagian: Bagaimana sebenarnya makro TeX bekerja?](/latex/id/topik-lainnya/01-a-six-part-series-how-do-tex-macros-actually-work.md)

### Memahami token karakter

Setiap karakter yang dapat dibaca mesin TeX dari file teks diwakili oleh dua nilai numerik:

* nilainya *kode karakter* (nilai ASCII atau, saat ini, titik kode Unicode-nya);
* nilai kedua yang berpusat pada TeX, disebut *kode kategori*.

Pembaca yang ingin mengetahui lebih lanjut tentang kode kategori mungkin tertarik membaca pengantar ini yang diterbitkan oleh Overleaf: [Jadi, kita mulai dari mana? Dengan kode kategori](/latex/id/topik-lainnya/19-how-tex-macros-actually-work-part-1.md#so2c-where-do-we-start3f-with-category-codes).

Misalnya, jika mesin TeX membaca karakter `Sebuah` ia akan memiliki akses ke dua informasi: `Sebuah`kode karakternya (65), dan kode kategorinya (11, biasanya). Setelah TeX memasukkan karakter `Sebuah`, kode kategorinya tidak akan diubah tetapi makro pengguna dapat membuat perubahan kode kategori yang mungkin memengaruhi *berikutnya* karakter `Sebuah` yang *belum dibaca* oleh TeX. Akibatnya, TeX perlu merekam bahwa *ini* karakter `Sebuah`, *yang baru saja dibaca*, memiliki kode kategori 11. Untuk itu TeX menggunakan pasangan bilangan bulat (65,11) untuk menghitung nilai bilangan bulat lain yang disebutnya *token karakter*. Dengan menghitung nilai token itu, yang diteruskan ke pemrosesan internal TeX, karakter tertentu `Sebuah` dan kode kategorinya *terkait bersama*; pada dasarnya, token karakter itu *mewadahi* data yang perlu diketahui TeX tentang karakter itu untuk digunakan dalam aktivitas penyusunan huruf berikutnya yang lebih dalam di dalam mesin TeX.

#### Bagaimana token karakter dihitung?

Pertama, kita perlu mengingat bahwa mesin TeX menggunakan kode kategori 13 untuk tujuan membuat apa yang disebut *karakter aktif*: setiap karakter dengan kode kategori 13 berperilaku seperti makro mini; akibatnya, dan seperti yang akan kita lihat di bawah, token untuk karakter aktif dihitung secara berbeda dari karakter biasa dengan kode kategori lain seperti 10, 11, atau 12.

Untuk *nonaktif* karakter:

* mesin 8-bit yang lebih tua (TeX Knuth, e-TeX, pdfTeX) menghitung token karakter untuk *nonaktif* karakter menggunakan

$$\text{(non-active) character token} = (256 \times \text{category code}) + (\text{ASCII character code})$$

* untuk LuaTeX, yang harus berurusan dengan nilai karakter Unicode, perhitungan untuk *nonaktif* karakter serupa tetapi menghasilkan nilai bilangan bulat yang jauh lebih besar:

$$\text{(non-active) character token} = (2^{21} \times \text{category code}) + (\text{Unicode value})$$

Kembali ke contoh kita sebelumnya untuk huruf A dengan kode kategori 11, LuaTeX akan menghitung nilai token karakter sebesar $$2^{21} \times 11 + 65 = 23068737$$. Setelah dihitung, nilai token karakter itu *mengikat* karakter A tertentu itu ke nilai kode kategori 11. Makro pengguna dapat mengubah kode kategori untuk karakter A berikutnya, tetapi kode kategori milik yang ini telah ditetapkan dengan mengonversinya menjadi token untuk digunakan saat ia melewati cara kerja internal LuaTeX. LuaTeX telah mempertahankan, atau mewadahi, makna yang dimaksud dari karakter tersebut sebagaimana ditentukan pada saat dibaca masuk.

Mesin TeX menggunakan total [16 kode kategori yang berbeda](/latex/id/topik-lainnya/43-table-of-tex-category-codes.md) dan *apa pun* dari kode kategori tersebut dapat ditetapkan, melalui `\catcode` perintah, ke *apa pun* karakter apa pun yang dapat dibaca mesin TeX. Perubahan kode kategori digunakan untuk mengubah cara mesin TeX memproses karakter tertentu dalam input, memungkinkan pengguna TeX menulis makro yang menghasilkan hasil atau perilaku penyusunan huruf khusus.

**Karakter aktif**

Seperti disebutkan, mesin TeX menggunakan kode kategori 13 untuk menempelkan “makna khusus” pada sebuah karakter, menjadikannya apa yang disebut *karakter aktif* yang berperilaku seperti makro mini: tidak diperlukan `\` di depan, karakter yang terisolasi, karena kode kategorinya, sudah cukup untuk memicu perilaku mirip makronya.

Karena karakter aktif bertindak sebagai makro mini, ia tidak dikonversi menjadi sebuah *token karakter* tetapi menjadi tipe token bilangan bulat kedua yang disebut *token perintah*. Ini dihitung sebagai berikut:

* untuk mesin 8-bit yang lebih tua (TeX Knuth, e-TeX, pdfTeX) token untuk karakter aktif dihitung melalui:

1. hitung nilai antara yang disebut $$\text{curcs}$$ (**cur**rent **c**ontrol **s**equence) di mana $$\text{curcs} = \text{character code} + 1$$3. hitung nilai token di mana $$\text{active character token} = \text{curcs} + \text{4095}$$

* untuk LuaTeX perhitungannya sedikit lebih kompleks karena harus menangani seluruh rentang karakter Unicode, dan salah satunya dapat dijadikan aktif:

1. hitung nilai bilangan bulat antara $$\text{curcs}$$ dengan menerapkan apa yang disebut *fungsi hash* pada nilai titik kode Unicode karakter aktif yang diekspresikan dalam UTF-8: $$\text{curcs}=\texttt{hashfunction}\text{(UTF-8 text for Unicode value of active character)}$$3. hitung nilai token bilangan bulat: $$\text{active character token} = \text{curcs} + 2^{29} - 1$$

**Contoh**

* mesin 8-bit: perhitungan token untuk karakter aktif `~` (kode karakter 126) menghasilkan $$\text{curcs} = 126 + 1 = 127$$, menghasilkan nilai token sebesar $$4095 + 127 = 4222$$.
* LuaTeX: perhitungan token untuk karakter aktif `~` menghasilkan $$\text{curcs}=3186$$ menghasilkan nilai token sebesar $$3186 + 2^{29} - 1 = 536874097$$. Token LuaTeX menggunakan nilai bilangan bulat yang jauh lebih besar!

### Memahami token perintah

Selain memproses *individual* karakter, mesin TeX tentu saja dapat memproses *rangkaian* karakter yang disebut *perintah* (atau, lebih tepatnya, *urutan kendali*). Menurut tradisi, `\` karakter

Mesin TeX mengenali dua jenis perintah yang dikenal sebagai *kata kendali* dan *simbol kendali*:

* **kata kendali**: perintah yang dibentuk dari satu atau lebih karakter yang memiliki kode kategori 11;
* **simbol kendali**: perintah satu karakter di mana kode kategori karakter itu *tidak* 11: seperti `\$`, `\#` atau `\\`.

**Catatan**: Primitif TeX `\chardef`, `\mathchardef`, `\countdef`, `\dimendef`, `\skipdef`, `\muskipdef` dan `\toksdef` juga digunakan untuk mendefinisikan urutan kendali tetapi, tidak seperti definisi makro biasa, urutan kendali yang dihasilkan (kata kendali atau simbol kendali) *tidak dapat diekspansi*—kita akan membahasnya lebih detail di bawah.

#### Bagaimana token perintah dihitung?

Sama seperti karakter aktif, mesin TeX menggunakan tipe token bilangan bulat kedua untuk merepresentasikan perintah: *token perintah*—ingat bahwa karakter aktif juga menghasilkan token perintah karena mereka berperilaku sebagai makro mini.

Perhitungan yang digunakan oleh mesin 8-bit untuk membuat bilangan bulat token-perintah dapat ditemukan dalam [artikel Overleaf](/latex/id/artikel-mendalam/19-how-does-expandafter-work-an-introduction-to-tex-tokens.md#how-tex-calculates-token-values)ini. Di sini, kita akan meringkas langkah-langkah kunci dalam perhitungan token perintah untuk LuaTeX—yang sedikit berbeda karena LuaTeX harus memproses nilai kode karakter Unicode yang bisa jauh lebih besar daripada nilai 8-bit; namun, perhitungan LuaTeX mengikuti prinsip umum yang sama yang digunakan oleh mesin 8-bit yang lebih tua.

Setelah mendeteksi perintah yang masuk, mesin TeX, termasuk LuaTeX, mengabaikan karakter `\` di depan: ia tidak digunakan dalam perhitungan nilai token perintah tetapi hanya bertindak sebagai “saklar” untuk memberi tahu mesin TeX bahwa ia perlu memproses sebuah perintah. Nilai token perintah dihitung menggunakan urutan karakter (satu atau lebih) yang terdapat dalam nama perintah—LuaTeX menghitung token perintah untuk simbol kendali dan kata kendali menggunakan algoritme yang sama:

1. hitung nilai bilangan bulat antara $$\text{curcs}$$ dengan menerapkan apa yang disebut [fungsi hash](https://en.wikipedia.org/wiki/Hash_function) pada string UTF-8 Unicode dari karakter yang terkandung dalam nama perintah: $$\text{curcs}=\texttt{hashfunction}\text{(Unicode UTF-8 string of characters in command name)}$$3. hitung nilai token perintah di mana $$\text{command token} = \text{curcs} + 2^{29} - 1$$

**Contoh**

* untuk `\\` perintah (simbol kendali), LuaTeX menghitung $$\text{curcs}=94$$, menghasilkan nilai token untuk `\\` sebesar $$94 + 2^{29} - 1 = 536871005$$.
* untuk `\vskip` primitif (kata kendali) LuaTeX menghitung $$\text{curcs}=3560$$, menghasilkan nilai token untuk `\vskip` sebesar $$3560 + 2^{29} -1 = 536874471$$.
* untuk makro buatan pengguna `\mynewmacro` (kata kendali) LuaTeX menghitung $$\text{curcs} = 2971$$, menghasilkan nilai token untuk `\mynewmacro` sebesar $$2971 + 2^{29} -1 = 536873882$$.

Setelah dibuat, token dapat disimpan untuk digunakan nanti melalui apa yang disebut *daftar token* atau dapat segera diteruskan untuk pemrosesan lebih lanjut di dalam mesin TeX. Menggunakan nilai bilangan bulat untuk merepresentasikan token tidak hanya bekerja di semua jenis platform komputasi/sistem operasi tetapi juga merupakan cara yang sangat efisien bagi TeX untuk menyimpan/memproses data.

### Bagaimana mesin TeX mengidentifikasi jenis token (perintah atau karakter)

Diberikan nilai token bilangan bulat tertentu, $$T$$, mesin TeX dapat dengan mudah menentukan apakah $$T$$ merepresentasikan perintah atau karakter dengan menguji apakah $$T$$ melebihi suatu $$\text{threshold value}$$—itu $$\text{threshold value}$$ bergantung pada mesin TeX. Jika $$T \geq \text{threshold value}$$ maka $$T$$ adalah token perintah, jika tidak $$T$$ adalah token karakter. The $$\text{threshold value}$$ adalah $$4095$$ untuk mesin 8-bit dan $$2^{29}-1$$ (536.870.911) untuk LuaTeX. Knuth merancang metode yang digunakan dalam rumus perhitungan token sehingga mesin TeX-nya, dan semua mesin berikutnya yang didasarkan pada kode/arsitekturnya, dapat menguji nilai token dengan cepat dan mudah.

## Token dapat dipisah (dan dikonversi kembali menjadi teks)

Token (bilangan bulat) adalah mekanisme melalui mana mesin TeX “mewadahi” segala sesuatu yang perlu direkam tentang suatu item input (karakter atau perintah). Namun, ada saat-saat ketika mesin TeX perlu membalikkan proses tokenisasi—untuk mengetahui apa yang awalnya dibaca untuk menghasilkan nilai token itu—sebuah karakter individu atau urutan satu atau lebih karakter yang membentuk nama suatu perintah:

* **untuk token karakter**: Setiap token karakter dapat dipisahkan menjadi dua bagian penyusunnya: kode karakter dan kode kategori yang sesuai yang ditetapkan untuk karakter itu *pada saat pertama kali dibaca*. Seperti semua mesin TeX, LuaTeX tidak akan mengubah penetapan kode kategori asli itu tetapi akan memanfaatkannya selama aktivitas pemrosesan internal selanjutnya.
* **untuk token perintah:** Ini sedikit lebih rinci tetapi jika Anda melihat perhitungan token perintah oleh LuaTeX, termasuk token untuk karakter aktif, Anda akan melihat mereka mengikuti pola: $$\text{command token} = \text{curcs} + 2^{29} -1$$

di mana $$\text{curcs}$$ dihitung menurut jenis token perintah yang dihasilkan: karakter aktif, simbol kendali atau kata kendali. Variabel $$\text{curcs}$$ adalah komponen *sangat* penting dari operasi internal mesin TeX: dengan nilai token perintah (bilangan bulat) apa pun LuaTeX dapat dengan sangat mudah mengekstrak nilai $$\text{curcs}$$ dari token perintah itu menggunakan $$\text{curcs} = \text{token value} - (2^{29} -1)$$.

### Mengapa $$\text{curcs}$$ begitu penting?

Variabel internal TeX $$\text{curcs}$$ (**cur**rent **c**ontrol **s**sequence) adalah komponen yang sangat penting dari operasi “di balik layar” internal mesin TeX. Meskipun Anda tidak akan, dan tidak bisa, menggunakan atau mengaksesnya secara langsung dalam kode Anda, $$\text{curcs}$$ memainkan peran penting karena mesin TeX menggunakan nilai terkini dari $$\text{curcs}$$ sebagai indeks ke tabel internal yang menyimpan data tentang setiap perintah yang saat ini dikenal oleh mesin. Tabel-tabel itu menyimpan informasi tentang makna saat ini dari suatu perintah: apa yang dilakukannya, atau representasi apa yang dimilikinya dan, selain itu, mereka merekam urutan karakter yang semula digunakan untuk menghitung $$\text{curcs}$$ nilai itu. Dengan mengekstrak nilai $$\text{curcs}$$ dari token perintah, mesin TeX dapat menentukan nama, yaitu teks yang dapat dibaca manusia, yang berkorespondensi dengan token apa pun (perintah), memungkinkan mesin melakukan konversi token-ke-teks yang merupakan aspek kunci dari `\directlua`operasinya.

### Mengonversi token bilangan bulat kembali menjadi karakter atau urutan karakter (nama perintah)

Kita telah melihat bahwa mesin TeX mengonversi karakter input, atau urutan karakter, menjadi nilai token bilangan bulat tetapi ada kalanya mesin TeX perlu *membalik* proses itu—untuk menghasilkan teks yang dapat dibaca manusia yang semula digunakan untuk membuat nilai token bilangan bulat tersebut; misalnya:

* menulis pesan kesalahan atau peringatan ke layar atau `.log` berkas;
* mengeluarkan kode TeX/LaTeX ke file teks melalui `\write` perintah;
* saat mengonversi urutan token menjadi teks di dalam `\directlua` (seperti yang akan segera kita lihat!)

#### Mengonversi token karakter menjadi teks

Seperti disebutkan, token untuk karakter nonaktif dihitung menggunakan kode kategori dan kode karakter (nilai Unicode) dari karakter input. LuaTeX menggunakan rumus:

$$\text{character token} = (2^{21} \times \text{category code}) + (\text{Unicode value})$$

Ini adalah tugas pemrograman yang sederhana untuk memisahkan bilangan bulat $$\text{character token}$$ nilai untuk memperoleh kode karakter penyusunnya ($$\text{Unicode value}$$) dan $$\text{category code}$$.

#### Mengonversi token perintah menjadi teks

Semua mesin TeX menyimpan nama (urutan karakter) dari setiap perintah yang mereka “ketahui”: apakah perintah itu makro buatan pengguna atau primitif bawaan—penyimpanan nama perintah primitif terjadi saat mesin TeX mulai berjalan, jauh sebelum ia mulai memproses kode Anda. Untuk perintah buatan pengguna (makro), nama makro itu (tanpa `\`karakter \ di depan) disimpan sebagai bagian dari proses definisi makro di dalam mesin TeX.

Ketika mesin TeX perlu mengakses atau mengeluarkan teks yang dapat dibaca manusia dari mana token perintah bilangan bulat semula dihitung, ia pertama-tama akan menentukan $$\text{curcs}$$ nilai untuk token itu; dalam LuaTeX, $$\text{curcs} = \text{token} - (2^{29} -1$$). Dengan menggunakan nilai $$\text{curcs}$$ yang diekstrak dari token perintah, mesin TeX dapat mengakses struktur data internal yang disebut *string pool* untuk menentukan urutan karakter yang dapat dibaca manusia yang semula digunakan untuk menghitung nilai khusus itu untuk $$\text{curcs}$$ dan, akibatnya, token perintah yang bersesuaian.

Seperti yang akan kita lihat, aktivitas pemrosesan token ini—mengonversi urutan karakter menjadi nilai token bilangan bulat dan mengonversi nilai token bilangan bulat kembali menjadi urutan karakter (“de-tokenization”)—adalah *mekanisme mendasar* yang digunakan di dalam `\directlua`.

## Daftar token

Saat mesin TeX membaca input, menghasilkan token karakter dan perintah (dan memprosesnya), ia mungkin menemui perintah tertentu yang menginstruksikan mesin untuk (sementara) berhenti meneruskan token untuk diproses lebih lanjut tetapi, sebagai gantinya, menyimpannya untuk digunakan nanti. Contoh yang paling umum adalah mendefinisikan makro menggunakan salah satu perintah definisi makro `\def`, `\edef`, `\gdef` atau `\xdef`—perintah LaTeX seperti `\newcommand` adalah makro yang menyediakan fungsionalitas tambahan yang dibangun di sekitar primitif tingkat rendah yang pada akhirnya melakukan proses definisi makro yang sebenarnya. Sebuah makro dapat dianggap sebagai nama yang diberikan pada daftar token tersimpan tertentu: sebuah daftar token.

Mesin TeX *secara luas* menggunakan daftar token, terutama [daftar internal sementara yang hanya untuk internal](/latex/id/artikel-mendalam/21-how-does-expandafter-work-tex-uses-temporary-token-lists.md) yang digunakan untuk tujuan pemrosesan internal. Setiap mesin TeX juga menyediakan perintah tingkat pengguna untuk membuat daftar token yang disimpan untuk saat pengguna, atau mesin TeX itu sendiri, membutuhkannya. Jumlah perintah pembuatan daftar token (primitif bawaan) bervariasi menurut mesin TeX tetapi semuanya memiliki seperangkat minimum inti yang didukung oleh setiap mesin, seperti `\toks` primitif.

Dalam praktiknya, daftar token hanyalah urutan nilai bilangan bulat yang disimpan:

* input dibaca untuk menghasilkan (menghitung) token individual, yang merepresentasikan karakter atau perintah;
* setiap token kemudian disimpan, mempertahankan urutan ketika token dihasilkan dari input.

Mesin TeX menyimpan daftar token menggunakan struktur data yang disebut [daftar tertaut](https://en.wikipedia.org/wiki/Linked_list) (varietas yang terhubung-satu). Pembaca yang ingin tahu lebih lanjut tentang daftar token dipersilakan membaca artikel Overleaf [Apa itu daftar token TeX?](/latex/id/artikel-mendalam/54-what-is-a-tex-token-list.md) yang menggunakan analogi untuk membangun konsep/gagasan di balik daftar token. Eksplorasi mendalam daftar token TeX, dan bagaimana mereka digunakan dalam pemrosesan makro, dapat ditemukan dalam seri artikel Overleaf [Bagaimana sebenarnya cara kerja makro TeX?](/latex/id/topik-lainnya/01-a-six-part-series-how-do-tex-macros-actually-work.md)

#### Daftar token dalam bentuk grafis

Grafik berikut menunjukkan daftar token yang dihasilkan LuaTeX dengan nilai token yang sesuai yang dihasilkan dari input berikut

`Hi, \TeX! \hskip 5bp`

Misalnya, jika kita mendefinisikan `\mymacro` sebagai `\def\mymacro{Hi, \TeX! \hskip 5bp}` definisi dari `\mymacro` akan disimpan dalam memori menggunakan daftar token seperti ini:

![](/files/85d6ffda54929346ecb2b2928a488fafe244ebae)

Daftar token adalah urutan item yang terhubung yang disebut *node*node, nama yang diberikan pada paket kecil memori LuaTeX yang dialokasikan untuk menampung setiap item dalam daftar (seperti tautan individual dalam rantai). Setiap node berisi nilai token bilangan bulat dan alamat memori dari *node* berikutnya dalam rantai, membentuk struktur data yang disebut [daftar tertaut](https://en.wikipedia.org/wiki/Linked_list). Node terakhir menandai akhir daftar menggunakan “nilai null” khusus untuk node berikutnya—karena memang tidak ada.

**Catatan:**

* Untuk kemudahan, kami menyertakan alamat setiap node individual tetapi, dalam praktiknya, data itu tidak disimpan di dalam node daftar token; hanya alamat *node berikutnya* yang diperlukan untuk membangun daftar token mesin TeX.
* Kolom kedua dalam grafik berjudul “Apa arti setiap token” menunjukkan serangkaian kotak abu-abu yang berisi informasi tentang token yang terkandung dalam setiap node: ini murni untuk informasi dan *tidak* merupakan bagian dari data aktual yang disimpan dalam daftar token.

Berikut adalah tabel nilai token yang terkandung dalam daftar token yang digambarkan di atas:

|                |                     |                                                                               |                 |
| -------------- | ------------------- | ----------------------------------------------------------------------------- | --------------- |
| **Item input** | **Jenis input**     | <p><strong>Kode kategori</strong><br><br><strong>(jika karakter)</strong></p> | **Nilai token** |
| H              | karakter            | 11                                                                            | 23068744        |
| i              | karakter            | 11                                                                            | 23068777        |
| ,              | karakter            | 12                                                                            | 25165868        |
|                | karakter            | 10                                                                            | 20971552        |
| \TeX           | perintah (makro)    |                                                                               | 536871539       |
| !              | karakter            | 12                                                                            | 25165857        |
|                | karakter            | 10                                                                            | 20971552        |
| \hskip         | perintah (primitif) |                                                                               | 536874247       |
| 5              | karakter            | 12                                                                            | 25165877        |
| b              | karakter            | 11                                                                            | 23068770        |
| p              | karakter            | 11                                                                            | 23068784        |

**Catatan:** Teks input asli kita memiliki a setelah `\hskip` perintah tetapi tidak ada token yang merepresentasikan karakter itu dalam daftar token. Karakter itu diserap oleh proses pemindaian (pembacaan) input LuaTeX karena digunakan untuk mengakhiri pencarian LuaTeX atas karakter yang membentuk `\hskip` perintah.

## Bagaimana \directlua benar-benar bekerja

Sekarang setelah kita telah mengeksplorasi token, daftar token, dan mengonversi token ke teks, tantangan berikutnya adalah memahami konsep token pada mesin TeX *ekspansi*.

Seperti dicatat, `\directlua{⟨code⟩}` dapat diminta untuk memproses `⟨code⟩` yang berisi kode Lua dan TeX/LaTeX, tetapi interpreter bahasa Lua bawaan LuaTeX tidak memahami TeX atau LaTeX: jadi bagaimana ini bisa bekerja? Bagaimana mungkin `⟨code⟩` untuk memuat instruksi TeX/LaTeX tanpa benar-benar membingungkan interpreter Lua dengan perintah yang tidak dipahaminya? Misalnya, perintah `\directlua` berikut hanya menggunakan makro TeX, tetapi berhasil:

```
\def\aa{tex}
\def\bb{.}
\def\cc{print}
\def\dd{("Hello")}
\directlua{
   \aa\bb\cc\dd
}
```

Ini `\directlua` menghasilkan penataan huruf LuaTeX `Hello` tetapi mengapa dan bagaimana ini bekerja karena bahasa Lua tidak memahami makro TeX?

Jawabannya terkandung dalam deskripsi sebelumnya yang kita pinjam dari [Manual Referensi LuaTeX](http://www.pragma-ade.com/general/manuals/luatex.pdf) tetapi kita dapat menganggap bahwa `\directlua{⟨code⟩}` bekerja dengan LuaTeX yang mula-mula melakukan “pra-pemrosesan” pada `⟨code⟩` sebelum apa pun diteruskan ke interpreter Lua. Sifat “pra-pemrosesan” ini—yakni, apa sebenarnya artinya dan konsekuensinya bagi `⟨code⟩`—adalah topik berikutnya yang akan kita bahas untuk membantu pembaca yang tertarik memanfaatkan kekuatan dan fleksibilitas `\directlua`.

### Bagaimana LuaTeX memproses \directlua: pandangan awal

Untuk membangun pemahaman kita tentang `\directlua`aktivitas “pra-pemrosesan” kita dapat memulai dengan diagram sederhana berikut yang memberi gambaran umum tentang apa yang terjadi.  `⟨code⟩` yang disediakan kepada `\directlua{⟨code⟩}` mula-mula dikonversi menjadi token menggunakan proses dan perhitungan yang dibahas di atas; urutan token itu disimpan dalam daftar token. Setelah daftar token itu dibangun, setiap token dalam daftar tersebut dikonversi kembali ke representasi tekstualnya: teks yang dihasilkan oleh setiap token—token karakter atau token perintah—digabungkan (dikonkatenasi) untuk membuat satu string kode yang diteruskan ke interpreter Lua untuk dieksekusi.

![](/files/66dd95f13fba606f565cf4b465870a21e8c04c99)

Tapi tunggu, apa gunanya pergi dari teks ke token lalu langsung mengonversi token-token itu kembali menjadi teks? Anda mungkin tidak akan terkejut mengetahui bahwa, ya, ada proses tambahan yang sangat penting yang belum kita sertakan dalam grafik ini: *ekspansi token*. Setiap token yang dihasilkan dari teks dalam `⟨code⟩` Anda menjalani semacam “inspeksi” di mana LuaTeX menerapkan uji untuk melihat apakah token itu mewakili perintah yang termasuk dalam subset yang dikenal sebagai *perintah yang dapat diekspansi*. Jika ya, LuaTeX memfilter perintah itu dengan *menghapus* dari `⟨code⟩` dan *menggantinya* dengan hasil dari suatu proses yang oleh mesin TeX disebut *ekspansi token*.

### Bagaimana LuaTeX memproses \directlua: pandangan kedua (tentang ekspansi)

Mekanisme ekspansi TeX adalah komponen inti dari semua mesin penataan huruf berbasis TeX karena, pada akhirnya, masing-masing diturunkan dari (atau berbasis pada) kode sumber asli dan desain TeX karya Knuth. Namun, konsep ekspansi sulit dijelaskan dengan bahasa yang singkat namun tetap mudah diakses, karena dalam praktiknya ekspansi adalah istilah “payung” yang digunakan untuk menggambarkan satu proses—tetapi yang menghasilkan beragam keluaran. Hasil-hasil yang bervariasi itu merupakan konsekuensi dari kumpulan perintah yang agak eklektik yang dapat dikenai ekspansi, jadi Anda dapat menganggap bahwa setiap perintah yang dapat diekspansi memiliki “perilaku ekspansi” tertentu.

Sebagai *aproksimasi pertama* untuk memahami ekspansi kita dapat mengatakan bahwa ekspansi sebuah token (perintah) berarti *menghapus* perintah (token) itu dari masukan TeX saat ini dan *menggantinya* menggantinya dengan urutan token yang dihasilkan dari mengeksekusi perintah yang dapat diekspansi tertentu itu—mengganti token asli dengan hasil/konsekuensi dari ekspansinya *perilaku*. Namun, “definisi” awal tentang ekspansi ini—dalam hal menghasilkan token baru untuk dibaca TeX—tidak sepenuhnya akurat untuk semua perintah yang dapat diekspansi, tetapi cukup baik sebagai titik awal.

Untuk memberikan contoh yang lugas: primitif TeX `\jobname` adalah perintah yang dapat diekspansi dan *ekspansi* nya adalah urutan token karakter yang mewakili nama berkas masukan utama TeX. Jika TeX memutuskan untuk mengekspansi sebuah `\jobname` perintah (token), itu *dihapus* dari sumber masukan TeX saat ini dan *digantikan* oleh urutan token karakter yang dihasilkannya—yang kemudian dibaca/diproses oleh TeX.

Di dalam `\directlua`, setelah token yang dapat diekspansi diproses (dihapus) dan digantikan oleh token baru, LuaTeX akan terus membaca token baru yang baru saja ditempatkannya—tetapi beberapa token baru itu juga bisa dapat diekspansi. Karena `\directlua` melakukan apa yang disebut *ekspansi penuh*, LuaTeX akan membaca token-token baru itu dan, sekali lagi, menjalani proses ekspansi untuk mengekspansi (menghapus) token-token baru yang dapat diekspansi—proses ekspansi ini berlanjut sampai tidak ada token yang dapat diekspansi yang tersisa. Namun, ada dua pengecualian penting terhadap aturan “terus mengekspansi” ini, yang keduanya akan kita bahas di bawah:

* menggunakan konstruksi `\the\toks`;
* pencegahan (penekanan) yang disengaja terhadap ekspansi untuk satu atau lebih token yang dipilih.

Seperti dicatat, definisi kerja kita (aproksimasi pertama) untuk memahami ekspansi tidak mencakup seluruh rentang perilaku ekspansi yang ditunjukkan oleh subset perintah yang dapat diekspansi. Misalnya, beberapa perintah yang dapat diekspansi tidak menghasilkan token dengan cara seperti yang `\jobname` lakukan, tetapi mereka mungkin:

* “memfilter” token dari masukan: perintah kondisional mesin TeX (`\if`, `\ifcat`, `\ifnum`, `\ifdim`, `\ifodd`, `\ifvmode`, …) dapat diekspansi. Perilaku ekspansinya adalah jenis “pemfilteran token”—kondisional dapat digunakan dalam `\directlua`.
* “mengakali” token dalam masukan:  [`\expandafter` perintah](/latex/id/artikel-mendalam/03-a-six-part-article-series-on-expandafter-tex-tokens-and-expansion.md) dapat diekspansi dan mengubah urutan di mana dua token diekspansi.
* mencegah ekspansi: perintah yang dapat diekspansi `\noexpand` dan `\unexpanded` menekan ekspansi token perintah dalam masukan.
* mengonversi urutan karakter dalam masukan menjadi token perintah: `\csname … \endcsname.`
* mengonversi kuantitas internal menjadi urutan token karakter: `\number` dan `\the` adalah perintah yang dapat diekspansi yang menghasilkan urutan token karakter yang mewakili nilai suatu kuantitas internal.
* mengonversi token perintah menjadi token karakter: `\string` dan `\detokenize` adalah perintah yang dapat diekspansi yang mengonversi argumen mereka menjadi urutan token karakter dengan kode kategori 12. Perhatikan bahwa `\detokenize` berbeda dari `\string`: `\detokenize` dapat memproses beberapa token dan menambahkan karakter spasi, dengan kode kategori 10, setelah memproses token perintah yang dibuat dari *kata kendali*. Secara efektif, `\detokenize` menambahkan karakter spasi di akhir setelah nama perintah—kita akan melihat beberapa contoh nanti di artikel ini.

#### Memperhalus “definisi” ekspansi kita

Sekarang kita dapat menggeneralisasi definisi kita dan mengatakan bahwa ekspansi sebuah perintah (token) melibatkan *penghapusan* dari perintah (token) itu dari sumber masukan TeX saat ini dan *menggantinya* dengan hasil dari *operasi token* yang dilakukan oleh perintah itu. Intinya, proses ekspansi menyebabkan sebuah perintah yang dapat diekspansi melakukan semacam “operasi” pada token dalam masukan TeX saat ini yang memengaruhi jumlah, atau perilaku, token yang selanjutnya akan dibaca TeX—sifat persis dari “operasi” itu bergantung pada perintah mana yang sedang diekspansi. Semua makro, dan karakter aktif, dapat diekspansi, tetapi hanya sejumlah kecil perintah bawaan (primitif) dari mesin TeX yang diklasifikasikan sebagai dapat diekspansi—daftar perintah yang dapat diekspansi bergantung pada mesin TeX yang Anda gunakan—LuaTeX memiliki cukup banyak di antaranya.

Setiap mesin TeX baru mewarisi perintah primitif yang dibangun ke dalam leluhurnya—mesin TeX generasi sebelumnya yang menjadi dasar pengembangannya—dan beberapa primitif yang diwarisi itu akan dapat diekspansi. Tentu saja, mesin TeX baru dapat memilih untuk tidak mengimplementasikan beberapa perintah primitif yang terdapat pada mesin sebelumnya atau memodifikasi perilakunya agar sesuai dengan kebutuhan mesin baru. Selain itu, mesin TeX baru biasanya mengimplementasikan primitif tambahan untuk memberikan dukungan bagi fungsionalitasnya yang ditingkatkan—beberapa di antaranya juga mungkin dapat diekspansi. Akibatnya, jumlah perintah yang dapat diekspansi yang tersedia bagi Anda akan bervariasi sesuai dengan mesin TeX yang Anda gunakan—LuaTeX memiliki cukup banyak.

Kesulitan lain dalam menjelaskan/memahami ekspansi, dan mungkin tantangan yang sebenarnya, adalah mengetahui dengan tepat *kapan* mesin TeX benar-benar akan, atau tidak akan, melakukan proses ekspansi. Itu adalah topik yang besar dan kompleks karena ekspansi tertanam sangat dalam di seluruh cara kerja internal mesin TeX: kita tidak punya ruang untuk membahas ini secara rinci selain penggunaan ekspansi dalam `\directlua`.

### Bagaimana LuaTeX memproses \directlua: pandangan akhir

Diagram berikut merangkum `\directlua` aktivitas pra-pemrosesan yang terjadi di dalam mesin LuaTeX itu sendiri. Dalam diagram ini kami juga menunjukkan dua fungsi LuaTeX tingkat rendah (internal) yang benar-benar melakukan pekerjaannya: `scan_toks()` dan `tokenlist_to_cstring()`. Fungsi-fungsi itu ditulis dalam bahasa C dan berada jauh di dalam perangkat lunak eksekutabel LuaTeX: mereka adalah bagian dari mesin internal LuaTeX dan tidak *langsung* dapat diakses oleh kode TeX/LaTeX Anda.

![](/files/c57f1ae763be83a2b460e25bd84b352a91032c04)

Deskripsi berikut tentang `\directlua ⟨code⟩`tentang aktivitas pra-pemrosesannya merangkum diagram di atas.

1. Urutan karakter dalam ⟨code⟩ Anda diproses oleh `scan_toks()`. Tujuannya adalah membaca ⟨code⟩ Anda karakter demi karakter untuk menghasilkan token karakter dan token perintah. Karena ia membuat token, kode kategori yang ditetapkan pada setiap karakter dalam ⟨code⟩, pada saat dibaca masuk, sangatlah penting.
2. Selama pemrosesan token (pembuatan) oleh `scan_toks()`setiap perintah yang dapat diekspansi diekspansi *kecuali* dicegah melalui perintah seperti `\protected` (definisi makro), `\noexpand`, `\unexpanded` dll. Karakter aktif (kode kategori 13) juga diekspansi (kecuali dicegah).
3. Aliran token yang dibuat oleh `scan_toks()` dibangun menjadi satu daftar token panjang—token yang ada dalam daftar itu mencakup token yang dihasilkan dari penerapan ekspansi pada perintah yang dapat diekspansi (seperti makro) yang ada dalam `⟨code⟩`Anda. Perhatikan juga bahwa `scan_toks()` *tidak* tidak memicu atau menyebabkan eksekusi token apa pun yang mewakili perintah yang tidak dapat diekspansi: token yang tidak dapat diekspansi seperti itu hanya dilewatkan untuk dimasukkan ke dalam daftar token yang sedang dibangun.
4. Setelah daftar token selesai dan semua aktivitas ekspansi selesai, daftar token itu diproses oleh fungsi lain yang disebut `tokenlist_to_cstring()` yang mengonversi setiap token dalam daftar token akhir kembali menjadi representasi tekstualnya. Ini menghasilkan string teks yang merupakan kode Lua yang akan diteruskan ke interpreter Lua. Agar berhasil dieksekusi, string itu harus berisi kode Lua yang secara sintaksis benar.
5. Pemrosesan kode itu oleh Lua terjadi dalam dua langkah:
6. Interpreter Lua bawaan LuaTeX mengurai dan “mengompilasi” kode Lua yang dihasilkan pada langkah-langkah sebelumnya. Jika penguraian/kompilasi itu gagal, interpreter Lua akan menghasilkan kesalahan (seperti kesalahan sintaks)—kesalahan tersebut dapat menyebabkan proses LuaTeX gagal kecuali Anda memilih untuk menggunakan `--interaction=nonstopmode` pada baris perintah.
7. Jika penguraian/kompilasi berhasil, interpreter Lua mengeksekusi kode yang dikompilasi pada langkah (5a).

Pada intinya, fungsi `scan_toks()` adalah inti dari aktivitas pra-pemrosesan LuaTeX: tugas utamanya adalah mengekspansi semua perintah TeX/LaTeX yang dapat diekspansi yang terkandung dalam teks `⟨code⟩` Anda dan membangun daftar token dari semua yang telah diprosesnya. Sekali lagi, kami menekankan bahwa `scan_toks()` *tidak mengeksekusi perintah yang tidak dapat diekspansi* (token): ia hanya *menyimpan* token-token tersebut dalam daftar token yang sedang dibangunnya. Setelah selesai, daftar token itu kemudian dikonversi *kembali ke representasi tekstual* oleh `tokenlist_to_cstring()`—daftar token adalah konsep khusus TeX yang sama sekali asing bagi interpreter Lua, sehingga perlu mengonversinya menjadi teks, menjadi kode Lua untuk diteruskan ke interpreter Lua.

## Ekspansi sebagai “antarmuka” bahasa pemrograman

Anda dapat menganggap `\directlua`proses ekspansi LuaTeX digunakan sebagai mekanisme, atau antarmuka, untuk meneruskan data/informasi dari “Dunia TeX” ke “Dunia Lua”: menyediakan metode bagi bahasa TeX untuk mengomunikasikan data ke bahasa Lua. Misalnya, kode TeX seperti `\number\count75` dapat digunakan untuk mentransfer nilai “Dunia TeX” yang disimpan di register hitung 75 ke variabel integer x di “Dunia Lua”:

```
\count75=1564 % Data yang ada di "Dunia TeX"
\directlua{
   local x=\number\count75 \space % Mentransfer data TeX ke "Dunia Lua"
   tex.print("x= "..x)
   local y = (2*x-65)/5
   tex.print(" dan y = "..y)
}
```

Ini menghasilkan kode Lua

```
 local x=1564 tex.print("x= "..x) local y = (2*x-65)/5 tex.print(" dan y = "..y)
```

**Catatan**: Kami menambahkan `<space>\space` setelah `\number\count75` untuk memastikan karakter spasi dipertahankan antara `1564` dan `tex.print`—itu sebenarnya tidak mutlak diperlukan di sini karena Lua masih akan mengurai kode dengan benar jika kita menghilangkannya. Karakter spasi yang segera mengikuti `\count75` diserap selama proses yang digunakan mesin TeX untuk mencari nilai numerik—di sini, nilai yang diberikan kepada `\count`. Karakter spasi setelah `75` digunakan untuk mengakhiri pencarian LuaTeX terhadap deret digit `75` dan diserap dari masukan. Makro `\space` mengembang untuk menyediakan karakter spasi yang diperlukan untuk memisahkan teks `1564` dan `tex.print`.

Menggunakan kode di atas LuaTeX akan menata huruf

`x= 1564 dan y = 612.6`

Di sini, mekanisme “penyaluran data” dicapai dengan `\number`: perintah yang dapat diekspansi yang, dalam kasus ini, menginstruksikan TeX untuk mengambil nilai yang disimpan di `\count` register `75` dan dari nilai itu (`1546`) menghasilkan serangkaian token karakter, satu token karakter untuk setiap digit, sehingga menghasilkan urutan token untuk digit `1`, `5`, `6` dan `4`. Keempat token karakter itu dimasukkan ke dalam daftar token utama yang sedang dibangun oleh `\directlua` dan kemudian dikonversi kembali ke representasi tekstualnya ketika daftar token dikonversi menjadi teks. Jelas ini adalah jalan yang sangat memutar dari `\count75` nilai register yang tersimpan di dalam LuaTeX, ke digit-digit yang ditujukan untuk kode Lua, tetapi pada akhirnya, itu berhasil.

**TIP:** Jika Anda ingin memeriksa hasil aktivitas ekspansi LuaTeX, Anda dapat menulis kode seperti ini:

```
\directlua{
   local foo=[[local x=\number\count75
   tex.print("x= "..x)
   local y = (2*x-65)/5
   tex.print(" dan y = "..y)]]
   print(foo)
}
```

Dalam contoh ini kita menggunakan metode tanda kurung panjang untuk membuat variabel string `foo` yang tujuannya adalah menampung string kode Lua yang dihasilkan dari ekspansi semua yang ada di antara `[[` dan `]]`. String itu dicetak ke konsol melalui panggilan fungsi Lua `print(foo)`.

Di Overleaf Anda dapat melihat hasil serupa dengan menulis isi dari `foo` ke `.log` berkas menggunakan fungsi LuaTeX Lua `texio.write()`:

```
\directlua{
   local foo=[[local x=\number\count75
   tex.print("x= "..x)
   local y = (2*x-65)/5
   tex.print(" dan y = "..y)]]
   texio.write(foo)
}
```

## Token dalam daftar token \directlua: token yang tidak dapat diekspansi dan token yang tidak diekspansi

Kita telah mencatat bahwa `\directlua{⟨code⟩}` melakukan *ekspansi penuh* dari `⟨code⟩`: ia menghapus dan mengekspansi semua perintah yang dapat diekspansi sampai hanya token yang tidak dapat diekspansi yang tersisa. Urutan token yang dibuat oleh `\directlua`pemrosesan oleh `scan_toks()` (dalam fungsi

) disusun menjadi sebuah daftar token yang token-token individualnya akan dikonversi kembali ke teks untuk diteruskan ke Lua. Namun, kita belum membahas bagian akhir dari cerita ini karena kita perlu mempertimbangkan dua “kelas” token perintah yang dapat masuk ke daftar token yang dibangun di dalam `\directlua`: kita akan menyebutnya sebagai *token perintah ringkas* dan *tidak diekspansi* token:

* **token perintah ringkas**: Jenis token perintah ini muncul dari urutan kontrol yang didefinisikan menggunakan salah satu primitif TeX `\chardef`, `\mathchardef`, `\countdef`, `\dimendef`, `\skipdef`, `\muskipdef` dan `\toksdef`. Perintah primitif ini digunakan untuk mendefinisikan urutan kontrol yang mewakili nilai numerik—urutan kontrol yang dihasilkan adalah *berisi nilai data aktual yang disimpan dalam* tidak dapat diekspansi.
* **token yang tidak diekspansi**: Jenis token ini muncul dari perintah yang biasanya akan diekspansi tetapi `\directlua` has either:
* diperintahkan secara eksplisit *berisi nilai data aktual yang disimpan dalam* untuk mengekspansinya; misalnya, penekanan ekspansi oleh perintah `\noexpand` atau `\unexpanded`—kami akan segera menjelaskan bagaimana ini dilakukan;
* token yang disisipkan dengan memproses urutan `\the\toks` (lebih lanjut tentang ini di bawah).

### Dua “kelompok” token dalam daftar token \directlua

Berdasarkan pembahasan kita, kita dapat mengatakan bahwa token yang terkandung dalam daftar token yang sedang dibangun selama tahap pertama pra-pemrosesan `\directlua`(dalam fungsi `scan_toks()` ) terbagi ke dalam dua kelompok:

1. *secara inheren tidak dapat diekspansi* token

* token apa pun yang mewakili *karakter*;
* token apa pun yang mewakili sebuah *primitif* *perintah*;
* token apa pun yang mewakili sebuah *perintah ringkas* (ini tidak dapat diekspansi, lihat di bawah).

3. *tidak diekspansi* token:

* token apa pun yang mewakili perintah yang dapat diekspansi yang ekspansinya *dicegah* (atau dihindari) selama `\directlua`pra-pemrosesan.

#### Token perintah ringkas: membuat perintah yang tidak dapat diekspansi

Seperti dicatat, mesin TeX menyediakan seperangkat primitif (perintah bawaan) yang dapat digunakan untuk membangun *tidak dapat diekspansi* urutan kontrol (diindikasikan di sini oleh `⟨command⟩`). Primitif ini berbentuk:

* `\chardef ⟨command⟩ = ⟨numeric value⟩`
* `\mathchardef ⟨command⟩ = ⟨numeric value⟩`
* `\countdef ⟨command⟩ = ⟨numeric value⟩`
* `\dimendef ⟨command⟩ = ⟨numeric value⟩`
* `\skipdef ⟨command⟩ = ⟨numeric value⟩`
* `\muskipdef ⟨command⟩ = ⟨numeric value⟩`
* `\toksdef ⟨command⟩ = ⟨numeric value⟩`

di mana `⟨numeric value⟩` adalah suatu nilai integer yang sesuai untuk masing-masing perintah.

Di sini, kita akan secara singkat meninjau penggunaan `\chardef` untuk mendemonstrasikan fitur kunci dari primitif ini—menghasilkan sebuah `⟨command⟩` yang tidak dapat diekspansi. Anda dapat menggunakan ``\chardef\mydollar=`\$`` untuk membuat urutan kontrol `\mydollar` dan menggunakannya untuk menata huruf sebuah `$`:

`Saya membayar \mydollar30.`

Ini akan menata huruf `Saya membayar $30.` Urutan kontrol `\mydollar` yang dibuat oleh `\chardef` tidak dapat diekspansi, sebagaimana kita lihat dari contoh berikut:

```
\chardef\mydollar=`\$
\directlua{
   local x =[[Saya membayar \mydollar30.]]
   texio.write(x)
}
```

Yang menghasilkan teks berikut di dalam `.log` yang dapat diedit

`Saya membayar \mydollar 30.`

Ini menunjukkan `\mydollar` diusulkan *berisi nilai data aktual yang disimpan dalam* diekspansi selama pra-pemrosesan `\directlua`’. Spasi yang muncul setelah `\mydollar` ditambahkan ketika token perintah dikonversi ke representasinya sebagai teks.

Ketika Anda menggunakan `\chardef` untuk membuat sebuah urutan kontrol, klasifikasi internal TeX terhadap urutan kontrol itu (perintah) membuatnya menjadi *tidak dapat diekspansi* yang merupakan perilaku yang sangat berbeda dibandingkan urutan kontrol yang didefinisikan oleh salah satu perintah definisi makro: \def, \edef, \gdef atau \xdef. Seperti disebutkan di atas, selama proses membangun daftar tokennya `\directlua` memeriksa setiap token perintah yang masuk untuk mengecek keterekspansian. Jika token perintah tidak dapat diekspansi, token itu langsung diteruskan ke daftar token dan representasi tekstualnya kemudian akan muncul kembali dalam string kode Lua yang dihasilkan dari konversi token-token dalam daftar token kembali ke bentuk tekstualnya.

**Catatan singkat tentang plain TeX vs. LaTeX**

Secara historis, plain TeX karya Knuth mendefinisikan simbol kontrol yang umum digunakan `\%`, `\&`, `\#` dan `\$` menggunakan `\chardef`—tidak menggunakan salah satu perintah standar untuk definisi makro `\def`, `\edef`, `\gdef` atau `\xdef`. Misalnya:

```
   \chardef\#=`\#
   \chardef\$=`\$
   \chardef\%=`\%
   \chardef\&=`\&
```

Sintaks `` `\ `` yang aneh adalah metode TeX untuk mendapatkan nilai kode karakter numerik. Dalam rezim plain TeX lama, simbol kontrol ini tidak dapat diekspansi (karena `\chardef`) tetapi LaTeX (atau paket) dapat mendefinisikannya ulang sebagai *makro* untuk menyediakan fungsionalitas yang ditingkatkan—itu akan membuatnya dapat diekspansi, jadi Anda mungkin perlu menyadari hal ini.

**Bagaimana ini memengaruhi \directlua?**

Mari kita bandingkan hasil dari kode berikut ketika dijalankan di bawah plain TeX dan LaTeX. Untuk kesederhanaan kita akan menulis hasilnya ke `.log` berkas menggunakan fungsi API Lua LuaTeX `texio.write()`.

```
\directlua{
   local x=[[\$150 for the "\#1" product---20\%! more than its competitor, Widget \& Co.]]
   texio.write(x)
}
```

Menjalankan kode ini menggunakan **plain TeX** menghasilkan keluaran berikut di dalam `.log` berkas, menunjukkan hasil dari setiap ekspansi:

```
\$150 for the "\#1" product---20\%! more than its competitor, Widget \& Co.
```

Jelas, di bawah plain TeX tidak ada satu pun simbol kontrol`\$`, `\#`, `\%` atau `\&` yang diekspansi—karena semuanya dibuat menggunakan `\chardef`.

Menjalankan kode itu menggunakan dokumen **LaTeX** LaTeX:

```
\documentclass{article}
\begin{document}
   \directlua{local x=[[\$150 for the "\#1" product---20\%! more than its competitor, Widget \& Co.]] texio.write(x)}
\end{document}
```

menghasilkan keluaran berikut di dalam `.log` yang dapat diedit

```
\protect \TU\textdollar 150 for the "\#1" product---20\%! more than its competitor, Widget \& Co.
```

Jelas, menjalankan LaTeX menghasilkan hasil yang berbeda dari plain TeX karena di bawah LaTeX perintah `\$` telah diekspansi, yang menandakan bahwa itu adalah sebuah makro.

**Catatan:** Dalam plain TeX dan LaTeX `\directlua` tidak sepenuhnya memproses simbol kontrol apa pun `\%`, `\&`, `\#` dan `\$` untuk menghasilkan karakter yang bersesuaian. Selama proses ekspansi yang dilakukan oleh `\directlua` token yang mewakili simbol kontrol ini—atau, untuk LaTeX, ekspansinya—langsung diteruskan ke daftar token utama yang sedang dibangun.

**Catatan:** Simbol kontrol dibentuk dari satu karakter yang bukan berkode kategori 11, seperti `\#`. Ketika token yang mewakili simbol kontrol dikonversi kembali ke representasi tekstualnya, mesin TeX tidak menyisipkan karakter spasi setelah teks itu. Perlakuan khusus terhadap simbol kontrol ini adalah aturan bawaan tentang cara kerja mesin TeX.

### Token yang tidak diekspansi: menekan ekspansi

`\directlua`pra-pemrosesan ’s adalah salah satu contoh ketika mesin TeX melakukan ekspansi, tetapi Anda mungkin ingin *mencegah* ekspansi diterapkan pada satu atau beberapa token yang jika tidak akan diperluas. Sebagai contoh lain, LuaTeX (dan semua mesin TeX) melakukan proses ekspansi, mirip dengan proses `\directlua`, ketika mereka memproses `\write` perintah:

`\write file-number {⟨material⟩}`

\write memerintahkan mesin TeX untuk mengeluarkan `⟨material⟩`—sering kali berisi perintah TeX/LaTeX—ke sebuah berkas teks (`nomor berkas`); setiap perintah yang dapat diperluas di dalam `⟨material⟩` akan, kecuali dicegah, diperluas sebelum `⟨material⟩` benar-benar dituliskan ke berkas tersebut.

Seperti yang mungkin Anda duga, mesin TeX menyediakan perintah untuk menekan atau mengendalikan ekspansi:

* `\noexpand⟨token⟩`: mencegah ekspansi dari satu `⟨token⟩`;
* `\unexpanded{⟨material⟩}`: mencegah ekspansi semua perintah (token) yang dapat diperluas di dalam `⟨material⟩`. `\noexpand`;
* `\protected`: sebuah prefiks yang ditambahkan pada definisi makro yang mencegah ekspansi makro tersebut dalam keadaan tertentu (misalnya selama `\directlua`, `\write` atau `\edef`).

Meskipun namanya menyiratkan sebaliknya, keduanya `\noexpand` dan `\unexpanded` sudah *perintah yang dapat diekspansi* dan memberikan contoh yang baik tentang melihat proses ekspansi mesin TeX sebagai melakukan “operasi token”: operasinya di sini adalah mencegah ekspansi satu atau beberapa token (perintah) berikutnya. Karena `\noexpand` dan `\unexpanded` keduanya adalah perintah yang dapat diperluas, keduanya dihapus dan diproses (dieksekusi) selama `\directlua`pra-pemrosesan ’s saat membangun daftar token dari `⟨code⟩`.

#### \noexpand ⟨token⟩

`\noexpand ⟨token⟩` mencegah ekspansi dari satu `⟨token⟩`. `\noexpand` di dalam `\directlua` akan diperluas (dihapus dari masukan) dan digantikan oleh hasil dari “perilaku ekspansinya”. Hasil dari ekspansi `\noexpand` adalah untuk membuat sebuah token penanda khusus (tersembunyi) `⟨marker token⟩` yang ditempatkan di depan token asli `⟨token⟩` yang ekspansinya harus ditekan: token itu `⟨marker token⟩` berfungsi sebagai penanda yang mengatakan “jangan perluas token berikutnya”. Karena `\directlua` melakukan ekspansi penuh, ia akan memproses ulang token apa pun yang dihasilkan dari “perilaku ekspansi” sebuah perintah yang dapat diperluas. Akibatnya, ketika ekspansi dari `\noexpand ⟨token⟩` selesai, LuaTeX kembali membaca hasilnya dan melihat urutan dua token `⟨marker token⟩⟨token⟩` yang menyebabkan token asli `⟨token⟩` lolos, tanpa diperluas, ke dalam daftar token yang sedang dibangun oleh `\directlua`.

**Contoh**

Jika kita menulis

```
\directlua{
   local x= "\TeX"
}
```

situs web `\TeX` makro diperluas menjadi token-token penyusunnya yang, dalam plain TeX, akan menghasilkan teks berikut diteruskan ke Lua (catatan: Lua tidak dapat memproses kode ini, ini hanya contoh untuk mendemonstrasikan prosesnya):

`local x = "T\kern -.1667em\lower .5ex\hbox {E}\kern -.125emX"`

Jika kita *menekan* ekspansi dari `\TeX` makro menggunakan `\noexpand`

`\directlua{local x= "\noexpand\TeX"}`

kode Lua berikut dihasilkan (lagi, Lua tidak dapat menjalankan kode ini; ini hanya contoh untuk mendemonstrasikan `\noexpand`):

`local x= "\TeX "`

Karena `\noexpand`, `\directlua` tidak akan diperluas `\TeX` tetapi hanya membiarkan nilai token yang mewakili `\TeX` perintah lolos, tanpa berubah, ke dalam daftar token yang dibangun selama tahap pertama dari `\directlua`pra-pemrosesan.

**Catatan:** Karakter spasi yang muncul setelah `\TeX` diperkenalkan oleh konversi berikutnya oleh LuaTeX atas `\TeX` nilai token bilangan bulat kembali ke representasi tekstualnya (di dalam `tokenlist_to_cstring()` fungsi).

#### \unexpanded{⟨material⟩}

`\unexpanded` adalah perintah yang dapat diperluas yang menekan ekspansi semua token yang dibentuk dari `⟨material⟩`. *dihapus* dari masukan dan *digantikan* oleh hasil dari “perilaku ekspansinya”; jadi apa sebenarnya artinya bagi `\unexpanded`? Biasanya, selama *ekspansi penuh*, setelah proses ekspansi untuk suatu perintah selesai, mesin TeX akan melanjutkan membaca/memproses token apa pun yang muncul dari “perilaku ekspansi” perintah tersebut—ia perlu memperluas lebih lanjut token-token yang dihasilkan. Namun, `\unexpanded` *melewati* setiap ekspansi lebih lanjut: berikut cara melakukannya.

Di dalam mesin TeX,  `\unexpanded` perintah terlebih dahulu mengonversi karakter dan perintah dalam `⟨material⟩` menjadi daftar token sementara yang terdiri dari *tidak diekspansi* token. Setelah semua token dibuat dan disimpan dalam daftar token sementara itu,  `\unexpanded` perintah menyebabkan `\directlua` ke *melewati* kembali untuk membaca dan memprosesnya—meskipun \directlua melakukan ekspansi penuh. Sebaliknya, token-token itu *tidak diekspansi* lolos begitu saja dan menjadi bagian dari daftar token utama yang dibangun oleh `\directlua` (dalam `scan_toks()` fungsi). `⟨material⟩` dikonversi menjadi token dan proses ekspansi dilewati untuk set token tersebut. Operasi `\unexpanded{⟨material⟩}` mirip dengan penggunaan `\the\toks`, yang akan kita bahas di bawah.

**Contoh**

`\unexpanded` menghasilkan hasil dengan cara yang mirip dengan `\noexpand` kecuali bahwa ia dapat mencegah ekspansi beberapa token; berikut contohnya:

```
\directlua{
   local x = "\unexpanded{\foo\bar\foobar}. But Lua can't process this code!"
}
```

yang menghasilkan teks berikut sebagai kode untuk Lua:

`local x = "\foo \bar \foobar . But Lua can't process this code!"`

**Catatan**: Ada karakter spasi setelah setiap nama perintah. Ini sekali lagi merupakan konsekuensi dari konversi berikutnya oleh LuaTeX atas token-token yang tidak diperluas `\foo`, `\bar` dan `\foobar` kembali menjadi teks di dalam `tokenlist_to_cstring()` fungsi.

#### definisi makro \protected

Fitur `\protected` perintah adalah prefiks yang diterapkan pada definisi makro untuk mencegah makro tersebut diperluas saat TeX membangun daftar token yang diperluas, seperti daftar token yang dibangun oleh `\directlua`pra-pemrosesan.

**Contoh**

Misalkan Anda mendefinisikan makro berikut dengan dan tanpa menggunakan prefiks `\protected` :

```
\def\macroA{"This unprotected macro contains a string"}
\protected\def\macroB{"This protected macro also contains a string"}
```

Jika Anda menggunakan operator penggabungan string Lua (`..`) untuk menulis

```
\directlua{
   local x=\macroA..\macroB
}
```

`\directlua`pra-pemrosesan ’s akan menghasilkan kode berikut untuk diteruskan ke Lua:

`local x="This unprotected macro contains a string"..\macroB`

`\macroA` tidak didefinisikan menggunakan `\protected` jadi ia diperluas, menghasilkan bagian pertama string yang akan digabungkan, tetapi `\macroB` didefinisikan menggunakan `\protected` jadi belum diperluas.

Selama pra-pemrosesan,  `scan_toks()` fungsi LuaTeX membuat token untuk `\macroA`, mengenalinya sebagai perintah biasa yang dapat diperluas dan memperluasnya: ekspansi itu menghasilkan serangkaian token karakter, satu token karakter untuk setiap karakter dalam `"This unprotected macro contains a string"`. Setiap token karakter diteruskan dan ditambahkan ke daftar token yang sedang dibangun.

Saat `scan_toks()` membuat token untuk `\macroB` ia menyadari bahwa perintah tersebut didefinisikan sebagai `\protected` dan tidak memperluasnya: token yang mewakili `\macroB` lolos begitu saja, tanpa disentuh (tidak diperluas), ke dalam daftar token yang sedang dibangun. Setelah daftar token itu dibangun, tahap berikutnya dari pra-pemrosesan, di dalam `tokenlist_to_cstring()` fungsi, adalah mengonversi semua token dalam daftar token kembali ke representasi tekstualnya. Token yang tidak diperluas yang mewakili `\macroB` terdeteksi dan dikonversi ke representasi teksnya, sehingga menghasilkan teks `\macroB` muncul dalam kode yang ditujukan untuk Lua. Perhatikan bahwa Lua sebenarnya tidak dapat menggabungkan `"This unprotected macro contains a string"..\macroB` untuk menghasilkan string akhir karena `\macroB` tidak memiliki arti dalam sintaks Lua, sehingga menghasilkan kesalahan `simbol tak terduga di dekat '\'`.

**Trivia**: Paket ini `\protected` perintah diperkenalkan oleh $$\varepsilon\text{-}\mathrm{\TeX}$$, ekstensi besar pertama dari perangkat lunak TeX asli karya Knuth, dan didukung oleh semua mesin TeX yang garis keturunan kodenya mencakup $$\varepsilon\text{-}\mathrm{\TeX}$$.

### Token yang tidak diperluas: Menggunakan \the\toks dalam \directlua

Hidup dalam pemrograman tidak akan sama tanpa “kasus-kasus khusus” untuk ditangani dan penggunaan `\the` bersama dengan `\toks` dalam sebuah `\directlua` adalah salah satu kasus khusus semacam itu.

#### Latar belakang singkat tentang \toks

Primitif TeX `\toks` memerintahkan mesin TeX untuk menyimpan sejumlah token untuk digunakan nanti: alih-alih diteruskan untuk pemrosesan lebih lanjut, token-token tersebut disisihkan dan disimpan di lokasi memori yang ditentukan menggunakan sebuah *register token*. Misalnya, kita dapat memberitahu mesin TeX untuk membuat sejumlah token dan menyimpannya di lokasi register token `100` menggunakan

`\toks100={Hi, \TeX! \hskip 5bp}`

Di sini, TeX menggunakan register token `100` untuk mengakses lokasi yang diketahui di dalam memorinya: area penyimpanan yang ditujukan untuk menampung daftar token.

Token yang mewakili semua yang berada di antara `{` dan `}` dibuat, *tetapi tidak diperluas*, dan dirangkai dalam sebuah daftar token—mirip dengan daftar token yang kita bahas sebelumnya dalam artikel ini. Untuk menggunakan kembali token-token tersebut kita akan menulis `\the\toks100` di mana `\the` (sebuah perintah yang dapat diperluas) memerintahkan TeX untuk mengambil token yang tersimpan dan menyisipkannya di lokasi tempat Anda menulis `\the\toks100`. `\the\toks` menyebabkan TeX menyisipkan beberapa token di lokasi tersebut.

Fitur `\toks` perintah *tidak memperluas* satu pun dari token yang diminta untuk dibuat dan disimpan: ia hanya mengonversi karakter dan perintah di antara `{` dan `}` menjadi token dan menyimpannya.

#### Kembali ke \directlua

Dalam pembahasan tentang ekspansi kita mencatat `\directlua{⟨code⟩}` melakukan *ekspansi penuh* sebesar `⟨code⟩`: menghapus semua perintah yang dapat diperluas dan menggantinya dengan hasil perilaku ekspansinya—terus *memperluas lebih lanjut* token apa pun yang muncul dari ekspansi awal sebuah perintah yang dapat diperluas.

`\the` adalah perintah yang dapat diperluas sehingga `\directlua` akan memperluasnya; namun, ketika `\the` digunakan bersama dengan `\toks` di dalam `\directlua`, seperti pada `\the\toks⟨token register⟩`, token yang disisipkan *tidak diperluas lebih lanjut*. Ekspansi dari `\the\toks⟨token register⟩` menyuntikkan rangkaian *tidak diekspansi* token, yang disimpan dalam `⟨token register⟩`, langsung ke dalam daftar token yang sedang dibangun oleh `\directlua`: perilaku ini melewati proses biasa ekspansi penuh. Pada dasarnya, token-token itu lolos begitu saja, *tidak diekspansi*, untuk menjadi bagian dari daftar token utama yang sedang dibangun oleh `\directlua`—proses lolosnya token yang tidak diperluas ini mirip dalam cara kerja dengan `\unexpanded`, seperti dibahas sebelumnya.

**Contoh**

Misalkan kita mendefinisikan makro `\mymacro` sebagai `\def\mymacro{\TeX}`. Makro ini hanya berisi satu token untuk `\TeX` perintah (yang merupakan makro): jadi kita memiliki perintah yang dapat diperluas `\mymacro` yang berisi makro lain `\TeX`, yang juga dapat diperluas.

Kode berikut akan membuat Lua mencoba membuat variabel string `x`:

```
\def\mymacro{\TeX}
\directlua{
   local x="\mymacro"
}
```

Di dalam \\`directlua`, token untuk `\mymacro` diperluas tetapi itu menghasilkan token lain yang dapat diperluas, `\TeX`yang kemudian diperluas lagi. Dalam plain TeX, ekspansi tersebut menghasilkan teks berikut yang diteruskan ke Lua:

`local x = "T\kern -.1667em\lower .5ex\hbox {E}\kern -.125emX"`

Kode ini mencoba mendefinisikan string yang berisi teks yang mewakili versi yang diperluas dari `\TeX` makro. Jika Anda mencoba menjalankan contoh ini, Lua akan mencoba menyusun string itu tetapi akan gagal, menghasilkan kesalahan:

`urutan escape tidak valid di dekat ' "T\k'.`

Nanti dalam artikel ini kita akan membahas arti “urutan escape tidak valid”.

Sekarang mari kita bandingkan penggunaan `\mymacro` dengan menempatkan `\TeX` token di dalam daftar token yang dihasilkan oleh sebuah `\toks` perintah:

```
\toks100={\TeX}
\directlua{
   local x="\the\toks100"
}
```

milik LuaTeX `\directlua` pemrosesan akan menghasilkan string teks ini untuk Lua:

`local x = "\TeX "`

Karakter spasi setelah `\TeX` dihasilkan oleh proses konversi token-perintah-ke-string LuaTeX.

**Tetapi perhatikan**: Paket ini `\TeX` makro telah *berisi nilai data aktual yang disimpan dalam* diperluas menjadi token-token penyusunnya. `\the\toks100` menyebabkan token yang tersimpan di register 100 disisipkan tetapi itu saja: token-token tersebut *berisi nilai data aktual yang disimpan dalam* tidak diperluas lebih lanjut dan menjadi bagian dari daftar token utama yang sedang dibangun oleh `\directlua` (di dalam fungsi `scan_toks()`). Menempatkan token ke dalam daftar token yang dibuat oleh `\toks` adalah cara lain untuk mencegah token diperluas.

Jika kita menjalankan contoh ini, ia juga menghasilkan kesalahan:

`urutan escape tidak valid di dekat ' "\T'.`

Kita akan membahas urutan escape Lua nanti dalam artikel ini.

## Perintah/teknik lain yang digunakan dalam ekspansi

Pada bagian ini kita melihat beberapa perintah/metode TeX tambahan yang dapat berguna dalam situasi ketika ekspansi diterapkan (seperti di dalam `\directlua`).

### \string ⟨token⟩

`\string` adalah perintah yang dapat diperluas yang mengonversi ⟨token⟩ menjadi serangkaian token karakter, masing-masing dengan kode kategori 12.

Misalnya, `\string\TeX` akan menghasilkan serangkaian 4 token karakter `\`, `T`, `e` dan `X` di mana setiap karakter diberi kode kategori 12 (termasuk karakter awal `\` karakter).

Jika kita menulis

```
\directlua{
   local x="I will use \string\newcommand"
   print(x)
}
```

situs web `\string` perintah akan diperluas, menghasilkan serangkaian token karakter dengan kode kategori 12. Setelah `\string` diperluas, token karakter yang dihasilkan (mewakili setiap karakter dalam `\newcommand`) akan dimasukkan ke dalam daftar token utama yang sedang dibangun oleh `\directlua`. Setelah `\directlua` selesai membangun daftar token utamanya, token-token penyusunnya dikonversi kembali ke representasi tekstualnya sehingga menghasilkan kode berikut untuk diteruskan ke interpreter Lua:

`local x="I will use \newcommand" print(x)`

Saat kode ini diteruskan ke Lua, `print(x)` akan menampilkan string `x` ke layar (konsol). Namun, kita sedikit licik dan sengaja menggunakan contoh perintah yang dimulai dengan `\n`. Jika Anda dapat menjalankan contoh ini pada instalasi TeX lokal, Anda akan melihat bahwa Lua mencetak teks berikut ke layar:

```
   Saya akan menggunakan
   ewcommand
```

Untuk menjalankan kode ini di Overleaf, Anda dapat memerintahkan LuaTeX untuk menulis langsung ke `.log` berkas menggunakan fungsi API Lua LuaTeX `texio.write(*string*)`:

```
\directlua{
   local x="I will use \string\newcommand"
   texio.write(x)
}
```

Jika Anda memeriksa `.log` berkas hasilnya, Anda akan melihat bahwa berkas itu juga berisi

```
   Saya akan menggunakan
   ewcommand
```

Keluaran yang tak terduga ini disebabkan oleh Lua yang menafsirkan `\n` di awal `**\n**ewcommand` sebagai urutan escape untuk karakter linefeed (kode karakter 10): ia mengasumsikan bahwa Anda ingin memulai baris teks baru yang dimulai dengan `ewcommand`. Kita membahas urutan escape Lua nanti dalam artikel ini.

### \detokenize{⟨material⟩}

`\detokenize` dalam efeknya, adalah versi multi-token dari `\string` dan itu juga merupakan perintah yang dapat diperluas yang mengonversi semua yang ada di `⟨material⟩` menjadi serangkaian token karakter dengan kode kategori 12—*kecuali* karakter spasi (nilai ASCII/Unicode 32) yang mendapat kode kategori 10. `\detokenize` juga menyisipkan karakter spasi di belakang setelah nama perintah yang *kata kendali* (misalnya, `\foo`) tetapi tidak ada karakter spasi yang disisipkan setelah *simbol kendali* (misalnya, `\#`, `\%` dll).

### Contoh

Bahkan jika makro-makro `\foohoo`, `\foo`, `\bar` dan `\foobar` tidak didefinisikan, jika Anda menulis ini:

```
\directlua{
   local x = "\string\foohoo\detokenize{\foo\bar\foobar}"
}
```

hal ini akan menghasilkan teks berikut sebagai kode untuk diteruskan ke interpreter Lua

`local x = "\foohoo\foo \bar \foobar "`

Jika Anda tidak menggunakan `\string` dan `\detokenize` dan menulis:

`\directlua{local x = "\foohoo\foo\bar\foobar"}`

`\directlua` akan memproses `\foohoo`, mengenalinya sebagai perintah dan mencoba memperluasnya; tetapi karena `\foohoo` tidak didefinisikan, hal ini akan menghasilkan kesalahan:

```
   ! Rangkaian kontrol tidak terdefinisi.
   l.1 \directlua{local x = "\foohoo
                      \foo\bar\foobar"}
         ?
```

Karena `\string` dan `\detokenize` mengonversi argumen mereka menjadi serangkaian token karakter, `\directlua`proses ekspansi ’s memang mendapat kesempatan untuk mendeteksi token perintah yang dapat diperluas `\foohoo`, `\foo`, `\bar`, atau `\foobar`: token-token tersebut diubah menjadi rangkaian token karakter jauh sebelum mereka dapat memicu ekspansi.

Seperti telah dicatat sebelumnya, ekspansi sebuah perintah melibatkan penghapusannya dari masukan dan menggantinya dengan hasil dari “perilaku ekspansinya”. Hasil ekspansi (biasanya token) kemudian dibaca oleh mesin TeX. Di sini, “perilaku ekspansi” untuk `\string` dan `\detokenize` adalah menyerap token karakter dan perintah dari masukan dan mengonversinya menjadi rangkaian token karakter, yang awalnya disimpan dalam daftar token sementara, yang `\directlua` kemudian dibaca. Token-token karakter tersebut menjadi bagian dari daftar token utama yang sedang dibangun oleh `\directlua`.

Grafik berikut menggambarkan bagaimana `\string` mengonversi `\foohoo` perintah menjadi serangkaian token karakter, menghasilkan daftar token sementara yang kemudian dibaca oleh `\directlua` untuk memasukkan token-token karakter tersebut ke dalam daftar token utama yang sedang dibangun.

![](/files/2c613bca4d41e64bf11b7d7a41d25563c8a8c088)

Jika `\string` atau `\detokenize` menemui karakter dalam argumen mereka, misalnya, `\string a` atau `\detokenize{abc}` karakter-karakter tersebut (di sini, dengan kode kategori 11) menghasilkan token karakter tetapi dengan kode kategori 12.

Catatan:

Jika kita kembali ke contoh di atas:

`\directlua{local x = "\string\foohoo\detokenize{\foo\bar\foobar}"}`

yang menghasilkan teks berikut sebagai kode untuk diteruskan ke interpreter Lua

`local x = "\foohoo\foo \bar \foobar "`

kita dapat mengamati hal berikut:

* `\detokenize` telah menyisipkan karakter spasi setelah setiap nama makro tetapi `\string` tidak.
* `\string` bekerja pada satu token.
* Dalam string `"\foohoo\foo \bar \foobar "` yang digunakan untuk mendefinisikan `x` kita akan sekali lagi menemui mekanisme karakter escape Lua (dibahas di bawah):

  * `\bar` dimulai dengan `\b` yang merupakan urutan escape Lua yang digunakan untuk mewakili [karakter backspace](https://en.wikipedia.org/wiki/Backspace) (kode karakter 8);
  * perintah `\foohoo`, `\foo` dan `\foobar` semua dimulai dengan `\f`, urutan escape Lua yang digunakan untuk mewakili [karakter formfeed](https://en.wikipedia.org/wiki/Page_break#Form_feed) (kode karakter 12).

  Karena rangkaian karakter `\b` dan `\f` digunakan di dalam string yang dibuat menggunakan tanda kutip ganda `"..."` mereka akan menghasilkan hasil yang tidak diinginkan kecuali diambil langkah untuk mencegahnya dengan menggunakan yang disebut Lua *long-brackets* string method: topik yang kini dapat kita bahas bersama dengan escape sequence Lua.

## Apa itu “Lua escape sequences”?

Bahasa pemrograman menyisihkan karakter tertentu untuk “penggunaan khusus” sebagai bagian dari sintaks bahasa: pada praktiknya, karakter-karakter itu ditetapkan memiliki suatu bentuk makna khusus. Namun, ada kalanya Anda perlu untuk sementara “mematikan” makna khusus suatu karakter jika, misalnya, Anda ingin karakter itu disematkan sebagai bagian dari string yang lebih panjang di mana perilaku standarnya akan menimbulkan kesalahan sintaks. Pada dasarnya, karakter itu perlu diproses *tanpa* tanpa memicu interpretasi standarnya—agar lolos tanpa disadari. Untuk melakukan ini, para pemrogram menggunakan teknik yang disebut *escaping* di mana sebuah “karakter khusus” direpresentasikan oleh yang disebut *escape sequence*.

Contoh standar (juga didukung oleh Lua) adalah menggunakan tanda kutip ganda di dalam string, di mana Anda meng-escape tanda kutip ganda di dalamnya menggunakan escape sequence `\"`:

`"When asked about LuaTeX they replied: \"It is an awesome TeX engine!\" I agreed."`

Bahasa Lua menyediakan sejumlah mekanisme untuk bekerja dengan escape sequence:

* urutan standar termasuk `\n` (baris baru), `\r` (carriage return), `\\` (backslash), `\"` (tanda kutip ganda), `\t` (tab horizontal), `\v` (tab vertikal) dan `\'` (tanda kutip tunggal);
* `\xXX`, di mana `XX` adalah urutan yang terdiri tepat dari dua digit heksadesimal;
* `\ddd`, di mana `ddd` adalah urutan hingga tiga digit desimal;
* pada saat artikel ini ditulis (Agustus 2019) versi terbaru LuaTeX, meskipun belum tersedia di Overleaf, menggunakan Lua versi 5.3 yang memperkenalkan dukungan untuk escape sequence UTF-8: `\u{XXX}`. Mekanisme escape ini ditujukan untuk karakter Unicode ber-encoding UTF-8 di mana `XXX` adalah urutan satu atau lebih digit heksadesimal yang merepresentasikan titik kode karakter. Perhatikan bahwa kurung pembatas `{ }` bersifat wajib.

### Mengendalikan escape sequence

Secara tradisional, string didefinisikan menggunakan tanda kutip ganda seperti pada `"this is a string"`; di dalam string seperti itu Anda dapat menggunakan escape sequence: `"this is a string.\nI'll now start on a new line."`. Namun, Lua memiliki mekanisme kedua dan *sangat* yang praktis untuk mendefinisikan string: yang disebut *long brackets* mekanisme di mana Anda mendefinisikan string dengan membungkus teks di dalam `[[` dan `]]`:

`[[I am a long brackets string]]`

Di dalam string yang dibuat menggunakan metode long-brackets, mekanisme escape karakter milik Lua *dimatikan*: escape sequence diperlakukan sebagai karakter biasa. Misalnya, dalam string

`[[I am a long brackets\n string]]`

situs web `\n` escape sequence tidak diperlakukan sebagai karakter carriage return tunggal (kode ASCII 13) melainkan sebagai dua karakter biasa: `\` diikuti oleh `n`.

### Mengapa string long bracket begitu berguna?

Seperti akan kita bahas nanti, LuaTeX menyediakan seperangkat fungsi Lua bawaan yang terspesialisasi yang dapat Anda gunakan dengan `\directlua` untuk mengendalikan perilaku penataan huruf LuaTeX. Di antara banyak fungsi tersebut ada yang disebut `tex.print(*string*)` yang memungkinkan Anda meneruskan `*string*` materi dari kode Lua kembali ke LuaTeX untuk penataan huruf. Contoh yang sangat sederhana adalah:

`\directlua{tex.print("Hello, World!")}`

yang akan menyebabkan LuaTeX menata `Hello, World!`

Fitur `*string*` digunakan dalam `tex.print(*string*)` juga dapat mencakup teks yang merepresentasikan perintah TeX dan LaTeX agar diproses oleh LuaTeX. Namun, perintah TeX/LaTeX dimulai dengan sebuah `\` karakter yang bermasalah dengan string yang dibuat menggunakan tanda kutip ganda karena Lua akan mencoba mengurai string, mendeteksi `\` awal dan menafsirkannya sebagai awal sebuah escape sequence. Ketika Lua mencoba memproses escape sequence tersebut, biasanya akan gagal karena `\` awal yang digabungkan dengan karakter pertama dalam banyak nama perintah TeX/LaTeX tidak membentuk escape sequence valid yang dikenali oleh Lua. Misalnya saat memproses string seperti `"I like \LaTeX"` Lua akan melihat `\L` dan gagal dengan kesalahan “invalid escape sequence”, dan inilah penyebab kesalahan yang disebutkan di atas.

#### String long-bracket datang sebagai penyelamat!

Metode long-brackets untuk membuat (mendefinisikan) string sangat berguna karena meskipun perintah TeX/LaTeX dimulai dengan sebuah `\` karakter, metode string long-brackets menonaktifkan (mematikan) mekanisme escape sequence Lua. Berikut contoh singkatnya, ingat bahwa kita perlu mencegah makro diperluas dengan, misalnya, `\protected` atau `\noexpand`.

Misalkan kita mendefinisikan sebuah `\newtest` makro seperti ini

`**\protected**\def\newtest#1{The argument: #1}`

dan menggunakannya dalam `\directlua` dengan fungsi LuaTeX Lua API `tex.print()`:

```
\directlua{
   tex.print("\newtest{Hello}")
}
```

Karena penggunaan `\protected`, makro `\newtest` tidak diperluas yang menghasilkan teks berikut diteruskan ke Lua:

`tex.print("\newtest {Hello}")`

Karakter spasi yang ditambahkan setelah `\newtest` dan sebelum kurung kurawal pembuka (`{`) adalah efek samping dari `\directlua`’s conversion of command tokens back to their textual representation.

Kode ini diteruskan ke Lua yang selanjutnya menjalankan fungsi LuaTeX `tex.print()` tetapi ada masalah yang muncul dengan cara yang bergantung pada font yang Anda gunakan. Di LaTeX pada Overleaf Anda akan melihat keluaran seperti ini:

![](/files/8157972e2f39fbd6e61d9e5f5087639f4eef0583)

beserta peringatan dalam berkas log:

```
   Missing character: There is no
   (U+000A) in font [lmroman10-regular]:+tlig;!
```

Dalam plain TeX Anda mungkin melihat keluaran yang tampak seperti ini:

![](/files/10370fbe5b26d731c1f6c6f8a0ce6e09d9386a42)

Dalam kedua kasus tersebut `\newtest` makro tidak dipanggil dan keluarannya bukan yang kita inginkan. Kesalahan ini disebabkan oleh mekanisme karakter escape Lua: dalam teks `\newtest {Hello}` nama makro dimulai dengan `\n` yang dikenali Lua sebagai escape sequence untuk karakter linefeed sehingga Lua menggantinya `\n` dengan karakter ASCII 10, atau dalam heksadesimal 0A. Dalam pesan kesalahan LaTeX, `U+000A` adalah cara untuk merepresentasikan nilai Unicode menggunakan 4 digit heksadesimal.

Karena `\n` dikonversi menjadi karakter linefeed, LuaTeX tidak melihat panggilan makro melainkan mengira ia diminta menata beberapa teks yang dimulai dengan kode karakter ASCII 10:

`⟨ASCII 10⟩ewtest {Hello}`

Bergantung pada font yang digunakan, LuaTeX mungkin bisa, atau mungkin tidak bisa, menata `⟨ASCII 10⟩` karakter tetapi teks sisanya dikeluarkan apa adanya dengan `{` dan `}` diperlakukan sebagai sebuah grup dan tidak dicetak.

Plain TeX memberikan hasil berbeda karena font default-nya adalah Computer Modern Roman yang memiliki pengodean aneh yang menghasilkan huruf Omega kapital ditata ketika kode karakter 10 terlihat.

Untuk mencegah masalah ini kita perlu menggunakan string long-bracket agar mekanisme escaping Lua tidak diterapkan. Hasil yang benar dihasilkan dengan

`\directlua{tex.print([[\newtest{Hello}]])}`

yang menghasilkan hasil seperti yang ditampilkan pada tangkapan layar berikut:

![](/files/2b5336c2cecd467fe7059db963ce0ce420d0b9e6)

### Ekspansi dan non-eksekusi perintah yang tidak dapat diekspansi

Saat membahas ekspansi, kita mencatat bahwa itu adalah proses di mana sebuah mesin TeX *menghapus* sebuah perintah yang dapat diekspansi (token) dari input saat ini dan *menggantikannya* dengan hasil yang dihasilkan oleh perintah yang dapat diekspansi tersebut. Karena \directlua melakukan aktivitas *hanya-ekspansi* (untuk menghasilkan daftar token), ia *tidak* tidak membawa pemrosesan LuaTeX lebih jauh dari itu. Setelah sebuah perintah yang dapat diekspansi dibaca dan diekspansi sepenuhnya, hasil ekspansi itu—yang sering kali mencakup perintah yang tidak dapat diekspansi (token)—akan dimasukkan ke dalam daftar token yang sedang dibangun, siap dikonversi kembali menjadi teks untuk diteruskan ke Lua.

Ada prinsip penting yang bekerja di sini: selama *hanya-ekspansi* aktivitas yang dirancang untuk menghasilkan daftar token, mesin TeX, termasuk LuaTeX, *tidak menjalankan* primtif, bawaan, perintah TeX yang tidak dapat diekspansi apa pun.

Dalam kasus `\directlua{⟨code⟩}`, jika versi yang telah diekspansi penuh dari `⟨code⟩` Anda menghasilkan, atau memuat perintah TeX/LaTeX yang tidak dapat diekspansi, semuanya *akan diteruskan ke Lua* (direpresentasikan sebagai teks).

#### Contoh

Berikut contoh untuk menunjukkan bahwa primitif yang tidak dapat diekspansi tidak dijalankan selama pemrosesan hanya-ekspansi (seperti di dalam `\directlua`). Misalkan kita mendefinisikan sebuah makro `\setcountreg` seperti ini:

`\def\setcountreg#1#2{\count#1=#2\relax}`

**Catatan**: Kita menggunakan `\relax` setelah parameter `#2` untuk mencegah LuaTeX melampaui batas saat memindai input dalam pencariannya terhadap nilai numerik (argumen) yang cocok dengan parameter `#2`.

Jika, di luar `\directlua`, kita kemudian menjalankan makro seperti ini

```
   \setcountreg{100}{50}
   Nilai dalam register hitung 100 adalah \the\count100.
```

itu akan menghasilkan

`Nilai dalam register hitung 100 adalah 50.`

Dalam konteks ini, mesin TeX mana pun akan memproses makro `\setcountreg`—memperluas makro, menentukan argumen, dan melanjutkan membaca *dan tindakan* (mengeksekusi) perintah yang terkandung dalam teks pengganti makro (definisi). Hasilnya di sini adalah menetapkan `50` sebagai nilai yang disimpan dalam register `\count100`.

Namun, ketika sebuah mesin TeX melakukan aktivitas *hanya-ekspansi* seperti halnya dengan `\directlua`, ia *tidak akan menjalankan* perintah yang tidak dapat diekspansi yang terkandung dalam definisi makro.

Jika kita menulis

```
\def\setcountreg#1#2{\count#1=#2\relax}
\directlua{
   local x = [[\setcountreg{100}{50}]]
}
```

ia menghasilkan teks berikut sebagai kode untuk Lua:

`local x = [[\count 100=50\relax ]]`

Kode Lua yang dihasilkan di atas menunjukkan bahwa di dalam `\directlua` situs web `\setcountreg` telah diperluas, argumennya diidentifikasi dan disubstitusikan ke parameter yang sesuai (`#1` dan `#2`) tetapi tidak melangkah lebih jauh dari itu: perintah TeX primitif yang tidak dapat diekspansi `\count` diusulkan *tidak dijalankan* selama `\directlua`pemrosesan ekspansi LuaTeX.

Namun, LuaTeX akan menjalankan kode TeX jika kita meneruskan string hasilnya `x` *kembali ke LuaTeX* melalui `tex.print(x)` seperti ini

```
\count100=50 % set \count100 to a starting value of 50
\def\setcountreg#1#2{\count#1=#2\relax}
\directlua{
   local x = [[\setcountreg{100}{250}]]
   tex.print(x)
}
Nilai yang disimpan dalam register hitung 100 adalah \the\count100.
```

Setelah `\directlua` telah selesai, keluarannya akan menjadi

`Nilai yang disimpan dalam register hitung 100 adalah 250.`

menunjukkan bahwa register hitung `100` sekarang memang berisi nilai `250`.

Kode Lua yang dihasilkan dari contoh di atas adalah

`local x = [[\count 100=250\relax ]] tex.print(x)`

Kode ini mendefinisikan `x` sebagai string yang dibuat menggunakan metode long-brackets yang digunakan untuk menghindari kesalahan dengan escape sequence yang salah. Jika kita menggunakan tanda kutip ganda `"..."` untuk mendefinisikan x, kombinasi karakter `\c` di awal `\count` akan memicu kesalahan: `invalid escape sequence near ' "\c'`.

Pemanggilan Lua API LuaTeX `tex.print(x)` mengakibatkan LuaTeX menjalankan rangkaian kode TeX `\count 100=250\relax` dan `\count100` ditetapkan bernilai `250` sebagaimana terlihat dari keluaran yang ditata huruf:

`Nilai yang disimpan dalam register hitung 100 adalah 250.`

#### Peringatan: makro dan LuaTeX Lua API

Dalam contoh di atas kita melihat bahwa selama `\directlua`pemrosesan awal (ekspansi) LuaTeX tidak menjalankan kode `\count 100=250`, yang memuat `tidak dapat diekspansi` perintah primitif `\count`: untuk menjalankan (mengeksekusi) kode itu kita harus *meneruskannya kembali ke LuaTeX* melalui `tex.print()`.

`\directlua` hanyalah salah satu contoh saat LuaTeX melakukan pemrosesan hanya-ekspansi untuk membangun daftar token. Ada perintah lain yang melakukan pemrosesan ekspansi serupa dan aktivitas pembuatan daftar token, seperti `\write` dan `\edef`: perintah-perintah itu juga tidak mengeksekusi primitif yang tidak dapat diekspansi selama pemrosesan ekspansinya. Ini merupakan prinsip umum bahwa mesin TeX tidak mengeksekusi primitif yang tidak dapat diekspansi saat membangun daftar token selama aktivitas pemrosesan hanya-ekspansi.

**Menulis ulang makro kita untuk menggunakan LuaTeX Lua API**

Kita dapat menulis ulang `\setcountreg` makro menggunakan fungsi LuaTeX Lua API yang disebut `tex.setcount()`, sehingga menghindari perintah TeX untuk mengubah nilai yang tersimpan dalam register hitung `100`:

```
   \def\setcount#1#2{\directlua{tex.setcount(#1,#2)}}
   \count100=50
   register hitung 100 berisi \the\count100\par
   \setcount{100}{250}
   register hitung 100 sekarang berisi \the\count100\par
```

Kode ini akan menata huruf:

```
register hitung 100 berisi 50
register hitung 100 sekarang berisi 250
```

Di sini kita menggunakan `tex.setcount()`, salah satu dari banyak fungsi Lua API milik LuaTeX, untuk *mengakses langsung* area penyimpanan data internal LuaTeX untuk menempatkan nilai `250` di lokasi memori yang merepresentasikan register hitung `100`. Pada praktiknya, kita telah *melewati* metode pemrosesan input mesin TeX standar milik LuaTeX: membaca input, membuat token, dan mengeksekusi perintah TeX primitif. Namun, ada kisah peringatan: dengan menggunakan fungsi Lua API milik LuaTeX, aktivitas pemrosesan hanya-ekspansi *dapat menghasilkan efek samping*: perubahan pada nilai yang disimpan di dalam mesin TeX yang tidak akan mungkin dilakukan dengan perintah TeX/LaTeX murni.

**Contoh: efek samping yang tidak terduga**

Berikut contoh untuk menunjukkan *tidak terduga* efek samping yang dapat muncul dengan makro menggunakan `\directlua`. Misalkan kita menulis kode berikut:

```
\def\dochange{\directlua{tex.setcount(999,12345)}}
\edef\careful{\dochange}
\the\count999
```

Menjalankan kode ini menata huruf `12345`!

Bagaimana bisa begitu? Kita tidak *secara eksplisit* memanggil kode atau makro apa pun untuk menempatkan nilai itu dalam register hitung `999`. Atau, apakah kita melakukannya?

Kita mendefinisikan `\dochange` dengan sebuah `\directlua` perintah yang menggunakan `tex.setcount()` untuk menyimpan nilai `12345` dalam register hitung `999`: dalam kode TeX itu setara dengan `\count999=12345`. Kita kemudian menggunakan primitif TeX standar `\edef` untuk mendefinisikan makro `\careful`—justru penggunaan `\edef` yang memicu efek samping tak terduga tersebut.

`\edef` memperluas argumennya sepenuhnya: di sini, ia mendeteksi sebuah makro yang dapat diekspansi `\dochange` dan memperluasnya. Makro `\dochange` menggunakan perintah yang dapat diekspansi `\directlua` yang memuat panggilan Lua API; jadi perluasan dari `\dochange` menghasilkan perluasan dari `\directlua` dan itu menyebabkan `tex.setcount()` dipanggil, yang mengubah nilai dalam register hitung `999`.

Jika kita mendefinisikan ulang `\dochange` untuk menggunakan perintah TeX:

```
   Sebelum: register hitung 999 berisi \the\count999.\par
   \def\dochange{\count999=12345\relax}
   \edef\careful{\dochange}
   Setelah: register hitung 999 berisi \the\count999.\par
```

menjalankan kode ini menata huruf

```
Sebelum: register hitung 999 berisi 0.
Setelah: register hitung 999 berisi 0.
```

Jelas, tidak ada efek pada `\count999`. Saat `\edef` mendefinisikan `\careful` ia memperluas `\dochange` tetapi perluasan itu hanya menghasilkan primitif TeX yang tidak dapat diekspansi: semuanya *tidak dijalankan* tetapi hanya *disimpan* dalam daftar token yang membentuk definisi `\careful`.

Sekadar untuk mempertegas, prinsip yang sama menjelaskan mengapa ini menghasilkan keluaran yang ditata huruf:

```
\def\dochange{\directlua{tex.print("Hello")}}
\edef\careful{\dochange}
```

## Pengantar singkat ke Lua API milik LuaTeX

Seperti yang telah kita lihat, `\directlua` tidak hanya memungkinkan Anda menulis kode Lua konvensional, atau campuran kode Lua dan TeX/LaTeX, tetapi juga menyediakan akses ke seperangkat fungsi Lua tambahan (khusus untuk LuaTeX) yang dapat Anda gunakan (panggil) untuk berkomunikasi dengan, atau mengendalikan langsung, cara kerja internal perangkat lunak penataan huruf LuaTeX. Kita telah menggunakan beberapa fungsi Lua dalam artikel ini, `tex.print()`, `texio.write()`, `tex.setcount()` dan fungsi-fungsi ini, bersama dengan *banyak* yang lain, didokumentasikan dalam [Panduan Referensi LuaTeX](http://www.pragma-ade.com/general/manuals/luatex.pdf) di mana kelompok fungsi yang terkait disebut sebagai *pustaka*.

Anda dapat menganggap fungsi-fungsi Lua ini sebagai Lua API milik LuaTeX (**Sebuah**p **P**rogramming **I**nterface) yang menyediakan alat untuk membangun solusi penataan huruf dan rekayasa dokumen yang canggih dengan mengendalikan perilaku penataan huruf LuaTeX menggunakan Lua sebagai penggeraknya.

Seperti telah dicatat, LuaTeX mengorganisasi API-nya menjadi sekumpulan fungsi yang disebutnya pustaka: kelompok fungsi yang saling terkait melalui tujuan atau tindakannya. Setiap kumpulan fungsi dirancang untuk memberikan akses ke aspek tertentu dari proses internal LuaTeX, struktur data, penyimpanan data, dan algoritma penataan huruf. Secara internal, LuaTeX dibangun dari berbagai komponen: pustaka/alat perangkat lunak (kebanyakan ditulis dalam C) yang tidak hanya mencakup mesin TeX itu sendiri tetapi juga subsistem lain termasuk Lua, MetaPost, Kpathsea, FontForge, libpng, dan zlib. Pustaka-pustaka ini diintegrasikan untuk membangun fitur dan fungsi perangkat lunak eksekutabel LuaTeX dan melalui Lua API inilah pengguna diberi akses ke fungsionalitas LuaTeX yang berasal dari integrasi dan koordinasi berbagai komponen perangkat lunak tersebut.

## Beberapa contoh dan jebakan

Pada bagian ini kami menyajikan beberapa contoh tambahan yang memanfaatkan topik, konsep, dan penjelasan yang diberikan dalam artikel ini.

### Menggunakan karakter tilde (\~)

Bahasa Lua menggunakan `~` karakter (disebut tilde) sebagai bagian dari sintaksnya, termasuk sintaksnya untuk melakukan uji “tidak sama dengan”; misalnya, untuk menguji apakah sebuah variabel `x` tidak sama dengan `4` kita dapat menulis:

```
   local x=3
   if x ~= 4 then
   print("x tidak sama dengan 4")
   end
```

Jika kita mencoba menjalankan kode Lua sederhana ini melalui `\directlua`:

```
\directlua{
   local x=3
   if x ~= 4 then
   print("x tidak sama dengan 4")
   end
}
```

kita mendapat pesan kesalahan:

`[\directlua]:1: 'then' diharapkan dekat '\'.`

Itu aneh karena kode kita benar: kita telah menggunakan `'then'` dan tidak ada `\` karakter dalam kode kita, jadi apa yang salah? Untuk memahaminya, kita harus ingat bahwa, bagi TeX/LaTeX, `~` biasanya didefinisikan sebagai “karakter khusus” dengan kode kategori 13: yang disebut karakter aktif, yaitu makro-mini dan karenanya tunduk pada ekspansi. Ketika `\directlua` mendeteksi `~` karakter itu diekspansi dengan *menghapusnya* dari masukan dan *menggantinya* dengan hasil ekspansinya. Dengan plain TeX, teks (kode) yang dihasilkan LuaTeX dan diteruskan ke interpreter Lua sebenarnya tidak mengandung `~` karakter, dan adalah:

`local x=3 if x \penalty \@M \ = 4 then print("x tidak sama dengan 4") end`

Fitur `~` karakter telah *dihapus* dan *diekspansi* menjadi perintah-perintah penyusunnya—kode Lua di atas merupakan hasil dari definisi plain TeX atas karakter aktif `~`. Sekarang kita bisa melihat mengapa Lua merespons dengan kesalahan `'then' diharapkan dekat '\'`—ia mulai mengurai kode ini tetapi menemukan kata `\penalty` yang tidak berarti apa pun bagi Lua dan menghasilkan kesalahan sintaks.

Untuk memperbaiki ini,  `~` karakter perlu memiliki kode kategori yang aman pada saat `\directlua` memproses kode Anda; misalnya, kita dapat sementara mengubah kode kategori dari `~` menjadi 11 (huruf) dengan membungkus kode dalam sebuah grup:

```
\begingroup
\catcode`\~=11
\directlua{
   local x=3
   if x ~= 4 then
   print("x tidak sama dengan 4")
   end
}
\endgroup
```

Kode ini bekerja seperti yang diharapkan dan `x tidak sama dengan 4` dicetak ke konsol. Ada opsi lain: kita dapat menggunakan perintah yang dapat diekspansi `\noexpand` atau `\string`.

#### Menggunakan \string⟨token⟩

Kita dapat menerapkan `\string` ke karakter tunggal `⟨token⟩` `~` yang memiliki kode kategori 13 (karakter aktif); `\string` mengonversi `~` karakter untuk menghasilkan token karakter yang memiliki kode kategori 12. Jika kita melakukan

```
\directlua{
   local x=3
   if x \string~= 4 then
   print("x tidak sama dengan 4")
   end
}
```

itu menghasilkan kode Lua yang kita perlukan:

`local x=3 if x ~= 4 then tex.print("x tidak sama dengan 4") end`

#### Menggunakan \noexpand⟨token⟩

Kita dapat menggunakan `\noexpand~` untuk menekan ekspansi karakter aktif `~`

```
\directlua{
   local x=3
   if x \noexpand~= 4 then
   print("x tidak sama dengan 4")
   end
}
```

Token yang tidak diekspansi `~` lewat ke daftar token yang sedang dibangun di `\directlua` dan akan dikonversi kembali menjadi teks yang menghasilkan kode Lua yang berfungsi.

### Menggunakan karakter \#

Dalam bahasa Lua, karakter `#` karakter dapat digunakan untuk mencari panjang sebuah tabel. Namun, jika kita mencoba kode berikut

```
\directlua{
   local tbl = {}
   tbl[1] = "Halo"
   tbl[2] = "Dunia"
   tex.print("Panjang tabel adalah "..#tbl)
}
```

kita mungkin berharap LuaTeX menata

`Panjang tabel adalah 2`

tetapi ia menghasilkan kesalahan:

`\directlua]:1: percobaan untuk mendapatkan panjang dari nilai numerik`

Kesalahan ini dipicu karena `#` karakter biasanya memiliki kode kategori 6 (parameter makro)—karakter `#` karakter memiliki dua kegunaan dalam TeX/LaTeX: untuk menunjukkan parameter makro (`#1`, `#2`… `#9`) dan teks pengganti dalam templat perataan (untuk `\halign` dan `\valign`).

Saat `\directlua` sedang menghasilkan token untuk membangun daftar tokennya, ia melihat `#` karakter dengan kode kategori 6 dan membuat token karakter yang sesuai untuk mewakilinya. Saat tiba waktunya mengonversi daftar token akhir kembali ke bentuk tekstual, token karakter untuk # (dengan kode kategori 6) menerima perlakuan khusus: token itu dikeluarkan sebagai *dua karakter berurutan*: `##`, sehingga kode berikut diteruskan ke Lua:

`local tbl = {} tbl[1] = "Halo" tbl[2] = "Dunia" print(##tbl)`

Saat dikonversi ke kode Lua, yang asli `#` telah digandakan dan itu menghasilkan kesalahan:

`\directlua]:1: percobaan untuk mendapatkan panjang dari nilai numerik`

Masalah ini muncul karena sintaks TeX yang menggunakan simbol pagar ganda `##` untuk merepresentasikan atau menghasilkan satu `#` token; sintaks ini digunakan dalam makro yang mendefinisikan makro lain yang menerima parameter, atau dalam makro yang digunakan untuk membuat templat bagi `\halign` atau `\valign` perintah pembuatan tabel. Ini cukup membingungkan, jadi mari kita lihat contohnya.

#### Contoh

Misalkan kita mendefinisikan sebuah makro `\mymacro` yang menerima satu parameter, `#1`, tetapi juga mendefinisikan makro kedua `\foo` yang juga menerima satu parameter. Untuk membedakan antara parameter `#1` yang digunakan dengan `\mymacro` dan kebutuhan untuk mendefinisikan `\foo` untuk menggunakan parameternya sendiri `#1` Sintaks TeX mengharuskan Anda menggunakan `##1` di dalam `\mymacro` untuk merepresentasikan parameter yang digunakan dengan `\foo`:

`\def\mymacro#1{\def\foo##1{#1 Halo##1}}`

Jika Anda menulis `\mymacro{Hei!}` itu akan mendefinisikan makro `\foo` menjadi

`\def\foo#1{Hei! Halo#1}`

Perhatikan bahwa `\mymacro`parameter `#1` (`Hei!`) telah dimasukkan ke dalam definisi `\foo` dan urutan `##1` telah diubah menjadi `#1` dalam definisi `\foo`. Jadi kita dapat menggunakan `\foo` seperti ini:

`\foo{, Dunia!}`

untuk menata `Hei! Halo, Dunia!`

Kita dapat mengatasi `\directlua`perlakuan `#` karakter dengan sementara mengubah kode kategorinya sebelum LuaTeX memproses kode. Misalnya:

```
\begingroup
   \catcode`\#=11
   \directlua{
   local tbl = {}
   tbl[1] = "Halo"
   tbl[2] = "Dunia"
   tex.print("Panjang tabel adalah "..#tbl)
}
\endgroup
```

Ini menghasilkan kode Lua

```
local tbl = {} tbl[1] = "Halo" tbl[2] = "Dunia" tex.print("Panjang tabel adalah "..#tbl)
```

yang menata hasil yang kita harapkan:

`Panjang tabel adalah 2`

### Menggunakan karakter %

Dalam TeX/LaTeX, karakter `%` karakter biasanya digunakan untuk menyertakan komentar satu baris dalam kode Anda: untuk memberi sinyal kepada mesin TeX agar mengabaikan semuanya dari titik itu hingga akhir baris tempat `%` ditulis. Namun, dalam bahasa Lua, karakter `%` karakter digunakan dalam beberapa fungsi pemrosesan string yang sangat berguna, seperti `string.format(...)`, `string.gmatch(...)`, dan `string.gsub(...)` di mana karakter `%` karakter memainkan peran penting sebagai bagian dari sintaks fungsi-fungsi tersebut.

Saat digunakan dengan TeX/LaTeX, `%` bertindak sebagai karakter komentar karena diberi kode kategori 14. Agar ia berperilaku sebagai karakter biasa, dan menonaktifkan perilaku standar TeX/LaTeX-nya, kita perlu mengubah kode kategorinya menjadi sesuatu yang aman, seperti 12.  `\directlua` Contoh di bawah menggunakan sejumlah teknik yang dibahas sebelumnya dalam artikel ini, bersama dengan satu yang belum kita sebutkan: ``\catcode`\^^M=12``, yang memungkinkan kita menggunakan komentar Lua dalam kode kita; ini dibahas di bawah.

#### Contoh

Contoh-contoh berikut dipinjam dari [lua-users.org](http://lua-users.org/wiki/StringLibraryTutorial), telah dimodifikasi seperlunya untuk digunakan dalam `\directlua`.

```
\documentclass{article}
\begin{document}
\begingroup
\ttfamily
\let\\\relax
\catcode`\^^M=12 %<---kita akan membahas ini lebih lanjut di bawah!
\catcode`\%=12
\directlua{
   local str -- deklarasikan variabel lokal untuk menyimpan hasil

   tex.print("Menggunakan string.format():".."\\par")

   str=string.format("%s %q", "Halo", "Pengguna Lua!") -- string dan string yang diapit tanda kutip
   tex.print(str.."\\par")
   str = string.format("%c%c%c", 76, 117, 97) -- karakter
   tex.print(str.."\\par")
   str=string.format("%e, %E", math.pi, math.pi) -- eksponen
   tex.print(str.."\\par")
   str=string.format("%f", math.pi) -- bilangan pecahan
   tex.print(str.."\\par")
   str=string.format("%g, %g", math.pi, 10^9) -- bilangan pecahan atau eksponen
   tex.print(str.."\\par")
   str = string.format("%o, %x, %X", 99, 125, 125)  -- oktal, heksadesimal, heksadesimal
   tex.print(str.."\\par")

   tex.print("\\vskip3mm".."Menggunakan string.gmatch():".."\\par")

   for word in string.gmatch("Halo pengguna TeX", "%a+") do
      tex.print(word.."\\par")
   end

   tex.print("\\vskip3mm".."Menggunakan string.gsub():".."\\par")
   str=string.gsub("banana", "(an)", "%1-") -- tangkap setiap kemunculan "an" dan ganti
   tex.print(str.."\\par")
}
\endgroup
\end{document}
```

Tangkapan layar berikut menunjukkan hasil penataan dari kode di atas:

![Menggunakan fungsi string Lua dalam \directlua](/files/8196b2305630e2c1f6916196828974d4d8cd0f41)

## Mengapa kode Lua ditampilkan pada satu baris?

Seperti yang mungkin Anda perhatikan, semua fragmen kode Lua (yang dihasilkan) yang ditampilkan dalam contoh-contoh artikel ini disajikan sebagai satu baris teks: pemisah baris yang semula ada dalam `\directlua` cuplikan kode tidak diikuti. Mengapa demikian? Itu karena pemisah baris dalam kode Lua telah *dihapus* selama praproses LuaTeX di dalam `\directlua`, sehingga kode Lua menjadi satu baris teks yang panjang. Perilaku itu dapat ditelusuri ke cara mesin TeX menangani karakter akhir-baris—dilambangkan dengan `\r` (carriage return) dan `\n` (line feed) dalam literatur pemrograman. Mengapa kita perlu memikirkan detail-detail kecil ini akan menjadi jelas ketika kita membahas penggunaan mekanisme Lua untuk mengomentari bagian-bagian kode.

Saat perangkat lunak menulis (menyimpan) file teks, setiap baris teks diakhiri oleh karakter yang disebut “newline”—karakter newline yang sebenarnya bergantung pada aplikasi dan sistem operasi yang digunakan untuk menulis file tersebut. Wikipedia memiliki sebuah [artikel yang menarik](https://en.wikipedia.org/wiki/Newline) yang membahas sejarah/evolusi karakter newline yang digunakan saat ini.

Pada file teks apa pun, tiap baris teksnya dapat diakhiri oleh berbagai kombinasi karakter, yang disebut carriage return (karakter ASCII/Unicode 13) dan/atau line feed (karakter ASCII/Unicode 10), yang dilambangkan dengan `\r` dan `\n` masing-masing. Karena mesin TeX dirancang agar independen terhadap platform, mereka memerlukan metode untuk mengatasi sifat penutup baris yang secara inheren bergantung pada platform dalam file teks. Tentu saja, mesin TeX memiliki metode bawaan (namun dapat dikonfigurasi) untuk menangani karakter penutup baris.

### Bagaimana mesin TeX menangani penutup baris

Saat LuaTeX memproses `\directlua{⟨code⟩}` ia membaca teks yang terdapat dalam `⟨code⟩` dan menerapkan metode standar mesin TeX untuk memproses setiap penutup baris yang terdapat dalam `⟨code⟩`. Secara default, metode standar TeX tersebut menyebabkan semua karakter penutup baris (carriage return dan line feed) dihapus dan diganti dengan karakter spasi. Kami mengatakan “secara default” karena penanganan karakter penutup baris oleh mesin TeX dapat dimodifikasi melalui parameter yang dapat dikonfigurasi pengguna yang disebut `\endlinechar`. Di sini, kami akan memberikan gambaran singkat dua langkah, tetapi rincian lebih lanjut dapat ditemukan dalam artikel Overleaf [Pengantar \endlinechar: Bagaimana TeX membaca baris dari file teks](/latex/id/artikel-mendalam/05-an-introduction-to-endlinechar-how-tex-reads-lines-from-text-files.md).

#### Langkah 1: TeX menyisipkan karakter akhir-barisnya sendiri

Setelah membaca sebuah baris teks dari file masukan Anda, mesin TeX segera menghapus semua `\r` atau `\n` karakter dari akhir baris itu. Berikutnya, mesin TeX *menyisipkan* (menambahkan kembali) karakter penutup baris mereka sendiri ke akhir baris itu. Karakter tersebut ditentukan oleh nilai parameter TeX yang dapat dikonfigurasi pengguna yang disebut `\endlinechar` dan melalui mekanisme inilah mesin TeX dapat memproses karakter akhir-baris secara independen terhadap platform: mereka memilih, dan menetapkan, karakter akhir-baris terlepas dari apa yang semula terdapat dalam file teks masukan.

Biasanya, mesin TeX menggunakan pengaturan

`\endlinechar=13`

yang merupakan karakter carriage return (`\r`). Namun, pengguna selalu dapat menetapkan kode karakter lain sebagai nilai dari `\endlinechar`—yang akan kita lihat nanti dalam artikel ini.

Akibatnya, setiap karakter penutup baris yang terdapat dalam `⟨code⟩` untuk diproses oleh `\directlua{⟨code⟩}` dihapus dan diganti oleh satu karakter yang ditentukan oleh mesin TeX itu sendiri. Perhatikan bahwa mesin TeX melakukan pemrosesan akhir-baris ini segera setelah membaca baris teks baru dari sebuah file dan *sebelum* memproses karakter apa pun dalam baris itu (untuk menghasilkan token). Namun, ini belum akhir cerita: apa yang dilakukan mesin TeX *tidak* terhadap karakter-karakter akhir-baris itu (yang telah disisipkannya) menjelaskan mengapa kode Lua menjadi satu baris tunggal.

#### Langkah 2: TeX mengonversi karakter akhir-barisnya menjadi spasi

Selain menyisipkan karakter penutup barisnya sendiri, yang ditentukan oleh nilai `\endlinechar`, mesin TeX juga menggunakan kode kategori 5 untuk karakter yang seharusnya *diperlakukan sebagai* sebuah karakter akhir-baris. Ini menyebabkan mesin TeX biasanya bekerja dengan:

1. sebuah karakter akhir-baris yang ditentukan oleh `\endlinechar`;
2. karakter yang sama itu *biasanya* diberi kode kategori 5.

Apa yang TeX lakukan terhadap karakter akhir-baris itulah yang menjelaskan kebingungan kita mengenai kode Lua satu baris. Saat mesin TeX memproses sebuah baris masukan, pada akhirnya ia akan mendeteksi karakter terakhir dalam baris itu: karakter yang ditentukan oleh `\endlinechar`. Biasanya, karakter tersebut memiliki kode kategori 5 yang menyebabkan TeX *menggantinya* dengan karakter spasi: yaitu, pada akhir baris, TeX pada dasarnya menghapus karakter penutup barisnya dan menggantinya dengan spasi. Sebagai catatan, mesin TeX juga menggunakan karakter dengan kode kategori 5 untuk mendeteksi baris kosong dan memulai paragraf baru, tetapi kita tidak akan membahasnya di sini.

Tentu saja, karena ini TeX, Anda dapat melakukan berbagai macam trik pemrograman makro khusus dengan mengatur ulang `\endlinechar` ke karakter lain, dan/atau memberikan karakter yang ditetapkan ke `\endlinechar` nilai kode kategori sesuai pilihan Anda.

Jika Anda ingin mencegah kode Lua menjadi satu baris teks, Anda dapat (sementara) mengubah nilai yang ditetapkan ke `\endlinechar` atau mengubah kode kategori dari penanda akhir-baris standar `\r`.

### notasi ^^ TeX yang aneh

Dalam bagian-bagian berikut kita akan menemui `^^` notasi yang tidak biasa dari TeX, yang dikenal sebagai “mekanisme karakter yang diperluas”. Notasi ini dirancang oleh Knuth sebagai cara untuk memudahkan pengetikan “karakter kontrol” seperti penanda akhir-baris, tab, dan sebagainya. Misalnya:

* `^^J` merepresentasikan kode karakter 10 (`\n`, line feed);
* `^^M` merepresentasikan kode karakter 13 (`\r`, carriage return).

Urutan karakter seperti `^^M` diubah menjadi kode karakter yang sesuai pada awal proses pemindaian masukan TeX, ketika TeX membaca karakter masukan untuk menghasilkan token karakter yang sesuai.

### Mengubah karakter yang ditetapkan ke \endlinechar

Dengan mengingat bahwa kita masih perlu mencegah ekspansi dari `~` karakter, kita dapat menulis

```
\begingroup
\endlinechar=10 % Ubah karakter akhir-baris menjadi \n
\directlua{
   local x=3
   if x \noexpand~= 4 then
   print("x tidak sama dengan 4")
   end
}% tidak ingin \n muncul di sini
\endgroup% atau \n di sini
```

Pengaturan di atas untuk `\endlinechar` menyebabkan LuaTeX menambahkan kode karakter 10 (`\n`, line feed) ke akhir setiap baris yang dibacanya. Kita melakukan ini karena `\n` (line feed) biasanya memiliki kode kategori 12, yang dapat Anda uji dengan menulis ``\the\catcode`\^^J``. Karena `\n` tidak memiliki kode kategori 5, LuaTeX tidak akan mengubahnya menjadi karakter spasi sehingga ia tetap berada di akhir setiap baris yang dibaca oleh LuaTeX. Ini menghasilkan karakter dengan kode 10 yang tetap berada di akhir setiap baris, sehingga lolos ke dalam daftar token yang sedang dibangun oleh `\directlua` dan kemudian muncul kembali dalam kode Lua setelah daftar token dikonversi menjadi teks. Dengan perubahan di atas, kode Lua dikirim ke interpreter Lua sebagai urutan karakter berikut:

**\n**local x=3\*\*\n**if x \~= 4 then**\n**print("x tidak sama dengan 4")**\n**end**\n\*\*

di mana **\n** notasi ini dimaksudkan untuk merepresentasikan kode karakter 10 *berisi nilai data aktual yang disimpan dalam* beberapa makro tak dikenal `\n`. Sekarang, interpreter Lua akan melihat pemisah baris dalam kode, persis seperti yang semula ditulis dalam `\directlua` perintah:

```
   local x=3
   if x ~= 4 then
   print("x tidak sama dengan 4")
   end
```

Ngomong-ngomong, perhatikan bahwa karakter pertama dalam string kode Lua adalah `\n` (sebelum `lokal` kata kunci). Itu `\n` muncul dari baris

`\directlua{`

karena ada pemisah baris tepat setelah pembuka `{` dan ini juga dipertahankan. Untuk mencegahnya Anda dapat

`\directlua{%`

### Mengubah kode kategori dari \r

Untuk mempertahankan pemisah baris dalam kode Lua kita juga dapat mengubah kode kategori dari `\r` menjadi sesuatu selain 5, sehingga `\r` tidak lagi dikenali (diperlakukan sebagai) karakter akhir-baris. Dengan teknik ini LuaTeX tetap menggunakan `\endlinechar=13` dan akan terus menambahkan sebuah `\r` ke akhir setiap baris; namun, karena `\r` tidak lagi memiliki kode kategori 5, LuaTeX tidak akan mengenali `\r` karakter sebagai penutup baris: ia tidak akan mengubahnya menjadi spasi dan meneruskannya tanpa berubah agar muncul dalam kode Lua.

Dengan mengingat bahwa kita masih perlu mencegah ekspansi dari `~` karakter, kita dapat menulis

```
\begingroup
\catcode`\^^M=12 % ubah kode kategori dari \r menjadi 12
\directlua{
   local x=3
   if x \noexpand~= 4 then
   print("x tidak sama dengan 4")
   end
}
\endgroup
```

Dalam kasus ini, kode Lua dikirim ke interpreter Lua sebagai:

**\r**local x=3\*\*\r**if x \~= 4 then**\r**print("x tidak sama dengan 4")**\r**end**\r\*\*

di mana `\r` notasi ini dimaksudkan untuk merepresentasikan kode karakter 13, bukan makro tak dikenal apa pun `\r`. Seperti pada `\endlinechar` contoh, interpreter Lua sekarang akan melihat pemisah baris dalam kode, persis seperti yang semula ditulis dalam `\directlua` perintah:

```
   local x=3
   if x ~= 4 then
   print("x tidak sama dengan 4")
   end
```

Ngomong-ngomong, perhatikan lagi bahwa karakter pertama dalam string kode Lua adalah `\r` (sebelum kata kunci local): ini juga muncul dari baris

`\directlua{`

#### Mengapa \r menggunakan kode kategori 12 tetapi bukan kode kategori 11?

Jawabannya adalah karena risiko secara tidak sengaja menimbulkan kesalahan yang dipicu oleh `\r` (dengan kode kategori 11) yang ditambahkan ke akhir perintah TeX/LaTeX yang dibaca dari file masukan kita. Perhatikan contoh ini:

```
\begingroup
\catcode`\^^M=11 % ubah kode kategori dari \r menjadi 11
\directlua{
   local x=3
   if x \noexpand~= 4 then
   print("x tidak sama dengan 4")
   end
}
\endgroup
```

yang menghasilkan kesalahan:

```
   ! Rangkaian kontrol tidak terdefinisi.
   l.9 \endgroup
```

Bagaimana itu bisa terjadi padahal `\endgroup` adalah perintah primitif TeX standar? Penyebab kesalahan ini cukup halus: Saat LuaTeX membaca baris teks terakhir—yang berisi `\endgroup`—ia juga menambahkan `\endlinechar` karakter `\r` ke akhir baris itu. Sekarang, di dalam memorinya, LuaTeX melihat urutan karakter

`\endgroup\r`

di mana kita menggunakan `\r` untuk menunjukkan karakter dengan kode 13—bukan nama dari makro TeX tak dikenal apa pun `\r`.

Saat LuaTeX membaca baris ini dari file teks kita, keberadaan `\begingroup` masih aktif: kita berada di dalam grup yang belum ditutup dengan menjalankan `\endgroup` perintah yang cocok—yang akan menyebabkan `\r` kembali ke nilai kode kategori sebelumnya, yaitu 5.

Saat LuaTeX mulai memproses (membuat token) dari baris teks `\endgroup\r` ia mengenali karakter pertama `\` sebagai karakter escape yang memicu LuaTeX mulai mencari nama sebuah perintah. Untuk mengidentifikasi nama perintah, LuaTeX mencari urutan karakter dengan kode kategori 11, tetapi karena `\r` juga memiliki kode kategori 11, LuaTeX mengira karakter `\r` karakter (masih dengan kode kategori 11) membentuk *bagian dari sebuah perintah* bernama `\endgroup\r` yang tentu saja tidak ada sehingga LuaTeX melaporkan `Rangkaian kontrol tak terdefinisi` kesalahan. Itulah sebabnya kita menggunakan kode kategori 12 dan bukan 11.

Karena pesan kesalahan LuaTeX ditulis ke konsol, kita tidak dapat dengan mudah melihat/memperhatikan `\r` karakter tersebut sehingga tidak jelas apa yang menyebabkan kesalahan.

### Mengapa kita memikirkan akhir-baris?

Alasannya adalah untuk memungkinkan penggunaan metode komentar Lua dalam kode Anda! Anda dapat menggunakan mekanisme standar LuaTeX untuk menambahkan `%` karakter untuk mengomentari satu baris dalam kode Anda; namun, bahasa Lua memiliki mekanisme komentar *multi-baris* yang mungkin ingin Anda manfaatkan.

Mari kita mulai dengan melihat apa yang terjadi jika kita mencoba menggunakan komentar satu baris bahasa Lua tanpa menangani masalah pemisah baris. Sementara TeX menggunakan `%` karakter untuk mengomentari satu baris kode, Lua menggunakan dua tanda hubung: `--`.

Apa yang terjadi jika kita mencoba menjalankan ini:

```
\directlua{
   local x=3
   if x \noexpand~= 4 then
   -- Saya akan menampilkan hasil dari pengujian kompleks ini
   print("x tidak sama dengan 4")
   end
}
```

Kita mendapat kesalahan:

`[\directlua]:1: 'end' diharapkan dekat <eof>`

Kesalahan ini disebabkan oleh tidak adanya pemisah baris dalam kode Lua yang diteruskan ke interpreter, yang hanya melihat satu string kontinu tunggal di mana komentar dimulai di tengah-tengah string tersebut:

```

local x=3 if x ~= 4 then -- Saya akan menampilkan hasil dari pengujian kompleks ini print("x tidak sama dengan 4") end
```

Segalanya setelah `**local x=3 if x ~= 4 then**` diperlakukan sebagai bagian yang dikomentari sehingga menyebabkan interpreter melihat potongan kode Lua yang tidak lengkap, yang berakibat pada kesalahan

`'end' diharapkan dekat <eof>`.

di mana `<eof>` berarti akhir berkas.

Seperti yang mungkin telah Anda duga, kita harus memperbaikinya dengan memastikan pemisah baris diteruskan ke kode Lua yang dihasilkan, yang dapat kita lakukan dengan, misalnya, mengubah kode kategori dari `\r` ke 12:

```
\begingroup
\catcode`\^^M=12 % ubah kode kategori dari \r menjadi 12
\directlua{
   local x=3
   if x \noexpand~= 4 then
   -- Saya akan menampilkan hasil dari pengujian kompleks ini
   print("x tidak sama dengan 4")
   end
}
\endgroup
```

Sekarang, interpreter Lua melihat sebuah string tetapi string itu berisi `\r` pemutusan baris seperti yang ditulis dalam `\directlua` fragmen:

**\r**local x=3\*\*\r**if x \~= 4 then**\r\*\*-- Saya akan menampilkan hasil dari pengujian kompleks ini\*\*\r**tex.print("x tidak sama dengan 4")**\r**end**\r\*\*

Ini, pada dasarnya, setara dengan menulis

```
   local x=3
   if x \noexpand~= 4 then
   -- Saya akan menampilkan hasil dari pengujian kompleks ini
   print("x tidak sama dengan 4")
   end
```

yang berarti Lua dapat memproses kode ini dengan benar dan mengabaikan baris yang kita komentari.

**Komentar blok**

Bahasa Lua juga mendukung sintaks yang disebutnya [“komentar blok”](https://www.lua.org/pil/1.3.html) (atau *komentar panjang*): ini diawali dengan `--[[` dan berlaku hingga `]]`. Kita dapat menggunakan sintaks yang praktis ini untuk menulis komentar multi-baris, atau mengomentari bagian kode yang ingin kita hapus sementara:

```
\begingroup
\catcode`\^^M=12 % ubah kode kategori dari \r menjadi 12
\directlua{
   local x=3
   if x \noexpand~= 4 then
   --[[ Saya akan menampilkan hasil dari pengujian kompleks ini
   semata-mata karena memang benar-benar
   kesimpulan yang luar biasa ini]]
   print("x tidak sama dengan 4")
   end
}
\endgroup
```

## Sebagai penutup

Pertama-tama, selamat jika Anda berhasil membaca artikel yang cukup panjang ini! Kami telah berusaha menyusun panduan yang cukup komprehensif tentang konsep dan topik terkait TeX yang memberikan latar belakang yang diperlukan untuk mendapatkan hasil maksimal dari LuaTeX melalui `\directlua` perintah. Kami berharap telah menghasilkan artikel yang bersifat informatif dan memberikan sesuatu yang berguna dan bernilai bagi komunitas pengguna Overleaf, dan juga lebih luas lagi. Seperti biasa, kami senang menerima masukan, jadi silakan merasa bebas untuk [hubungi kami](https://www.overleaf.com/contact) memberikan komentar tentang artikel ini atau saran untuk topik lain yang ingin Anda baca dari kami.

Selamat $$\text{Lua}\mathrm{\TeX}\text{-ing!}$$ dari Graham Douglas dan tim Overleaf.

### Dan akhirnya... cukup gunakan paket luacode

Meskipun TeX dan Lua beroperasi dengan cara yang pada dasarnya berbeda, kedua bahasa tersebut berbagi sejumlah karakter yang memiliki “makna khusus” dalam konteks masing-masing bahasa—seperti \\, %, \~, #, ^, &—tentu saja, Lua dan TeX memberikan makna khusus itu untuk *sangat* tujuan yang berbeda. Penjelajahan kami terhadap karakter bermasalah menunjukkan mengapa kesulitan dapat muncul dan bagaimana Anda dapat mengatasinya; namun, memperbaiki secara manual banyak fragmen kode Lua yang kecil bisa cukup merepotkan, jadi sebagian besar pengguna lebih memilih menggunakan paket LaTeX yang menghilangkan tantangan tersebut. Salah satu paket tersebut adalah [`luacode`](https://ctan.org/pkg/luacode?lang=en) yang menyediakan serangkaian fitur yang dirancang untuk menyederhanakan bekerja dengan `\directlua`, tetapi setidaknya sekarang Anda mungkin memiliki pemahaman yang lebih baik tentang masalah-masalah yang `luacode` diselesaikannya untuk Anda.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://overleaf-pro.ayaka.space/latex/id/artikel-mendalam/09-an-introduction-to-luatex-part-2-understanding-directlua.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
