Compare commits
5 Commits
master
...
set-exampl
Author | SHA1 | Date | |
---|---|---|---|
|
e655751043 | ||
|
30ede7255a | ||
|
af92697063 | ||
|
af38aebc75 | ||
|
32b0a2c936 |
1
.gitignore
vendored
1
.gitignore
vendored
@ -1 +0,0 @@
|
|||||||
*.pdf
|
|
15
CHANGELOG.md
15
CHANGELOG.md
@ -1,15 +0,0 @@
|
|||||||
# Changelog
|
|
||||||
|
|
||||||
## 0.4.0
|
|
||||||
* Implemented new API with `example` and `gloss` functions
|
|
||||||
* Some code style changes to be consistent with typst version 0.12
|
|
||||||
|
|
||||||
## 0.3.0
|
|
||||||
* Added `label` and `label-supplement` arguments to `gloss` function
|
|
||||||
* Added borders around code + rendered example in documentation pdf
|
|
||||||
|
|
||||||
## 0.2.0
|
|
||||||
* renamed `numbered_gloss` to `numbered-gloss`, `gloss_count` to `gloss-count`, in light of the
|
|
||||||
Typst style preference for kebab-case. Also renamed their arguments to use snake-case as well.
|
|
||||||
* Documented standard abbreviations
|
|
||||||
* Removed all default gloss line formatting
|
|
25
README.md
25
README.md
@ -4,28 +4,22 @@
|
|||||||
creating interlinear morpheme-by-morpheme glosses according to the [Leipzig
|
creating interlinear morpheme-by-morpheme glosses according to the [Leipzig
|
||||||
glossing rules](https://www.eva.mpg.de/lingua/pdf/Glossing-Rules.pdf).
|
glossing rules](https://www.eva.mpg.de/lingua/pdf/Glossing-Rules.pdf).
|
||||||
|
|
||||||
# Documentation
|
Run `typst compile leipzig-gloss-examples.typ` in the root of the repository to
|
||||||
|
|
||||||
Run `typst compile documentation.typ` in the root of the repository to
|
|
||||||
generate a pdf file with examples and documentation. This command is also
|
generate a pdf file with examples and documentation. This command is also
|
||||||
codified in the accompanying [justfile](https://github.com/casey/just) as `just
|
codified in the accompanying [justfile](https://github.com/casey/just) as `just
|
||||||
build-doc`.
|
build-example`.
|
||||||
|
|
||||||
The definitions intended for use by end users are the `gloss` and
|
The definitions intended for use by end users are the `#gloss` and
|
||||||
`numbered-gloss` functions, and the `abbreviations` submodule.
|
`#numbered_gloss` functions.
|
||||||
|
|
||||||
|
|
||||||
# Contributing
|
# Contributing
|
||||||
|
|
||||||
## Repositories
|
|
||||||
|
|
||||||
The canonical repository for this project is on the [Gitea
|
The canonical repository for this project is on the [Gitea
|
||||||
instance](https://code.everydayimshuflin.com/greg/typst-lepizig-glossing).
|
instance](https://code.everydayimshuflin.com/greg/typst-lepizig-glossing). The
|
||||||
|
repository is also [mirrored on
|
||||||
There is also a [Github mirror](https://github.com/neunenak/typst-leipzig-glossing/), and
|
Github](https://github.com/neunenak/typst-leipzig-glossing/). Bug reports and
|
||||||
a [Radicle](https://radicle.xyz) mirror available at <rad://z2j7vQLS3EtQbPkrzi7Tn2XR7YWLw>.
|
code contributions are welcome from all users.
|
||||||
|
|
||||||
Bug reports and code contributions are welcome from all users.
|
|
||||||
|
|
||||||
## License
|
## License
|
||||||
This library uses the MIT license; see `LICENSE.txt`.
|
This library uses the MIT license; see `LICENSE.txt`.
|
||||||
@ -34,6 +28,3 @@ This library uses the MIT license; see `LICENSE.txt`.
|
|||||||
|
|
||||||
Thanks to [Bethany E. Toma](https://github.com/betoma) for a number of
|
Thanks to [Bethany E. Toma](https://github.com/betoma) for a number of
|
||||||
suggestions and improvements.
|
suggestions and improvements.
|
||||||
|
|
||||||
Thanks to [Maja Abramski-Kronenberg](https://github.com/rwmpelstilzchen) for
|
|
||||||
the labeling functionality.
|
|
||||||
|
@ -1,58 +0,0 @@
|
|||||||
#import "abbreviations.typ": *
|
|
||||||
|
|
||||||
#let custom-abbreviations = (
|
|
||||||
"FMNT": "Present/Future stem formant",
|
|
||||||
)
|
|
||||||
|
|
||||||
#let fmnt = emit-abbreviation("FMNT")
|
|
||||||
|
|
||||||
// An example function that uses `with-used-abbreviations`
|
|
||||||
#let print_usage_chart = with-used-abbreviations(final-used-abbreviations => {
|
|
||||||
|
|
||||||
show terms: t => {
|
|
||||||
for t in t.children [
|
|
||||||
#t.term #h(2cm) #t.description\
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
||||||
let print-abbrevs(abbrv_list) = {
|
|
||||||
for abbrv in abbrv_list {
|
|
||||||
let explanation = if abbrv in standard-abbreviations {
|
|
||||||
standard-abbreviations.at(abbrv)
|
|
||||||
} else {
|
|
||||||
custom-abbreviations.at(abbrv)
|
|
||||||
}
|
|
||||||
|
|
||||||
terms((smallcaps(lower(abbrv)), explanation))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
heading(level: 3)[Abbreviations in order of use]
|
|
||||||
print-abbrevs(final-used-abbreviations.keys())
|
|
||||||
|
|
||||||
heading(level: 3)[Abbreviations in alphabetical order]
|
|
||||||
let sorted-abbreviations = final-used-abbreviations.keys().sorted()
|
|
||||||
print-abbrevs(sorted-abbreviations)
|
|
||||||
})
|
|
||||||
|
|
||||||
= Some linguistics paper
|
|
||||||
|
|
||||||
|
|
||||||
== Abbreviations used in this document
|
|
||||||
#print_usage_chart
|
|
||||||
|
|
||||||
== The main body of the paper
|
|
||||||
|
|
||||||
|
|
||||||
The #p1#sg pronoun in Spanish is _yo_. The #p2#sg pronoun in Spanish is _tu_.
|
|
||||||
|
|
||||||
The six cases of Latin are:
|
|
||||||
- Nominative (#nom)
|
|
||||||
- Genitive (#gen)
|
|
||||||
- Dative (#dat)
|
|
||||||
- Accusative (#acc)
|
|
||||||
- Ablative (#abl)
|
|
||||||
- Vocative (#voc)
|
|
||||||
|
|
||||||
The Present/Future stem formant (#fmnt) in Georgian disappears in perfective screeves.
|
|
||||||
|
|
@ -1,205 +0,0 @@
|
|||||||
// See https://www.eva.mpg.de/lingua/resources/glossing-rules.php
|
|
||||||
#let standard-abbreviations = (
|
|
||||||
"1": "first person",
|
|
||||||
"2": "second person",
|
|
||||||
"3": "third person",
|
|
||||||
"A": "agent-like argument of canonical transitive verb",
|
|
||||||
"ABL": "ablative",
|
|
||||||
"ABS": "absolutive",
|
|
||||||
"ACC": "accusative",
|
|
||||||
"ADJ": "adjective",
|
|
||||||
"ADV": "adverb(ial)",
|
|
||||||
"AGR": "agreement",
|
|
||||||
"ALL": "allative",
|
|
||||||
"ANTIP": "antipassive",
|
|
||||||
"APPL": "applicative",
|
|
||||||
"ART": "article",
|
|
||||||
"AUX": "auxiliary",
|
|
||||||
"BEN": "benefactive",
|
|
||||||
"CAUS": "causative",
|
|
||||||
"CLF": "classifier",
|
|
||||||
"COM": "comitative",
|
|
||||||
"COMP": "complementizer",
|
|
||||||
"COMPL": "completive",
|
|
||||||
"COND": "conditional",
|
|
||||||
"COP": "copula",
|
|
||||||
"CVB": "converb",
|
|
||||||
"DAT": "dative",
|
|
||||||
"DECL": "declarative",
|
|
||||||
"DEF": "definite",
|
|
||||||
"DEM": "demonstrative",
|
|
||||||
"DET": "determiner",
|
|
||||||
"DIST": "distal",
|
|
||||||
"DISTR": "distributive",
|
|
||||||
"DU": "dual",
|
|
||||||
"DUR": "durative",
|
|
||||||
"ERG": "ergative",
|
|
||||||
"EXCL": "exclusive",
|
|
||||||
"F": "feminine",
|
|
||||||
"FOC": "focus",
|
|
||||||
"FUT": "future",
|
|
||||||
"GEN": "genitive",
|
|
||||||
"IMP": "imperative",
|
|
||||||
"INCL": "inclusive",
|
|
||||||
"IND": "indicative",
|
|
||||||
"INDF": "indefinite",
|
|
||||||
"INF": "infinitive",
|
|
||||||
"INS": "instrumental",
|
|
||||||
"INTR": "intransitive",
|
|
||||||
"IPFV": "imperfective",
|
|
||||||
"IRR": "irrealis",
|
|
||||||
"LOC": "locative",
|
|
||||||
"M": "masculine",
|
|
||||||
"N": "neuter",
|
|
||||||
"N-": [non- (e.g. #smallcaps[nsg] nonsingular, #smallcaps[npst] nonpast)],
|
|
||||||
"NEG": "negation, negative",
|
|
||||||
"NMLZ": "nominalizer/nominalization",
|
|
||||||
"NOM": "nominative",
|
|
||||||
"OBJ": "object",
|
|
||||||
"OBL": "oblique",
|
|
||||||
"P": "patient-like argument of canonical transitive verb",
|
|
||||||
"PASS": "passive",
|
|
||||||
"PFV": "perfective",
|
|
||||||
"PL": "plural",
|
|
||||||
"POSS": "possessive",
|
|
||||||
"PRED": "predicative",
|
|
||||||
"PRF": "perfect",
|
|
||||||
"PRS": "present",
|
|
||||||
"PROG": "progressive",
|
|
||||||
"PROH": "prohibitive",
|
|
||||||
"PROX": "proximal/proximate",
|
|
||||||
"PST": "past",
|
|
||||||
"PTCP": "participle",
|
|
||||||
"PURP": "purposive",
|
|
||||||
"Q": "question particle/marker",
|
|
||||||
"QUOT": "quotative",
|
|
||||||
"RECP": "reciprocal",
|
|
||||||
"REFL": "reflexive",
|
|
||||||
"REL": "relative",
|
|
||||||
"RES": "resultative",
|
|
||||||
"S": "single argument of canonical intransitive verb",
|
|
||||||
"SBJ": "subject",
|
|
||||||
"SBJV": "subjunctive",
|
|
||||||
"SG": "singular",
|
|
||||||
"TOP": "topic",
|
|
||||||
"TR": "transitive",
|
|
||||||
"VOC": "vocative",
|
|
||||||
)
|
|
||||||
|
|
||||||
// A dictionary used as a set to mark which abbreviations have been used by a call to
|
|
||||||
// `emit-abbreviation`. Each key in the dictionary is the string symbol of that abbreviation,
|
|
||||||
// and the value is always `true`.
|
|
||||||
#let used-abbreviations = state("leipzig-gloss-used-abbreviations", (:))
|
|
||||||
|
|
||||||
// Accepts a callback that accepts the state of the `used-abbreviations`
|
|
||||||
// dictionary at the end of the document. Also an additional debug parameter
|
|
||||||
#let with-used-abbreviations(callback) = {
|
|
||||||
context {
|
|
||||||
let final_used-abbreviations = used-abbreviations.final()
|
|
||||||
callback(final_used-abbreviations)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#let render-abbreviation(symbol) = smallcaps(lower(symbol))
|
|
||||||
|
|
||||||
// Public function. Given a symbol that is a string, emits
|
|
||||||
// the lowercase version of that string in smallcaps format, and adds
|
|
||||||
// its use to the `used-abbreviations` table
|
|
||||||
#let emit-abbreviation(symbol) = {
|
|
||||||
let mark_used(symbol) = {
|
|
||||||
used-abbreviations.update(cur => {
|
|
||||||
cur.insert(symbol, true)
|
|
||||||
cur
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
mark_used(symbol)
|
|
||||||
render-abbreviation(symbol)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#let p1 = emit-abbreviation("1")
|
|
||||||
#let p2 = emit-abbreviation("2")
|
|
||||||
#let p3 = emit-abbreviation("3")
|
|
||||||
#let A = emit-abbreviation("A")
|
|
||||||
#let abl = emit-abbreviation("ABL")
|
|
||||||
#let abs = emit-abbreviation("ABS")
|
|
||||||
#let acc = emit-abbreviation("ACC")
|
|
||||||
#let adj = emit-abbreviation("ADJ")
|
|
||||||
#let adv = emit-abbreviation("ADV")
|
|
||||||
#let agr = emit-abbreviation("AGR")
|
|
||||||
#let all = emit-abbreviation("ALL")
|
|
||||||
#let antip = emit-abbreviation("ANTIP")
|
|
||||||
#let appl = emit-abbreviation("APPL")
|
|
||||||
#let art = emit-abbreviation("ART")
|
|
||||||
#let aux = emit-abbreviation("AUX")
|
|
||||||
#let ben = emit-abbreviation("BEN")
|
|
||||||
#let caus = emit-abbreviation("CAUS")
|
|
||||||
#let clf = emit-abbreviation("CLF")
|
|
||||||
#let com = emit-abbreviation("COM")
|
|
||||||
#let comp = emit-abbreviation("COMP")
|
|
||||||
#let compl = emit-abbreviation("COMPL")
|
|
||||||
#let cond = emit-abbreviation("COND")
|
|
||||||
#let cop = emit-abbreviation("COP")
|
|
||||||
#let cvb = emit-abbreviation("CVB")
|
|
||||||
#let dat = emit-abbreviation("DAT")
|
|
||||||
#let decl = emit-abbreviation("DECL")
|
|
||||||
#let def = emit-abbreviation("DEF")
|
|
||||||
#let dem = emit-abbreviation("DEM")
|
|
||||||
#let det = emit-abbreviation("DET")
|
|
||||||
#let dist = emit-abbreviation("DIST")
|
|
||||||
#let distr = emit-abbreviation("DISTR")
|
|
||||||
#let du = emit-abbreviation("DU")
|
|
||||||
#let dur = emit-abbreviation("DUR")
|
|
||||||
#let erg = emit-abbreviation("ERG")
|
|
||||||
#let excl = emit-abbreviation("EXCL")
|
|
||||||
#let F = emit-abbreviation("F")
|
|
||||||
#let foc = emit-abbreviation("FOC")
|
|
||||||
#let fut = emit-abbreviation("FUT")
|
|
||||||
#let gen = emit-abbreviation("GEN")
|
|
||||||
#let imp = emit-abbreviation("IMP")
|
|
||||||
#let incl = emit-abbreviation("INCL")
|
|
||||||
#let ind = emit-abbreviation("IND")
|
|
||||||
#let indf = emit-abbreviation("INDF")
|
|
||||||
#let inf = emit-abbreviation("INF")
|
|
||||||
#let ins = emit-abbreviation("INS")
|
|
||||||
#let intr = emit-abbreviation("INTR")
|
|
||||||
#let ipfv = emit-abbreviation("IPFV")
|
|
||||||
#let irr = emit-abbreviation("IRR")
|
|
||||||
#let loc = emit-abbreviation("LOC")
|
|
||||||
#let M = emit-abbreviation("M")
|
|
||||||
#let N = emit-abbreviation("N")
|
|
||||||
#let non = emit-abbreviation("N-")
|
|
||||||
#let neg = emit-abbreviation("NEG")
|
|
||||||
#let nmlz = emit-abbreviation("NMLZ")
|
|
||||||
#let nom = emit-abbreviation("NOM")
|
|
||||||
#let obj = emit-abbreviation("OBJ")
|
|
||||||
#let obl = emit-abbreviation("OBL")
|
|
||||||
#let P = emit-abbreviation("P")
|
|
||||||
#let pass = emit-abbreviation("PASS")
|
|
||||||
#let pfv = emit-abbreviation("PFV")
|
|
||||||
#let pl = emit-abbreviation("PL")
|
|
||||||
#let poss = emit-abbreviation("POSS")
|
|
||||||
#let pred = emit-abbreviation("PRED")
|
|
||||||
#let prf = emit-abbreviation("PRF")
|
|
||||||
#let prs = emit-abbreviation("PRS")
|
|
||||||
#let prog = emit-abbreviation("PROG")
|
|
||||||
#let proh = emit-abbreviation("PROH")
|
|
||||||
#let prox = emit-abbreviation("PROX")
|
|
||||||
#let pst = emit-abbreviation("PST")
|
|
||||||
#let ptcp = emit-abbreviation("PTCP")
|
|
||||||
#let purp = emit-abbreviation("PURP")
|
|
||||||
#let Q = emit-abbreviation("Q")
|
|
||||||
#let quot = emit-abbreviation("QUOT")
|
|
||||||
#let recp = emit-abbreviation("RECP")
|
|
||||||
#let refl = emit-abbreviation("REFL")
|
|
||||||
#let rel = emit-abbreviation("REL")
|
|
||||||
#let res = emit-abbreviation("RES")
|
|
||||||
#let S = emit-abbreviation("S")
|
|
||||||
#let sbj = emit-abbreviation("SBJ")
|
|
||||||
#let sbjv = emit-abbreviation("SBJV")
|
|
||||||
#let sg = emit-abbreviation("SG")
|
|
||||||
#let top = emit-abbreviation("TOP")
|
|
||||||
#let tr = emit-abbreviation("TR")
|
|
||||||
#let voc = emit-abbreviation("VOC")
|
|
||||||
|
|
Binary file not shown.
@ -1,505 +0,0 @@
|
|||||||
#set document(title: "typst leipzig-glossing documentation")
|
|
||||||
#import "leipzig-gloss.typ": abbreviations, example, example-count, gloss, numbered-example
|
|
||||||
|
|
||||||
#set heading(numbering: "1.")
|
|
||||||
|
|
||||||
#show link: x => underline[*#x*]
|
|
||||||
|
|
||||||
#let codeblock(contents, addl-bindings: (:), unevaled-first-line: none) = {
|
|
||||||
let full-contents = if unevaled-first-line != none {
|
|
||||||
unevaled-first-line + "\n" + contents
|
|
||||||
} else {
|
|
||||||
contents
|
|
||||||
}
|
|
||||||
|
|
||||||
block(stroke: 0.5pt + black, inset: 4pt, width: 100%, breakable: false)[
|
|
||||||
#eval(contents, mode: "markup", scope: (gloss: gloss, example: example, numbered-example: numbered-example) + addl-bindings)
|
|
||||||
#block(fill: luma(230), inset: 8pt, radius: 4pt, breakable: false, width: 100%, raw(full-contents, lang: "typst"))
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
||||||
// Abbreviations used in this document
|
|
||||||
|
|
||||||
#import abbreviations: poss, prog, sg, pl, sbj, obj, fut, neg, obl, gen, com, ins, all, pst, inf, indf, def, dem, pred
|
|
||||||
#import abbreviations: art, dat, du, A, P, prf
|
|
||||||
|
|
||||||
#let fmnt = abbreviations.emit-abbreviation("FMNT")
|
|
||||||
|
|
||||||
#align(center)[#text(17pt)[Typst `leipzig-glossing` Documentation]]
|
|
||||||
|
|
||||||
= Introduction
|
|
||||||
|
|
||||||
Interlinear morpheme-by-morpheme glosses are common in linguistic texts to give
|
|
||||||
information about the meanings of individual words and morphemes in the
|
|
||||||
language being studied. A set of conventions called the *Leipzig Glossing Rules*
|
|
||||||
was developed to give linguists a general set of standards and principles for
|
|
||||||
how to format these glosses. The most recent version of these rules can be
|
|
||||||
found in PDF form at
|
|
||||||
#link("https://www.eva.mpg.de/lingua/pdf/Glossing-Rules.pdf")[this link],
|
|
||||||
provided by the Department of Linguistics at the Max Planck Institute for
|
|
||||||
Evolutionary Anthropology.
|
|
||||||
|
|
||||||
There is a staggering variety of LaTex packages designed to properly align and
|
|
||||||
format glosses (including `gb4e`, `ling-macros`, `linguex`, `expex`, and
|
|
||||||
probably even more). These modules vary in the complexity of their syntax and
|
|
||||||
the amount of control they give to the user of various aspects of formatting.
|
|
||||||
The `typst-leipzig-glossing` module is designed to provide utilities for
|
|
||||||
creating aligned Leipzig-style glosses in Typst, while keeping the syntax as
|
|
||||||
intuitive as possible and allowing users as much control over how their glosses
|
|
||||||
look as is feasible.
|
|
||||||
|
|
||||||
This PDF will show examples of the module's functionality and detail relevant
|
|
||||||
parameters. For more information or to inform devs of a bug or other issue,
|
|
||||||
visit the module's Github repository
|
|
||||||
#link("https://github.com/neunenak/typst-leipzig-glossing")
|
|
||||||
|
|
||||||
#show raw: x => highlight(fill: luma(230), extent: 1pt)[#x]
|
|
||||||
|
|
||||||
= Basic glossing functionality
|
|
||||||
|
|
||||||
As a first example, here is a gloss of a text in Georgian, along with the Typst code used to generate it:
|
|
||||||
|
|
||||||
#codeblock(
|
|
||||||
"#gloss(
|
|
||||||
header: [from \"Georgian and the Unaccusative Hypothesis\", Alice Harris, 1982],
|
|
||||||
source: ([ბავშვ-ი], [ატირდა]),
|
|
||||||
transliteration: ([bavšv-i], [aṭirda]),
|
|
||||||
morphemes: ([child-#smallcaps[nom]], [3S/cry/#smallcaps[incho]/II]),
|
|
||||||
translation: [The child burst out crying],
|
|
||||||
)", unevaled-first-line: "#import \"leipzig-gloss.typ\": gloss")
|
|
||||||
|
|
||||||
The function `gloss()` typesets _bare_ interlinear glosses (including styling, see @styling and @additional-lines). Normally when adding linguistic examples use the `example()` function, which calls `gloss()` internally and includes functionality that has to do with linguistic examples: numbering, labelling/referencing and sub-examples. `gloss()` is to be used when only the basic function of typesetting interlinear glosses is needed. Unlike `gloss()`, the function `example()` does not take the different parameters directly, but takes a list of dictionaries whose keys and values correspond to `gloss()`’s parameters (with added options such as `label` and `numbering`). It also indents the text even when numbering is not enabled:
|
|
||||||
|
|
||||||
#codeblock(
|
|
||||||
"#example(
|
|
||||||
(
|
|
||||||
header: [from \"Georgian and the Unaccusative Hypothesis\", Alice Harris, 1982],
|
|
||||||
source: ([ბავშვ-ი], [ატირდა]),
|
|
||||||
transliteration: ([bavšv-i], [aṭirda]),
|
|
||||||
morphemes: ([child-#smallcaps[nom]], [3S/cry/#smallcaps[incho]/II]),
|
|
||||||
translation: [The child burst out crying],
|
|
||||||
)
|
|
||||||
)")
|
|
||||||
|
|
||||||
== Styling <styling>
|
|
||||||
|
|
||||||
Each of the aforementioned text parameters has a corresponding style parameter,
|
|
||||||
formed by adding `-style` to its name: `header-style`, `source-style`,
|
|
||||||
`transliteration-style`, `morphemes-style`, and `translation-style`. These parameters
|
|
||||||
allow you to specify formatting that should be applied to each entire line of
|
|
||||||
the gloss. This is particularly useful for the aligned gloss itself, since
|
|
||||||
otherwise one would have to modify each content item in the list individually.
|
|
||||||
|
|
||||||
In addition to these parameters, Typst’s usual content formatting can be applied
|
|
||||||
to or within any given content block in the gloss. Formatting applied in this
|
|
||||||
way will override any contradictory line-level formatting.
|
|
||||||
|
|
||||||
#codeblock(
|
|
||||||
"#example(
|
|
||||||
(
|
|
||||||
header: [This text is about eating your head.],
|
|
||||||
header-style: text.with(weight: \"bold\", fill: green),
|
|
||||||
source: (text(fill:black)[I'm], [eat-ing], [your], [head]),
|
|
||||||
source-style: text.with(style: \"italic\", fill: red),
|
|
||||||
morphemes: ([1#sg.#sbj\=to.be], text(fill:black)[eat-#prog], [2#sg.#poss], [head]),
|
|
||||||
morphemes-style: text.with(fill: blue),
|
|
||||||
translation: text(weight: \"bold\")[I'm eating your head!],
|
|
||||||
)
|
|
||||||
)", addl-bindings: (prog: prog, sbj: sbj, poss: poss, sg: sg))
|
|
||||||
|
|
||||||
//TODO add `line-styles` param
|
|
||||||
|
|
||||||
An example for English which exhibits some additional styling, and uses imports from another file
|
|
||||||
for common glossing abbreviations:
|
|
||||||
|
|
||||||
#codeblock(
|
|
||||||
"#example(
|
|
||||||
(
|
|
||||||
source: ([I'm], [eat-ing], [your], [head]),
|
|
||||||
source-style: (item) => text(fill: red)[#item],
|
|
||||||
morphemes: ([1#sg.#sbj\=to.be], [eat-#prog], [2#sg.#poss], [head]),
|
|
||||||
morphemes-style: text.with(size: 10pt, fill: blue),
|
|
||||||
translation: text(weight: \"semibold\")[I'm eating your head!],
|
|
||||||
translation-style: (item) => [\"#item\"],
|
|
||||||
)
|
|
||||||
)
|
|
||||||
", addl-bindings: (poss: poss, prog: prog, sg: sg, sbj: sbj))
|
|
||||||
|
|
||||||
|
|
||||||
The `gloss()` function has three pre-defined parameters for glossing levels:
|
|
||||||
`source`, `transliteration`, and `morphemes`. It also has two parameters
|
|
||||||
for unaligned text: `header` for text that precedes the gloss, and
|
|
||||||
`translation` for text that follows the gloss.
|
|
||||||
|
|
||||||
|
|
||||||
The `morphemes` param can be skipped, if you just want to provide a source
|
|
||||||
text and translation, without a gloss:
|
|
||||||
|
|
||||||
#codeblock(
|
|
||||||
"#example(
|
|
||||||
(
|
|
||||||
source: ([Trato de entender, debo comprender, qué es lo que ha hecho conmigo],),
|
|
||||||
source-style: emph,
|
|
||||||
translation: [I try to understand, I must comprehend, what she has done with me],
|
|
||||||
)
|
|
||||||
)
|
|
||||||
")
|
|
||||||
|
|
||||||
|
|
||||||
Note that it is still necessary to wrap the `source` argument in an array of length one.
|
|
||||||
|
|
||||||
Here is an example of a lengthy gloss that forces a line break:
|
|
||||||
|
|
||||||
// adapted from https://brill.com/fileasset/downloads_static/static_publishingbooks_formatting_glosses_linguistic_examples.pdf
|
|
||||||
#codeblock(
|
|
||||||
"#example(
|
|
||||||
(
|
|
||||||
source: ([Ich],[arbeite],[ein],[Jahr],[um],[das],[Geld], [zu],[verdienen,],[das], [dein],[Bruder], [an],[einem],[Wochenende],[ausgibt.]),
|
|
||||||
source-style: text.with(weight: \"bold\"),
|
|
||||||
morphemes: ([I], [work],[ one], [year],[to],[the],[money],[to],[earn,], [that],[your],[brother],[on],[one], [weekend], [spends.]),
|
|
||||||
translation: [\"I work one year to earn the money that your brother spends in one weekend\"]
|
|
||||||
)
|
|
||||||
)", addl-bindings: (poss: poss, prog: prog, sg: sg, sbj: sbj))
|
|
||||||
|
|
||||||
== Additional lines <additional-lines>
|
|
||||||
|
|
||||||
To add more than three glossing lines, there is an additional parameter
|
|
||||||
`additional-lines` that can take a list of arbitrarily many more glossing
|
|
||||||
lines, which will appear below those specified in the aforementioned
|
|
||||||
parameters:
|
|
||||||
|
|
||||||
#codeblock(
|
|
||||||
"#example(
|
|
||||||
(
|
|
||||||
header: [Hunzib (van den Berg 1995:46)],
|
|
||||||
source: ([ождиг],[хо#super[н]хе],[мукъер]),
|
|
||||||
transliteration: ([oʒdig],[χõχe],[muqʼer]),
|
|
||||||
morphemes: ([ož-di-g],[xõxe],[m-uq'e-r]),
|
|
||||||
additional-lines: (
|
|
||||||
([boy-#smallcaps[obl]-#smallcaps[ad]], [tree(#smallcaps[g4])], [#smallcaps[g4]-bend-#smallcaps[pret]]),
|
|
||||||
([at boy], [tree], [bent]),
|
|
||||||
),
|
|
||||||
translation: [\"Because of the boy, the tree bent.\"]
|
|
||||||
)
|
|
||||||
)
|
|
||||||
")
|
|
||||||
|
|
||||||
== Sub-examples
|
|
||||||
|
|
||||||
Sub-examples can be achieved by adding more dictionaries of glossing fields, separated by commas.
|
|
||||||
A global `header` field for the set can be added.
|
|
||||||
|
|
||||||
#codeblock(
|
|
||||||
"#example(
|
|
||||||
header: [Coptic; transliterated and glossed based on _Coptic in 20 lessons_ (2007) by Layton Bently (§~28)],
|
|
||||||
(
|
|
||||||
header: [Indefinite articles],
|
|
||||||
source: ([hen-maein], [mn-hen-špêre]),
|
|
||||||
morphemes: ([#indf.#pl\-sign], [with-#indf.#pl\-wonder]),
|
|
||||||
translation: [signs and wonders]
|
|
||||||
),
|
|
||||||
(
|
|
||||||
header: [Definite articles],
|
|
||||||
source: ([m-maein], [mn-ne-špêre]),
|
|
||||||
morphemes: ([#def.#pl\-sign], [with-#def.#pl\-wonder]),
|
|
||||||
translation: [the signs and the wonders]
|
|
||||||
),
|
|
||||||
(
|
|
||||||
header: [Definite pronouns],
|
|
||||||
source: ([nei-maein], [mn-nei-špêre]),
|
|
||||||
morphemes: ([#dem.#pl\-sign], [with-#dem.#pl\-wonder]),
|
|
||||||
translation: [these signs and these wonders]
|
|
||||||
),
|
|
||||||
)
|
|
||||||
", addl-bindings: (indf: indf, pl: pl, sg: sg, def: def, dem: dem))
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//TODO add a custom numbering system that can handle example 18a-c of Kartvelian Morphosyntax and Number Agreement
|
|
||||||
== Numbering Glosses
|
|
||||||
|
|
||||||
The `example()` function takes a boolean parameter `numbering` which will add an incrementing
|
|
||||||
count to each gloss. A function `numbered-example` is exported for convenience; this is
|
|
||||||
defined as simply `#let numbered-example = example.with(numbering: true)`, and is called with the
|
|
||||||
same arguments as `example()`:
|
|
||||||
|
|
||||||
|
|
||||||
#codeblock(
|
|
||||||
"#example(
|
|
||||||
(
|
|
||||||
source: ([გვ-ფრცქვნ-ი],),
|
|
||||||
transliteration: ([gv-prtskvn-i],),
|
|
||||||
morphemes: ([1#pl.#obj\-peel-#fmnt],),
|
|
||||||
translation: \"You peeled us\",
|
|
||||||
),
|
|
||||||
numbering: true,
|
|
||||||
)
|
|
||||||
|
|
||||||
#numbered-example(
|
|
||||||
(
|
|
||||||
source: ([მ-ფრცქვნ-ი],),
|
|
||||||
transliteration: ([m-prtskvn-i],),
|
|
||||||
morphemes: ([1#sg.#obj\-peel-#fmnt],),
|
|
||||||
translation: \"You peeled me\",
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
", addl-bindings: (pl: pl, obj: obj, sg: sg, fmnt: fmnt))
|
|
||||||
|
|
||||||
The displayed number for numbered glosses is iterated for each numbered gloss
|
|
||||||
that appears throughout the document. Unnumbered glosses do not increment the
|
|
||||||
counter for the numbered glosses.
|
|
||||||
|
|
||||||
The gloss count is controlled by the Typst counter variable `example-count`. This
|
|
||||||
variable can be imported from the `leipzig-gloss` package and manipulated using the
|
|
||||||
standard Typst counter functions to control gloss numbering:
|
|
||||||
|
|
||||||
#codeblock(
|
|
||||||
"#example-count.update(20)
|
|
||||||
|
|
||||||
#numbered-example(
|
|
||||||
(
|
|
||||||
header: [from _Standard Basque: A Progressive Grammar_ by Rudolf de Rijk, quoting P. Charriton],
|
|
||||||
source: ([Bada beti guregan zorion handi baten nahia.],),
|
|
||||||
translation: [There always is in us a will for a great happiness.],
|
|
||||||
)
|
|
||||||
)", addl-bindings: (example-count: example-count))
|
|
||||||
|
|
||||||
References to individual examples can be achieved using the `label` argument and the referencing mechanism of Typst:
|
|
||||||
|
|
||||||
#codeblock(
|
|
||||||
"See @sorcerers:
|
|
||||||
|
|
||||||
#numbered-example(
|
|
||||||
(
|
|
||||||
header: [Middle Welsh; modified from _Grammatical number in Welsh_ (1999) by Silva Nurmio (§~2.1.1)],
|
|
||||||
source: ([ac], [ny], [allvs], [y], [dewinyon], [atteb], [idav]),
|
|
||||||
morphemes: ([and], [#neg], [be_able.#smallcaps[pret].3#sg], [#smallcaps[def]], [sorcerer.#pl], [answer.#smallcaps[inf]], [to.3#sg.#smallcaps[m]]),
|
|
||||||
translation: [and the sorcerers could not answer him],
|
|
||||||
),
|
|
||||||
label: \"sorcerers\",
|
|
||||||
label-supplement: [Example]
|
|
||||||
)
|
|
||||||
|
|
||||||
As we have seen in @sorcerers, […].", addl-bindings: (neg: neg, sg: sg, pl: pl))
|
|
||||||
|
|
||||||
Labelling uses the Typst #link("https://typst.app/docs/reference/model/figure/")[figure] document element. The `label-supplement`
|
|
||||||
parameter fills in the `suppliment` parameter of a `figure`, which is `[example]` by default.
|
|
||||||
Note that `label` and `label-supplement` are top-level arguments of `example()` and `numbered-example()`, not of the interlinear glosses surrounded by `(` and `)`.
|
|
||||||
|
|
||||||
Labelling of sub-examples is possible as well, using the same `label` and `label-supplement` fields but within the parentheses surrounding the sub-example in question.
|
|
||||||
|
|
||||||
#codeblock(
|
|
||||||
"#numbered-example(
|
|
||||||
header: [Hausa; from _Toward a functional typology of adpositions_ (2022) by Zygmunt Frajzyngier (§~3.2)],
|
|
||||||
label: \"hausa\",
|
|
||||||
(
|
|
||||||
source: ([àkwai], [mutā̀nè], [dà], [yawā̀], [a], [kanṑ]),
|
|
||||||
morphemes: ([exist], [People], [#smallcaps[assc]], [many], [#pred], [Kano]),
|
|
||||||
translation: [There are a lot of people in Kano.],
|
|
||||||
label: \"people\"
|
|
||||||
),
|
|
||||||
(
|
|
||||||
source: ([àkwai], [makar̃antā], [a], [nan], [gàrin]),
|
|
||||||
morphemes: ([exist], [school], [#pred], [#dem], [town]),
|
|
||||||
translation: [There is a school in this town.],
|
|
||||||
label: \"school\",
|
|
||||||
),
|
|
||||||
)
|
|
||||||
|
|
||||||
In @hausa there are two sub-examples: @people deals with people and @school with a school.
|
|
||||||
", addl-bindings: (pred: pred, dem: dem))
|
|
||||||
|
|
||||||
= Standard Abbreviations
|
|
||||||
|
|
||||||
The Leipzig Glossing Rules define a commonly-used set of short abbreviations
|
|
||||||
for grammatical terms used in glosses, such as #abbreviations.acc for
|
|
||||||
"accusative (case)", or #abbreviations.ptcp for "participle" (see "Appendix:
|
|
||||||
List of Standard Abbreviations in the Leipzig Glossing Rules document)
|
|
||||||
|
|
||||||
|
|
||||||
By convention, these are typeset using #smallcaps[smallcaps]. This package
|
|
||||||
contains a module value `abbreviations`. Individual abbreviations may be
|
|
||||||
accessed either with Typst field access notation or by importing them from
|
|
||||||
`abbreviations`:
|
|
||||||
|
|
||||||
|
|
||||||
#codeblock(
|
|
||||||
"#import abbreviations: obl, sg, prf
|
|
||||||
|
|
||||||
#example(
|
|
||||||
(
|
|
||||||
header: [(from _Why Caucasian Languages?_, by Bernard Comrie, in _Endangered Languages of the Caucasus and Beyond_)],
|
|
||||||
source: ([\[qálɐ-m], [∅-kw’-á\]], [ɬ’ə́-r]),
|
|
||||||
morphemes: ([city-#obl], [3#sg\-go-#prf], [man-#abbreviations.abs]),
|
|
||||||
translation: \"The man who went to the city.\"
|
|
||||||
)
|
|
||||||
)", addl-bindings: (abbreviations: abbreviations), unevaled-first-line: "#import \"leipzig-gloss.typ\": abbreviations")
|
|
||||||
|
|
||||||
|
|
||||||
The full list of abbreviations is as follows:
|
|
||||||
|
|
||||||
== Full list of abbreviations
|
|
||||||
|
|
||||||
#{
|
|
||||||
for (abbreviation, description) in abbreviations.standard-abbreviations {
|
|
||||||
[#abbreviations.render-abbreviation(abbreviation) - #raw(lower(abbreviation)) - #description ]
|
|
||||||
linebreak()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
== Custom abbreviations
|
|
||||||
|
|
||||||
Custom abbreviations may be defined using the `abbreviations.emit-abbreviation` function:
|
|
||||||
|
|
||||||
#codeblock(
|
|
||||||
"#import abbreviations: obl, sg, prf, fut, emit-abbreviation
|
|
||||||
|
|
||||||
#let ts = emit-abbreviation(\"TS\")
|
|
||||||
|
|
||||||
#example(
|
|
||||||
(
|
|
||||||
header: [(from _Georgian: A Structural Reference Grammar_, by George Hewitt)],
|
|
||||||
source: ([g-nax-av-en],),
|
|
||||||
morphemes: ([you#sub[2]-see(#fut)#sub[4]-#ts#sub[7]-they#sub[11]],),
|
|
||||||
translation: \"they will see you\",
|
|
||||||
)
|
|
||||||
)", addl-bindings: (abbreviations: abbreviations), unevaled-first-line: "#import \"leipzig-gloss.typ\": abbreviations")
|
|
||||||
|
|
||||||
== Building used-abbreviations pages
|
|
||||||
|
|
||||||
A user of `leipzig-glossing` might wish to generate an introductory page
|
|
||||||
displaying which abbreviations were actually used in the document. The
|
|
||||||
`abbreviations.with-used-abbreviations` function may be used for this purpose;
|
|
||||||
see the `abbreviations-used-example.typ` file in `leipzig-glossing` source for an example.
|
|
||||||
|
|
||||||
= Further Example Glosses
|
|
||||||
|
|
||||||
These are the first twelve example glosses given in #link("https://www.eva.mpg.de/lingua/pdf/Glossing-Rules.pdf").
|
|
||||||
along with the Typst markup needed to generate them:
|
|
||||||
|
|
||||||
#{
|
|
||||||
example-count.update(0)
|
|
||||||
}
|
|
||||||
|
|
||||||
#codeblock(
|
|
||||||
"#numbered-example(
|
|
||||||
(
|
|
||||||
header: [Indonesian (Sneddon 1996:237)],
|
|
||||||
source: ([Mereka], [di], [Jakarta], [sekarang.]),
|
|
||||||
morphemes: ([they], [in], [Jakarta], [now]),
|
|
||||||
translation: \"They are in Jakarta now\",
|
|
||||||
)
|
|
||||||
)")
|
|
||||||
|
|
||||||
#codeblock(
|
|
||||||
"#numbered-example(
|
|
||||||
(
|
|
||||||
header: [Lezgian (Haspelmath 1993:207)],
|
|
||||||
source: ([Gila], [abur-u-n], [ferma], [hamišaluǧ], [güǧüna], [amuq’-da-č.]),
|
|
||||||
morphemes: ([now], [they-#obl\-#gen], [farm], [forever], [behind], [stay-#fut\-#neg]),
|
|
||||||
translation: \"Now their farm will not stay behind forever.\",
|
|
||||||
)
|
|
||||||
)", addl-bindings: (fut: fut, neg: neg, obl: obl, gen:gen))
|
|
||||||
|
|
||||||
#codeblock(
|
|
||||||
"#numbered-example(
|
|
||||||
(
|
|
||||||
header: [West Greenlandic (Fortescue 1984:127)],
|
|
||||||
source: ([palasi=lu], [niuirtur=lu]),
|
|
||||||
morphemes: ([priest=and], [shopkeeper=and]),
|
|
||||||
translation: \"both the priest and the shopkeeper\",
|
|
||||||
)
|
|
||||||
)")
|
|
||||||
|
|
||||||
#codeblock(
|
|
||||||
"#numbered-example(
|
|
||||||
(
|
|
||||||
header: [Hakha Lai],
|
|
||||||
source: ([a-nii -láay],),
|
|
||||||
morphemes: ([3#sg\-laugh-#fut],),
|
|
||||||
translation: [s/he will laugh],
|
|
||||||
)
|
|
||||||
)", addl-bindings: (sg: sg, fut: fut))
|
|
||||||
|
|
||||||
#codeblock(
|
|
||||||
"#numbered-example(
|
|
||||||
(
|
|
||||||
header: [Russian],
|
|
||||||
source: ([My], [s], [Marko], [poexa-l-i], [avtobus-om], [v], [Peredelkino]),
|
|
||||||
morphemes: ([1#pl], [#com], [Marko], [go-#pst\-#pl], [bus-#ins], [#all], [Peredelkino]),
|
|
||||||
additional-lines: (([we], [with], [Marko], [go-#pst\-#pl], [bus-by], [to], [Peredelkino]),),
|
|
||||||
translation: \"Marko and I went to Perdelkino by bus\",
|
|
||||||
)
|
|
||||||
)", addl-bindings: (com: com, pl: pl, ins: ins, all: all, pst:pst))
|
|
||||||
|
|
||||||
#codeblock(
|
|
||||||
"#numbered-example(
|
|
||||||
(
|
|
||||||
header: [Turkish],
|
|
||||||
source: ([çık-mak],),
|
|
||||||
morphemes: ([come.out-#inf],),
|
|
||||||
translation: \"to come out\",
|
|
||||||
)
|
|
||||||
)", addl-bindings: (inf: inf))
|
|
||||||
|
|
||||||
#codeblock(
|
|
||||||
"#numbered-example(
|
|
||||||
(
|
|
||||||
header: [Latin],
|
|
||||||
source: ([insul-arum],),
|
|
||||||
morphemes: ([island-#gen\-#pl],),
|
|
||||||
translation: \"of the islands\",
|
|
||||||
)
|
|
||||||
)", addl-bindings: (gen:gen, pl: pl))
|
|
||||||
|
|
||||||
#codeblock(
|
|
||||||
"#numbered-example(
|
|
||||||
(
|
|
||||||
header: [French],
|
|
||||||
source: ([aux], [chevaux]),
|
|
||||||
morphemes: ([to-#art\-#pl],[horse.#pl]),
|
|
||||||
translation: \"to the horses\",
|
|
||||||
)
|
|
||||||
)",addl-bindings: (art:art, pl:pl))
|
|
||||||
|
|
||||||
#codeblock(
|
|
||||||
"#numbered-example(
|
|
||||||
(
|
|
||||||
header: [German],
|
|
||||||
source: ([unser-n], [Väter-n]),
|
|
||||||
morphemes: ([our-#dat\-#pl],[father.#pl\-#dat.#pl]),
|
|
||||||
translation: \"to our fathers\",
|
|
||||||
)
|
|
||||||
)", addl-bindings: (dat:dat, pl:pl))
|
|
||||||
|
|
||||||
#codeblock(
|
|
||||||
"#numbered-example(
|
|
||||||
(
|
|
||||||
header: [Hittite (Lehmann 1982:211)],
|
|
||||||
source: ([n=an], [apedani], [mehuni],[essandu.]),
|
|
||||||
morphemes: ([#smallcaps[conn]=him], [that.#dat.#sg], [time.#dat.#sg], [eat.they.shall]),
|
|
||||||
translation: \"They shall celebrate him on that date\",
|
|
||||||
)
|
|
||||||
)", addl-bindings: (pl:pl, sg:sg, dat:dat))
|
|
||||||
|
|
||||||
#codeblock(
|
|
||||||
"#numbered-example(
|
|
||||||
(
|
|
||||||
header: [Jaminjung (Schultze-Berndt 2000:92)],
|
|
||||||
source: ([nanggayan], [guny-bi-yarluga?]),
|
|
||||||
morphemes: ([who], [2#du.#A.3#sg.#P\-#fut\-poke]),
|
|
||||||
translation: \"Who do you two want to spear?\",
|
|
||||||
)
|
|
||||||
)", addl-bindings: (du:du, sg:sg, fut:fut, A:A, P:P))
|
|
||||||
|
|
||||||
|
|
||||||
#codeblock("
|
|
||||||
#numbered-example(
|
|
||||||
(
|
|
||||||
header: [Turkish (cf. 6)],
|
|
||||||
source: ([çık-mak],),
|
|
||||||
morphemes: ([come_out-#inf],),
|
|
||||||
translation: ['to come out'],
|
|
||||||
)
|
|
||||||
)", addl-bindings: (inf: inf))
|
|
9
justfile
9
justfile
@ -2,10 +2,5 @@ default:
|
|||||||
just --list
|
just --list
|
||||||
|
|
||||||
|
|
||||||
# Build the leipzig-glossing documentation PDF
|
build-example:
|
||||||
build-doc:
|
typst compile leipzig-gloss-examples.typ
|
||||||
typst compile documentation.typ
|
|
||||||
|
|
||||||
# Build the abbbreviations-used example
|
|
||||||
build-abbreviations-example:
|
|
||||||
typst compile abbreviations-used-example.typ
|
|
||||||
|
BIN
leipzig-gloss-examples.pdf
Normal file
BIN
leipzig-gloss-examples.pdf
Normal file
Binary file not shown.
282
leipzig-gloss-examples.typ
Normal file
282
leipzig-gloss-examples.typ
Normal file
@ -0,0 +1,282 @@
|
|||||||
|
#import "leipzig-gloss.typ": gloss, numbered_gloss, gloss_count
|
||||||
|
#import "linguistic-abbreviations.typ": *
|
||||||
|
|
||||||
|
#show link: x => underline[*#x*]
|
||||||
|
//#show raw: x => text(fill: rgb("#43464b"))[#x]
|
||||||
|
|
||||||
|
#let codeblock(contents) = block(fill: luma(230), inset: 8pt, radius: 4pt, breakable: false, contents)
|
||||||
|
|
||||||
|
|
||||||
|
= Introduction
|
||||||
|
|
||||||
|
Interlinear morpheme-by-morpheme glosses are common in linguistic texts to give
|
||||||
|
information about the meanings of individual words and morphemes in the
|
||||||
|
language being studied. A set of conventions called the *Leipzig Glossing Rules*
|
||||||
|
was developed to give linguists a general set of standards and principles for
|
||||||
|
how to format these glosses. The most recent version of these rules can be
|
||||||
|
found in PDF form at
|
||||||
|
#link("https://www.eva.mpg.de/lingua/pdf/Glossing-Rules.pdf")[this link],
|
||||||
|
provided by the Department of Linguistics at the Max Planck Institute for
|
||||||
|
Evolutionary Anthropology.
|
||||||
|
|
||||||
|
There is a staggering variety of LaTex packages designed to properly align and
|
||||||
|
format glosses (including `gb4e`, `ling-macros`, `linguex`, `expex`, and
|
||||||
|
probably even more). These modules vary in the complexity of their syntax and
|
||||||
|
the amount of control they give to the user of various aspects of formatting.
|
||||||
|
The `typst-leipzig-glossing` module is designed to provide utilities for
|
||||||
|
creating aligned Leipzig-style glosses in Typst, while keeping the syntax as
|
||||||
|
intuitive as possible and allowing users as much control over how their glosses
|
||||||
|
look as is feasible.
|
||||||
|
|
||||||
|
This PDF will show examples of the module's functionality and detail relevant
|
||||||
|
parameters. For more information or to inform devs of a bug or other issue,
|
||||||
|
visit the module's Github repository
|
||||||
|
#link("https://github.com/neunenak/typst-leipzig-glossing")[neunenak/typst-leipzig-glossing].
|
||||||
|
|
||||||
|
= Basic glossing functionality
|
||||||
|
|
||||||
|
|
||||||
|
As a first example, here is a gloss of a text in Georgian, along with the Typst code used to generate it:
|
||||||
|
|
||||||
|
|
||||||
|
#gloss(
|
||||||
|
header_text: [from "Georgian and the Unaccusative Hypothesis", Alice Harris, 1982],
|
||||||
|
source_text: ([ბავშვ-ი], [ატირდა]),
|
||||||
|
transliteration: ([bavšv-i], [aṭirda]),
|
||||||
|
morphemes: ([child-#smallcaps[nom]], [3S/cry/#smallcaps[incho]/II]),
|
||||||
|
translation: [The child burst out crying],
|
||||||
|
)
|
||||||
|
|
||||||
|
#codeblock[
|
||||||
|
```typst
|
||||||
|
#gloss(
|
||||||
|
header_text: [from "Georgian and the Unaccusative Hypothesis", Alice Harris, 1982],
|
||||||
|
source_text: ([ბავშვ-ი], [ატირდა]),
|
||||||
|
transliteration: ([bavšv-i], [aṭirda]),
|
||||||
|
morphemes: ([child-#smallcaps[nom]], [3S/cry/#smallcaps[incho]/II]),
|
||||||
|
translation: [The child burst out crying],
|
||||||
|
)
|
||||||
|
```
|
||||||
|
]
|
||||||
|
|
||||||
|
And an example for English which exhibits some additional styling, and uses imports from another file
|
||||||
|
for common glossing abbreviations:
|
||||||
|
|
||||||
|
#gloss(
|
||||||
|
source_text: ([I'm], [eat-ing], [your], [head]),
|
||||||
|
source_text_style: (item) => text(fill: red)[#item],
|
||||||
|
morphemes: ([1#sg.#sbj\=to.be], [eat-#prog], [2#sg.#pos], [head]),
|
||||||
|
morphemes_style: text.with(fill: blue),
|
||||||
|
translation: text(weight: "semibold")[I'm eating your head!],
|
||||||
|
)
|
||||||
|
|
||||||
|
#codeblock[
|
||||||
|
```typst
|
||||||
|
#import "linguistic-abbreviations.typ": *
|
||||||
|
|
||||||
|
#gloss(
|
||||||
|
source_text: ([I'm], [eat-ing], [your], [head]),
|
||||||
|
source_text_style: (item) => text(fill: red)[#item],
|
||||||
|
morphemes: ([1#sg.#subj\=to.be], [eat-#prog], [2#sg.#pos], [head]),
|
||||||
|
morphemes_style: text.with(fill: blue),
|
||||||
|
translation: text(weight: "semibold")[I'm eating your head!],
|
||||||
|
)
|
||||||
|
```
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
The `#gloss` function has three pre-defined parameters for glossing levels:
|
||||||
|
`source_text`, `transliteration`, and `morphemes`. It also has two parameters
|
||||||
|
for unaligned text: `header_text` for text that precedes the gloss, and
|
||||||
|
`translation` for text that follows the gloss.
|
||||||
|
|
||||||
|
If one wishes to add more than three glossing lines, there is an additional
|
||||||
|
parameter `additional_gloss_lines` that can take a list of arbitrarily many more glossing
|
||||||
|
lines, which will appear below those specified in the aforementioned
|
||||||
|
parameters:
|
||||||
|
|
||||||
|
#gloss(
|
||||||
|
header_text: [Hunzib (van den Berg 1995:46)],
|
||||||
|
source_text: ([ождиг],[хо#super[н]хе],[мукъер]),
|
||||||
|
transliteration: ([oʒdig],[χõχe],[muqʼer]),
|
||||||
|
morphemes: ([ož-di-g],[xõxe],[m-uq'e-r]),
|
||||||
|
additional_gloss_lines: (
|
||||||
|
([boy-#smallcaps[obl]-#smallcaps[ad]], [tree(#smallcaps[g4])], [#smallcaps[g4]-bend-#smallcaps[pret]]),
|
||||||
|
([at boy], [tree], [bent]),
|
||||||
|
),
|
||||||
|
translation: ["Because of the boy, the tree bent."]
|
||||||
|
)
|
||||||
|
|
||||||
|
#codeblock[
|
||||||
|
```typst
|
||||||
|
#gloss(
|
||||||
|
header_text: [Hunzib (van den Berg 1995:46)],
|
||||||
|
source_text: ([ождиг],[хо#super[н]хе],[мукъер]),
|
||||||
|
transliteration: ([oʒdig],[χõχe],[muqʼer]),
|
||||||
|
morphemes: ([ož-di-g],[xõxe],[m-uq'e-r]),
|
||||||
|
additional_gloss_lines: (
|
||||||
|
([boy-#smallcaps[obl]-#smallcaps[ad]], [tree(#smallcaps[g4])], [#smallcaps[g4]-bend-#smallcaps[pret]]),
|
||||||
|
([at boy], [tree], [bent]),
|
||||||
|
),
|
||||||
|
translation: ["Because of the boy, the tree bent."]
|
||||||
|
)
|
||||||
|
```
|
||||||
|
]
|
||||||
|
|
||||||
|
To number gloss examples, use `#numbered_gloss` in place of `gloss`. All other parameters remain the same.
|
||||||
|
|
||||||
|
#numbered_gloss(
|
||||||
|
source_text: ([გვ-ფრცქვნ-ი],),
|
||||||
|
source_text_style: none,
|
||||||
|
transliteration: ([gv-prtskvn-i],),
|
||||||
|
morphemes: ([1#pl.#obj\-peel-#fmnt],),
|
||||||
|
translation: "You peeled us",
|
||||||
|
)
|
||||||
|
|
||||||
|
#codeblock[
|
||||||
|
```typst
|
||||||
|
#import "linguistic-abbreviations.typ": *
|
||||||
|
|
||||||
|
#gloss(
|
||||||
|
source_text: ([გვ-ფრცქვნ-ი],),
|
||||||
|
source_text_style: none,
|
||||||
|
transliteration: ([gv-prtskvn-i],),
|
||||||
|
morphemes: ([1#pl.#obj\-peel-#fmnt],),
|
||||||
|
translation: "You peeled us",
|
||||||
|
```)]
|
||||||
|
|
||||||
|
The displayed number for numbered glosses is iterated for each numbered gloss
|
||||||
|
that appears throughout the document. Unnumbered glosses do not increment the
|
||||||
|
counter for the numbered glosses.
|
||||||
|
|
||||||
|
The gloss count is controlled by the Typst counter variable `gloss_count`. This
|
||||||
|
variable can be imported from the `leipzig-gloss` package and reset using the
|
||||||
|
standard Typst counter functions to control gloss numbering.
|
||||||
|
|
||||||
|
//TODO add examples here
|
||||||
|
|
||||||
|
|
||||||
|
== Styling lines of a gloss
|
||||||
|
|
||||||
|
Each of the aforementioned text parameters has a corresponding style parameter,
|
||||||
|
formed by adding `_style` to its name: `header_text_style`, `source_text_style`,
|
||||||
|
`transliteration_style`, `morphemes_style`, and `translation_style`. These parameters
|
||||||
|
allow you to specify formatting that should be applied to each entire line of
|
||||||
|
the gloss. This is particularly useful for the aligned gloss itself, since
|
||||||
|
otherwise one would have to modify each content item in the list individually.
|
||||||
|
|
||||||
|
In addition to these parameters, Typst’s usual content formatting can be applied
|
||||||
|
to or within any given content block in the gloss. Formatting applied in this
|
||||||
|
way will override any contradictory line-level formatting.
|
||||||
|
|
||||||
|
#gloss(
|
||||||
|
header_text: [This text is about eating your head.],
|
||||||
|
header_text_style: text.with(weight: "bold", fill: green),
|
||||||
|
source_text: (text(fill:black)[I'm], [eat-ing], [your], [head]),
|
||||||
|
source_text_style: text.with(style: "italic", fill: red),
|
||||||
|
morphemes: ([1#sg.#sbj\=to.be], text(fill:black)[eat-#prog], [2#sg.#pos], [head]),
|
||||||
|
morphemes_style: text.with(fill: blue),
|
||||||
|
translation: text(weight: "bold")[I'm eating your head!],
|
||||||
|
)
|
||||||
|
#codeblock[
|
||||||
|
```typst
|
||||||
|
#gloss(
|
||||||
|
header_text: [This text is about eating your head.],
|
||||||
|
header_text_style: text.with(weight: "bold", fill: green),
|
||||||
|
source_text: (text(fill:black)[I'm], [eat-ing], [your], [head]),
|
||||||
|
source_text_style: text.with(style: "italic", fill: red),
|
||||||
|
morphemes: ([1#sg.#sbj\=to.be], text(fill:black)[eat-#prog], [2#sg.#pos], [head]),
|
||||||
|
morphemes_style: text.with(fill: blue),
|
||||||
|
translation: text(weight: "bold")[I'm eating your head!],
|
||||||
|
)
|
||||||
|
```
|
||||||
|
]
|
||||||
|
//TODO add `line_styles` param
|
||||||
|
|
||||||
|
|
||||||
|
== Further Example Glosses
|
||||||
|
|
||||||
|
These example glosses replicate the ones given in
|
||||||
|
#link("https://www.eva.mpg.de/lingua/pdf/Glossing-Rules.pdf").
|
||||||
|
|
||||||
|
#{
|
||||||
|
gloss_count.update(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
#numbered_gloss(
|
||||||
|
header_text: [Indonesian (Sneddon 1996:237)],
|
||||||
|
source_text: ([Mereka], [di], [Jakarta], [sekarang.]),
|
||||||
|
morphemes: ([they], [in], [Jakarta], [now]),
|
||||||
|
translation: "They are in Jakarta now",
|
||||||
|
)
|
||||||
|
|
||||||
|
#numbered_gloss(
|
||||||
|
header_text: [Lezgian (Haspelmath 1993:207)],
|
||||||
|
source_text: ([Gila], [abur-u-n], [ferma], [hamišaluǧ], [güǧüna], [amuq’-da-č.]),
|
||||||
|
morphemes: ([now], [they-#obl\-#gen], [farm], [forever], [behind], [stay-#fut\-#neg]),
|
||||||
|
translation: "Now their farm will not stay behind forever.",
|
||||||
|
)
|
||||||
|
|
||||||
|
#numbered_gloss(
|
||||||
|
header_text: [West Greenlandic (Fortescue 1984:127)],
|
||||||
|
source_text: ([palasi=lu], [niuirtur=lu]),
|
||||||
|
morphemes: ([priest=and], [shopkeeper=and]),
|
||||||
|
translation: "both the priest and the shopkeeper",
|
||||||
|
)
|
||||||
|
|
||||||
|
#numbered_gloss(
|
||||||
|
header_text: [Hakha Lai],
|
||||||
|
source_text: ([a-nii -láay],),
|
||||||
|
morphemes: ([3#sg\-laugh-#fut],),
|
||||||
|
translation: [s/he will laugh],
|
||||||
|
)
|
||||||
|
|
||||||
|
#numbered_gloss(
|
||||||
|
header_text: [Russian],
|
||||||
|
source_text: ([My], [s], [Marko], [poexa-l-i], [avtobus-om], [v], [Peredelkino]),
|
||||||
|
morphemes: ([1#pl], [#com], [Marko], [go-#pst\-#pl], [bus-#ins], [#all], [Peredelkino]),
|
||||||
|
additional_gloss_lines: (([we], [with], [Marko], [go-#pst\-#pl], [bus-by], [to], [Peredelkino]),),
|
||||||
|
translation: "Marko and I went to Perdelkino by bus",
|
||||||
|
)
|
||||||
|
|
||||||
|
#numbered_gloss(
|
||||||
|
header_text: [Turkish],
|
||||||
|
source_text: ([çık-mak],),
|
||||||
|
morphemes: ([come.out-#inf],),
|
||||||
|
translation: "to come out",
|
||||||
|
)
|
||||||
|
|
||||||
|
#numbered_gloss(
|
||||||
|
header_text: [Latin],
|
||||||
|
source_text: ([insul-arum],),
|
||||||
|
morphemes: ([island-#gen\-#pl],),
|
||||||
|
translation: "of the islands",
|
||||||
|
)
|
||||||
|
|
||||||
|
#numbered_gloss(
|
||||||
|
header_text: [French],
|
||||||
|
source_text: ([aux], [chevaux]),
|
||||||
|
morphemes: ([to-#art\-#pl],[horse.#pl]),
|
||||||
|
translation: "to the horses",
|
||||||
|
)
|
||||||
|
|
||||||
|
#numbered_gloss(
|
||||||
|
header_text: [German],
|
||||||
|
source_text: ([unser-n], [Väter-n]),
|
||||||
|
morphemes: ([our-#dat\-#pl],[father.#pl\-#dat.#pl]),
|
||||||
|
translation: "to our fathers",
|
||||||
|
)
|
||||||
|
|
||||||
|
#numbered_gloss(
|
||||||
|
header_text: [Hittite (Lehmann 1982:211)],
|
||||||
|
source_text: ([n=an], [apedani], [mehuni],[essandu.]),
|
||||||
|
morphemes: ([#smallcaps[conn]=him], [that.#dat.#sg], [time.#dat.#sg], [eat.they.shall]),
|
||||||
|
translation: "They shall celebrate him on that date",
|
||||||
|
)
|
||||||
|
|
||||||
|
#numbered_gloss(
|
||||||
|
header_text: [Jaminjung (Schultze-Berndt 2000:92)],
|
||||||
|
source_text: ([nanggayan], [guny-bi-yarluga?]),
|
||||||
|
morphemes: ([who], [2#du.#A.3#sg.#P\-#fut\-poke]),
|
||||||
|
translation: "Who do you two want to spear?",
|
||||||
|
)
|
@ -1,200 +1,130 @@
|
|||||||
#import "abbreviations.typ"
|
#let gloss_count = counter("gloss_count")
|
||||||
|
|
||||||
// ╭─────────────────────╮
|
#let build_gloss(spacing_between_items, formatters, gloss_line_lists) = {
|
||||||
// │ Interlinear glosses │
|
assert(gloss_line_lists.len() > 0, message: "Gloss line lists cannot be empty")
|
||||||
// ╰─────────────────────╯
|
|
||||||
|
|
||||||
#let build-gloss(item-spacing, formatters, gloss-line-lists) = {
|
let len = gloss_line_lists.at(0).len()
|
||||||
assert(gloss-line-lists.len() > 0, message: "Gloss line lists cannot be empty")
|
|
||||||
|
|
||||||
let len = gloss-line-lists.at(0).len()
|
for line in gloss_line_lists {
|
||||||
|
|
||||||
for line in gloss-line-lists {
|
|
||||||
assert(line.len() == len)
|
assert(line.len() == len)
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(formatters.len() == gloss-line-lists.len(), message: "The number of formatters and the number of gloss line lists should be equal")
|
assert(formatters.len() == gloss_line_lists.len(), message: "The number of formatters and the number of gloss line lists should be equal")
|
||||||
|
|
||||||
let make-item-box(..args) = {
|
let make_item_box(..args) = {
|
||||||
box(stack(dir: ttb, spacing: 0.5em, ..args))
|
box(stack(dir: ttb, spacing: 0.5em, ..args))
|
||||||
}
|
}
|
||||||
|
|
||||||
for item-index in range(0, len) {
|
for item_index in range(0, len) {
|
||||||
let args = ()
|
let args = ()
|
||||||
for (line-idx, formatter) in formatters.enumerate() {
|
for (line_idx, formatter) in formatters.enumerate() {
|
||||||
let formatter-fn = if formatter == none {
|
let label_string = "leipzig-glossing-" + formatter.label
|
||||||
|
let formatter_fn = if formatter.fn == none {
|
||||||
(x) => x
|
(x) => x
|
||||||
} else {
|
} else {
|
||||||
formatter
|
formatter.fn
|
||||||
}
|
}
|
||||||
|
|
||||||
let item = gloss-line-lists.at(line-idx).at(item-index)
|
let item = gloss_line_lists.at(line_idx).at(item_index)
|
||||||
args.push(formatter-fn(item))
|
args.push([#formatter_fn(item) #label(label_string)])
|
||||||
}
|
}
|
||||||
make-item-box(..args)
|
make_item_box(..args)
|
||||||
h(item-spacing)
|
h(spacing_between_items)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Typesets the internal part of the interlinear glosses. This function does not deal with the external matters of numbering and labelling; which are handled by `example()`.
|
|
||||||
#let gloss(
|
#let gloss(
|
||||||
header: none,
|
header_text: none,
|
||||||
header-style: none,
|
header_text_style: none,
|
||||||
source: (),
|
source_text: (),
|
||||||
source-style: none,
|
source_text_style: emph,
|
||||||
transliteration: none,
|
transliteration: none,
|
||||||
transliteration-style: none,
|
transliteration_style: none,
|
||||||
morphemes: none,
|
morphemes: (),
|
||||||
morphemes-style: none,
|
morphemes_style: none,
|
||||||
additional-lines: (), //List of list of content
|
additional_gloss_lines: (), //List of list of content
|
||||||
translation: none,
|
translation: none,
|
||||||
translation-style: none,
|
translation_style: none,
|
||||||
item-spacing: 1em,
|
spacing_between_items: 1em,
|
||||||
) = {
|
gloss_padding: 2.0em, //TODO document these
|
||||||
assert(type(source) == "array", message: "source needs to be an array; perhaps you forgot to type `(` and `)`, or a trailing comma?")
|
left_padding: 0.5em,
|
||||||
|
|
||||||
if morphemes != none {
|
|
||||||
assert(type(morphemes) == "array", message: "morphemes needs to be an array; perhaps you forgot to type `(` and `)`, or a trailing comma?")
|
|
||||||
assert(source.len() == morphemes.len(), message: "source and morphemes have different lengths")
|
|
||||||
}
|
|
||||||
|
|
||||||
if transliteration != none {
|
|
||||||
assert(transliteration.len() == source.len(), message: "source and transliteration have different lengths")
|
|
||||||
}
|
|
||||||
|
|
||||||
let gloss-items = {
|
|
||||||
if header != none {
|
|
||||||
if header-style != none {
|
|
||||||
header-style(header)
|
|
||||||
} else {
|
|
||||||
header
|
|
||||||
}
|
|
||||||
linebreak()
|
|
||||||
}
|
|
||||||
|
|
||||||
let formatters = (source-style,)
|
|
||||||
let gloss-line-lists = (source,)
|
|
||||||
|
|
||||||
if transliteration != none {
|
|
||||||
formatters.push(transliteration-style)
|
|
||||||
gloss-line-lists.push(transliteration)
|
|
||||||
}
|
|
||||||
|
|
||||||
if morphemes != none {
|
|
||||||
formatters.push(morphemes-style)
|
|
||||||
gloss-line-lists.push(morphemes)
|
|
||||||
}
|
|
||||||
|
|
||||||
for additional in additional-lines {
|
|
||||||
formatters.push(none) //TODO fix this
|
|
||||||
gloss-line-lists.push(additional)
|
|
||||||
}
|
|
||||||
|
|
||||||
build-gloss(item-spacing, formatters, gloss-line-lists)
|
|
||||||
|
|
||||||
if translation != none {
|
|
||||||
linebreak()
|
|
||||||
|
|
||||||
if translation-style == none {
|
|
||||||
translation
|
|
||||||
} else {
|
|
||||||
translation-style(translation)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
align(left)[#gloss-items]
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// ╭─────────────────────╮
|
|
||||||
// │ Linguistic examples │
|
|
||||||
// ╰─────────────────────╯
|
|
||||||
|
|
||||||
#let example-count = counter("example-count")
|
|
||||||
|
|
||||||
#let example(
|
|
||||||
label: none,
|
|
||||||
label-supplement: [example],
|
|
||||||
gloss-padding: 2.5em, //TODO document these
|
|
||||||
left-padding: 0.5em,
|
|
||||||
numbering: false,
|
numbering: false,
|
||||||
breakable: false,
|
breakable: false,
|
||||||
..args
|
|
||||||
) = {
|
) = {
|
||||||
let add-subexample(subexample, count) = {
|
|
||||||
// Remove parameters which are not used in the `gloss`.
|
assert(type(source_text) == "array", message: "source_text needs to be an array; perhaps you forgot to type `(` and `)`, or a trailing comma?")
|
||||||
// TODO Make this functional, if (or when) it’s possible in Typst: filter out `label` and `label-supplement` when they are passed below.
|
assert(type(morphemes) == "array", message: "morphemes needs to be an array; perhaps you forgot to type `(` and `)`, or a trailing comma?")
|
||||||
let subexample-internal = subexample
|
|
||||||
if "label" in subexample-internal {
|
assert(source_text.len() == morphemes.len(), message: "source_text and morphemes have different lengths")
|
||||||
let _ = subexample-internal.remove("label")
|
|
||||||
|
if transliteration != none {
|
||||||
|
assert(transliteration.len() == source_text.len(), message: "source_text and transliteration have different lengths")
|
||||||
|
}
|
||||||
|
|
||||||
|
let gloss_items = {
|
||||||
|
|
||||||
|
if header_text != none {
|
||||||
|
if header_text_style != none {
|
||||||
|
[#header_text_style(header_text) #label("leipzig-glossing-header_text")]
|
||||||
|
} else {
|
||||||
|
[#header_text #label("leipzig-glossing-header_text")]
|
||||||
|
}
|
||||||
|
linebreak()
|
||||||
}
|
}
|
||||||
if "label-supplement" in subexample-internal {
|
|
||||||
let _ = subexample-internal.remove("label-supplement")
|
let formatters = (("fn": source_text_style, "label": "source_text"),)
|
||||||
|
let gloss_line_lists = (source_text,)
|
||||||
|
|
||||||
|
if transliteration != none {
|
||||||
|
formatters.push(("fn": transliteration_style, "label": "transliteration"))
|
||||||
|
gloss_line_lists.push(transliteration)
|
||||||
|
}
|
||||||
|
|
||||||
|
formatters.push(("fn": morphemes_style, "label": "morpheme"))
|
||||||
|
gloss_line_lists.push(morphemes)
|
||||||
|
|
||||||
|
for additional in additional_gloss_lines {
|
||||||
|
formatters.push(("fn": none, "label": none)) //TODO fix this
|
||||||
|
gloss_line_lists.push(additional)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
build_gloss(spacing_between_items, formatters, gloss_line_lists)
|
||||||
|
|
||||||
|
if translation != none {
|
||||||
|
linebreak()
|
||||||
|
|
||||||
|
if translation_style == none {
|
||||||
|
["#translation"]
|
||||||
|
} else {
|
||||||
|
translation_style(translation)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
par()[
|
|
||||||
#box()[
|
|
||||||
#figure(
|
|
||||||
kind: "subexample",
|
|
||||||
numbering: it => [#example-count.display()#count.display("a")],
|
|
||||||
outlined: false,
|
|
||||||
supplement: it => {if "label-supplement" in subexample {return subexample.label-supplement} else {return "example"}},
|
|
||||||
stack(
|
|
||||||
dir: ltr, //TODO this needs to be more flexible
|
|
||||||
[(#context count.display("a"))],
|
|
||||||
left-padding,
|
|
||||||
gloss(..subexample-internal)
|
|
||||||
)
|
|
||||||
) #if "label" in subexample {std.label(subexample.label)}
|
|
||||||
]
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if numbering {
|
if numbering {
|
||||||
example-count.step()
|
gloss_count.step()
|
||||||
}
|
}
|
||||||
|
|
||||||
let example-number = if numbering {
|
let gloss_number = if numbering {
|
||||||
[(#context example-count.display())]
|
[(#gloss_count.display())]
|
||||||
} else {
|
} else {
|
||||||
none
|
none
|
||||||
}
|
}
|
||||||
|
|
||||||
style(styles => {
|
style(styles => {
|
||||||
block(breakable: breakable)[
|
block(breakable: breakable)[
|
||||||
#figure(
|
#stack(
|
||||||
kind: "example",
|
dir:ltr, //TODO this needs to be more flexible
|
||||||
numbering: it => [#example-count.display()],
|
left_padding,
|
||||||
outlined: false,
|
[#gloss_number],
|
||||||
supplement: label-supplement,
|
gloss_padding - left_padding - measure([#gloss_number],styles).width,
|
||||||
stack(
|
[#gloss_items]
|
||||||
dir: ltr, //TODO this needs to be more flexible
|
)
|
||||||
left-padding,
|
|
||||||
[#example-number],
|
|
||||||
gloss-padding - left-padding - measure([#example-number]).width,
|
|
||||||
{
|
|
||||||
if args.pos().len() == 1 { // a simple example with no sub-examples
|
|
||||||
gloss(..arguments(..args.pos().at(0)))
|
|
||||||
}
|
|
||||||
else { // containing sub-examples
|
|
||||||
let subexample-count = counter("subexample-count")
|
|
||||||
subexample-count.update(0)
|
|
||||||
set align(left)
|
|
||||||
if "header" in args.named() {
|
|
||||||
par[#args.named().header]
|
|
||||||
}
|
|
||||||
for subexample in args.pos() {
|
|
||||||
subexample-count.step()
|
|
||||||
add-subexample(subexample, subexample-count)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
),
|
|
||||||
) #if label != none {std.label(label)}
|
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
#let numbered-example = example.with(numbering: true)
|
#let numbered_gloss = gloss.with(numbering: true)
|
||||||
|
128
linguistic-abbreviations.typ
Normal file
128
linguistic-abbreviations.typ
Normal file
@ -0,0 +1,128 @@
|
|||||||
|
#let fmnt = smallcaps([fmnt])
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Appendix: List of Standard Abbreviations
|
||||||
|
|
||||||
|
1 first person
|
||||||
|
2 second person
|
||||||
|
3 third person
|
||||||
|
A agent-like argument of canonical transitive verb
|
||||||
|
ABL ablative
|
||||||
|
ABS absolutive
|
||||||
|
ACC accusative
|
||||||
|
ADJ adjective
|
||||||
|
ADV adverb(ial)
|
||||||
|
AGR agreement
|
||||||
|
ALL allative
|
||||||
|
ANTIP antipassive
|
||||||
|
APPL applicative
|
||||||
|
ART article
|
||||||
|
AUX auxiliary
|
||||||
|
BEN benefactive
|
||||||
|
*/
|
||||||
|
#let A = smallcaps([a])
|
||||||
|
#let all = smallcaps([all])
|
||||||
|
#let art = smallcaps([art])
|
||||||
|
|
||||||
|
/*
|
||||||
|
CAUS causative
|
||||||
|
CLF classifier
|
||||||
|
COM comitative
|
||||||
|
COMP complementizer
|
||||||
|
COMPL completive
|
||||||
|
COND conditional
|
||||||
|
COP copula
|
||||||
|
CVB converb
|
||||||
|
DAT dative
|
||||||
|
DECL declarative
|
||||||
|
DEF definite
|
||||||
|
DEM demonstrative
|
||||||
|
DET determiner
|
||||||
|
DIST distal
|
||||||
|
*/
|
||||||
|
#let com = smallcaps([com])
|
||||||
|
#let dat = smallcaps([dat])
|
||||||
|
|
||||||
|
/*
|
||||||
|
DISTR distributive
|
||||||
|
DU dual
|
||||||
|
DUR durative
|
||||||
|
ERG ergative
|
||||||
|
EXCL exclusive
|
||||||
|
F feminine
|
||||||
|
FOC focus
|
||||||
|
FUT future
|
||||||
|
GEN genitive
|
||||||
|
IMP imperative
|
||||||
|
INCL inclusive
|
||||||
|
IND indicative
|
||||||
|
INDF indefinite
|
||||||
|
INF infinitive
|
||||||
|
INS instrumental
|
||||||
|
INTR intransitive
|
||||||
|
IPFV imperfective
|
||||||
|
*/
|
||||||
|
|
||||||
|
#let du = smallcaps([du])
|
||||||
|
#let fut = smallcaps([fut])
|
||||||
|
#let gen = smallcaps([gen])
|
||||||
|
#let inf = smallcaps([inf])
|
||||||
|
#let ins = smallcaps([ins])
|
||||||
|
|
||||||
|
/*
|
||||||
|
IRR irrealis
|
||||||
|
LOC locative
|
||||||
|
M masculine
|
||||||
|
N neuter
|
||||||
|
N- non- (e.g. NSG nonsingular, NPST nonpast)
|
||||||
|
NEG negation, negative
|
||||||
|
NMLZ nominalizer/nominalization
|
||||||
|
NOM nominative
|
||||||
|
OBJ object
|
||||||
|
OBL oblique
|
||||||
|
P patient-like argument of canonical transitive verb
|
||||||
|
PASS passive
|
||||||
|
PFV perfective
|
||||||
|
PL plural
|
||||||
|
*/
|
||||||
|
|
||||||
|
#let obl = smallcaps([obl])
|
||||||
|
#let neg = smallcaps([neg])
|
||||||
|
#let obj = smallcaps([obj])
|
||||||
|
#let pl = smallcaps([pl])
|
||||||
|
/*
|
||||||
|
POSS possessive
|
||||||
|
PRED predicative
|
||||||
|
PRF perfect
|
||||||
|
PRS present
|
||||||
|
PROG progressive
|
||||||
|
PROH prohibitive
|
||||||
|
PROX proximal/proximate
|
||||||
|
PST past
|
||||||
|
PTCP participle
|
||||||
|
PURP purposive
|
||||||
|
Q question particle/marker
|
||||||
|
QUOT quotative
|
||||||
|
RECP reciprocal
|
||||||
|
REFL reflexive
|
||||||
|
*/
|
||||||
|
#let P = smallcaps([p])
|
||||||
|
#let pos = smallcaps([pos])
|
||||||
|
#let prog = smallcaps([prog])
|
||||||
|
#let pst = smallcaps([pst])
|
||||||
|
|
||||||
|
/*
|
||||||
|
REL relative
|
||||||
|
RES resultative
|
||||||
|
S single argument of canonical intransitive verb
|
||||||
|
SBJ subject
|
||||||
|
SBJV subjunctive
|
||||||
|
SG singular
|
||||||
|
TOP topic
|
||||||
|
TR transitive
|
||||||
|
VOC vocative
|
||||||
|
*/
|
||||||
|
|
||||||
|
#let sg = smallcaps([sg])
|
||||||
|
#let sbj = smallcaps([sbj])
|
33
new-example.typ
Normal file
33
new-example.typ
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
#import "leipzig-gloss.typ": gloss, numbered_gloss, gloss_count
|
||||||
|
#import "linguistic-abbreviations.typ": *
|
||||||
|
|
||||||
|
#show <leipzig-glossing-header_text>: set text(blue)
|
||||||
|
#show label("leipzig-glossing-source_text"): set text(weight: "bold")
|
||||||
|
|
||||||
|
= Saimiar
|
||||||
|
|
||||||
|
#let sc = smallcaps
|
||||||
|
|
||||||
|
From the song Tetrachromacy (_xoikesêcuxasø_) by King Gizzard.
|
||||||
|
|
||||||
|
#gloss(
|
||||||
|
header_text: [vath sêcubai dhiakŋo, somyxasan krexasir êsuŋo],
|
||||||
|
source_text: ([vath], [sêcu-bai], [dhika-ŋo], [so-my-xas-an], [kre-xas-ir], [êsu-ŋo]),
|
||||||
|
morphemes: ([three], [color-#sc[1sg]:#sc[pos]], [divide-#sc[cop]], [#sc[all]-un-see-#sc[nom]], [#sc[pot]-see-#sc[nom]], [desire-#sc[cop]]),
|
||||||
|
translation: [my three shades are divisible, lust to see the invisible],
|
||||||
|
)
|
||||||
|
|
||||||
|
#gloss(
|
||||||
|
header_text: [vath sêcubai dhiakŋo, somyxasan krexasir êsuŋo],
|
||||||
|
header_text_style: text.with(fill: green),
|
||||||
|
source_text: ([vath], [sêcu-bai], [dhika-ŋo], [so-my-xas-an], [kre-xas-ir], [êsu-ŋo]),
|
||||||
|
morphemes: ([three], [color-#sc[1sg]:#sc[pos]], [divide-#sc[cop]], [#sc[all]-un-see-#sc[nom]], [#sc[pot]-see-#sc[nom]], [desire-#sc[cop]]),
|
||||||
|
translation: [my three shades are divisible, lust to see the invisible],
|
||||||
|
)
|
||||||
|
|
||||||
|
#gloss(
|
||||||
|
header_text: [This text is about eating your head.],
|
||||||
|
source_text: (text(fill:black)[I'm], [eat-ing], [your], [head]),
|
||||||
|
morphemes: ([1#sg.#sbj\=to.be], text(fill:black)[eat-#prog], [2#sg.#pos], [head]),
|
||||||
|
translation: text(weight: "bold")[I'm eating your head!],
|
||||||
|
)
|
@ -1,12 +1,8 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "leipzig-glossing"
|
name = "leipzig-glossing"
|
||||||
version = "0.4.0"
|
version = "0.1.0"
|
||||||
entrypoint = "leipzig-gloss.typ"
|
entrypoint = "leipzig-gloss.typ"
|
||||||
authors = ["Greg Shuflin <greg@everydayimshuflin.com>", "Other open-source contributors"]
|
authors = ["Greg Shuflin", "Other open-source contributors"]
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
description = "Linguistic interlinear glosses according to the Leipzig Glossing rules"
|
description = "Linguistic interlinear glosses according to the Leipzig Glossing rules"
|
||||||
repository = "https://code.everydayimshuflin.com/greg/typst-lepizig-glossing"
|
repository = "https://code.everydayimshuflin.com/greg/typst-lepizig-glossing"
|
||||||
disciplines = ["linguistics"]
|
|
||||||
categories = ["paper"]
|
|
||||||
keywords = ["linguistics", "leipzig", "gloss", "glossing"]
|
|
||||||
compiler = "0.12.0"
|
|
||||||
|
Loading…
Reference in New Issue
Block a user