If you are unfamiliar with Sanskrit verbs, this, this, and this serve as great guides to get familiar with conjugations.
This template can be called in eight different ways:
{{sa-verb|nonf|...}}
: a table with the infinitive, gerund, gerundives, and past passive participle{{sa-verb|pres|...}}
: a table with the present tense (incl. the indicative, optative, imperative, and active participles){{sa-verb|impf|...}}
: a table with the imperfect tense{{sa-verb|fut|...}}
: a table with the future tense (incl. the simple, peripherastic, and active participles){{sa-verb|cond|...}}
: a table with the conditional tense{{sa-verb|aor|...}}
: a table with the aorist tense{{sa-verb|bene|...}}
: a table with the benedictive/precative, originally the optative of the aorist{{sa-verb|perf|...}}
: a table with the perfect tense (incl. active participles)The first argument is always the third-person singular indicative active-voice form (or optative, in the case of the benedictive) of the verb in that tense. For instance, {{sa-verb|pres|arhati}}
will produce a table for the present-tense conjugation of अर्हति (arhati). {{sa-verb|impf|ārhat}}
will likewise produce a table for the imperfect-tense conjugation of that verb.
If no other non-keyword arguments are passed, the verb is assumed to be thematic, and this is all that is necessary. If a second argument is passed, the verb is assumed to be athematic and the the second argument should be the third-person plural indicative active-voice form (or optative, in the case of the benedictive) of the verb. If a third argument is passed, it should be the third-person singular indicative passive-voice form (or optative, in the case of the benedictive) of the verb. For instance, {{sa-verb|pres|leḍhi<leh>|lihanti|lihyate}}
will produce a table for the present-tense athematic conjugation of लेढि (leḍhi). For aorist and benedictive tables, the passive stem must be provided if it is different from the active stem, but the middle/weak stem is unused; hence {{sa-verb|aor|alikṣat||alikṣata}}
produces the aorist table for लेढि (leḍhi).
The "<...>" in that example encloses the stem of the verb. In the case of "leḍhi", the stem "leh" cannot be inferred from the third-person tense due to internal sandhi. Hence, we must provide the stem in brackets like that. All non-keyword arguments can take a stem like this, and, if provided, will be used in place of the third-person form (although the third-person form should still be provided so the module can infer the class of the verb). ALSO, the bracketed stem argument must be provided if the third-person form is irregular.
The non-finite forms table is special and only takes a single non-keyword argument: the infinitive form of the verb (with a possible bracketed stem). For लेढि (leḍhi), we would write {{sa-verb|nonf|liḍhum<lih>}}
.
Usually, like in the case of {{sa-verb|pres|leḍhi<leh>|lihanti|lihyate}}
, this module is smart and will apply a variety of sandhi rules to produce a correct output. Occasionally, though, this is not welcome. For instance, in {{sa-verb|pres|asti|santi|...}}
, the internal sandhi rules will try to eliminate the स in the root. To avoid this, use the argument "auto_sandhi=false".
A number of Sanskrit verbs are deponent (only middle voice), active-only, or have no passive. By default, this module will conjugate as many voices as each tense has. To limit the voices, use the argument "n=...". "a" stands for "active", "m" stands for "middle", and "p" stands for "passive", so "n=amp" will produce all three voices, "n=m" will produce just the middle voice, and "n=am" will produce both the active and middle voices, for example.
Occasionally, the automatic sandhi is unable to predict the right form in a particular case or the verb has some special cases. To handle this, every single cell of the table can be completely overridden by a keyword argument to the table. It should be of the form:
where
For instance, in {{sa-verb|pres|asti|santi|auto_sandhi=false|n=a}}
, the second-person singular indicative present form will be *अस्सि by default, but it is actually irregular and is असि. Hence, we override the default value by providing the arg "indic_av_2_s=asi" in {{sa-verb|pres|asti|santi|auto_sandhi=false|indic_av_2_s=asi|n=a}}
.
For खेलति (khelati) (thematic, class 1, no ablaut),
{{sa-verb|nonf|Kelitum}}
{{sa-verb|pres|Kelati}}
{{sa-verb|impf|aKelat}}
{{sa-verb|fut|Kelizyati}}
{{sa-verb|cond|aKeizyat}}
{{sa-verb|aor|aKelIt}}
{{sa-verb|bene|KelyAt}}
{{sa-verb|perf|caKela}}
Lua error at line 458: Parameter "lemma" has been entered more than once. This is probably because a parameter alias has been used.
Lua error at line 458: Parameter "lemma" has been entered more than once. This is probably because a parameter alias has been used.
Lua error at line 458: Parameter "lemma" has been entered more than once. This is probably because a parameter alias has been used.
Lua error at line 458: Parameter "lemma" has been entered more than once. This is probably because a parameter alias has been used.
Lua error at line 458: Parameter "lemma" has been entered more than once. This is probably because a parameter alias has been used.
Lua error at line 458: Parameter "lemma" has been entered more than once. This is probably because a parameter alias has been used.
Lua error at line 458: Parameter "lemma" has been entered more than once. This is probably because a parameter alias has been used.
Lua error at line 458: Parameter "lemma" has been entered more than once. This is probably because a parameter alias has been used.
For अस्ति (asti) (athematic, class 2),
{{sa-verb|pres|asti|santi|auto_sandhi=false|indic_av_2_s=asi|n=a}}
{{sa-verb|impf|āsīt<ās>|āsan|auto_sandhi=false|indic_av_2_s=āsīḥ|indic_av_3_s=āsīt|n=a}}
("<ās>" is provided as the form "āsīt" is irregular).
Lua error at line 458: Parameter "lemma" has been entered more than once. This is probably because a parameter alias has been used.
Lua error at line 458: Parameter "lemma" has been entered more than once. This is probably because a parameter alias has been used.
For लेढि (leḍhi) (athematic, class 2, irregular),
{{sa-verb|nonf|līḍhum<lih>}}
{{sa-verb|pres|leḍhi<leh>|lihanti|lihyate}}
{{sa-verb|impf|aleṭ<aleh>|alihan|alihyata}}
{{sa-verb|fut|lekṣyati}}
{{sa-verb|cond|alekṣyat}}
{{sa-verb|aor|alikṣat||alikṣata}}
{{sa-verb|bene|lihyāt||likṣīṣṭa}}
{{sa-verb|perf|lileha|lilihuḥ}}
Lua error at line 458: Parameter "lemma" has been entered more than once. This is probably because a parameter alias has been used.
Lua error at line 458: Parameter "lemma" has been entered more than once. This is probably because a parameter alias has been used.
Lua error at line 458: Parameter "lemma" has been entered more than once. This is probably because a parameter alias has been used.
Lua error at line 458: Parameter "lemma" has been entered more than once. This is probably because a parameter alias has been used.
Lua error at line 458: Parameter "lemma" has been entered more than once. This is probably because a parameter alias has been used.
Lua error at line 458: Parameter "lemma" has been entered more than once. This is probably because a parameter alias has been used.
Lua error at line 458: Parameter "lemma" has been entered more than once. This is probably because a parameter alias has been used.
Lua error at line 458: Parameter "lemma" has been entered more than once. This is probably because a parameter alias has been used.
For रिणक्ति (riṇakti) (athematic, class 7),
{{sa-verb|nonf|riṇaktum<riṇac>|rikta<ric>}}
{{sa-verb|pres|riṇakti<riṇac>|riñcanti|ricyate}}
{{sa-verb|impf|ariṇak<ariṇac>|ariñcan|aricyata}}
{{sa-verb|fut|rekṣyati}}
{{sa-verb|cond|arekṣyat}}
{{sa-verb|aor|aricat,araikṣīt||arikta<aric>}}
{{sa-verb|bene|recyāt||rikṣīṣṭa}}
{{sa-verb|perf|rireca|riricuḥ}}
Lua error at line 458: Parameter "lemma" has been entered more than once. This is probably because a parameter alias has been used.
Lua error at line 458: Parameter "lemma" has been entered more than once. This is probably because a parameter alias has been used.
Lua error at line 458: Parameter "lemma" has been entered more than once. This is probably because a parameter alias has been used.
Lua error at line 458: Parameter "lemma" has been entered more than once. This is probably because a parameter alias has been used.
Lua error at line 458: Parameter "lemma" has been entered more than once. This is probably because a parameter alias has been used.
Lua error at line 458: Parameter "lemma" has been entered more than once. This is probably because a parameter alias has been used.
Lua error at line 458: Parameter "lemma" has been entered more than once. This is probably because a parameter alias has been used.
Lua error at line 458: Parameter "lemma" has been entered more than once. This is probably because a parameter alias has been used.
local export = {}
local m_para = require("Module:parameters")
local m_links = require("Module:links")
local m_utils = require("Module:utilities")
local lang = require("Module:languages").getByCode("sa")
local m_script_utils = require("Module:script utilities")
local sa_verb_data = require("Module:User:Dragonoid76/sa-verb/data")
local SLP_to_IAST = require("Module:sa-utilities/translit/SLP1-to-IAST")
local sa_utils_translit = require("Module:sa-utilities/translit")
local PAGENAME = mw.title.getCurrentTitle().text
local gsub = mw.ustring.gsub
local match = mw.ustring.match
local split = mw.text.split
local sa_utils = require("Module:sa-utilities")
local names = {
= "Present",
= "Imperfect",
= "Future",
= "Conditional",
= "Aorist",
= "Benedictive/Precative",
= "Perfect",
= "Indicative",
= "Imperative",
= "Optative/Potential",
= "Participles",
= "Simple Indicative",
= "Periphrastic Indicative",
= "Infinitive",
= "Gerund",
= "Masculine/Neuter Gerundive",
= "Feminine Gerundive",
= "Masculine/Neuter Past Passive Participle",
= "Feminine Past Passive Participle",
= "Masculine/Neuter Past Active Participle",
= "Feminine Past Active Participle",
= "Nonfinite Forms"
}
local tenses = {
= {
= { "indic", "imper", "optat", "part" },
= { "av", "mv" }
},
= {
= { "indic" },
= { "av", "mv" }
},
= {
= { "simple", "periph", "part" },
= { "av", "mv" }
},
= {
= { "indic" },
= { "av", "mv" }
},
= {
= { "indic" },
= { "av", "mv" }
},
= {
= { "optat" },
= { "av", "mv" }
},
= {
= { "indic", "part" },
= { "av", "mv" }
},
= {
= { "inf", "gerund", "gerundive_mn", "gerundive_f", "part_mn", "part_f", "part_av_mn", "part_av_f" }
}
}
local numbers = {"1_s", "2_s", "3_s", "1_d", "2_d", "3_d", "1_p", "2_p", "3_p"}
local super_nums = {
= "¹",
= "²",
= "³",
= "⁴",
= "⁵",
= "⁶",
= "⁷",
= "⁸",
= "⁹",
= "⁰"
}
local function to_super(num)
local annotation = gsub(num, ".", super_nums)
return annotation
end
local function get_form_note_tags(form_notes, data)
local output = {}
if type(form_notes) ~= "table" then
form_notes = {form_notes}
end
for _, form_note in ipairs(form_notes) do
if type(data.form_notes) ~= "number" then
table.insert(data.form_notes_out, form_note)
data.form_notes = #data.form_notes_out
end
table.insert(output, to_super(data.form_notes))
end
return table.concat(output)
end
local function make_header(args, data, title_models, sc_cache)
local width = 70
local title = names .. ": " .. title_models
local header = {
'{| class="inflection-table vsSwitcher" data-toggle-category="inflection" style="background:#F9F9F9; text-align:center; border: 1px solid #CCC; width: ' ..
width .. 'em"\n'
}
table.insert(header, '|- style="background: #d9ebff;"\n')
table.insert(
header,
'! class="vsToggleElement" style="text-align: left;" colspan="' .. args.colspan .. '" | ' .. title .. "\n"
)
table.insert(header, '|- class="vsHide"\n')
table.insert(header, '! style="background:#eff7ff" rowspan="2" |\n')
table.insert(header, '! colspan="3" style="background:#eff7ff" | Active\n')
table.insert(header, '! colspan="3" style="background:#eff7ff" | Mediopassive\n')
table.insert(header, '|- class="vsHide"\n')
local size = 2
for i = 1, size, 1 do
table.insert(header, '! style="background:#eff7ff" | Singular\n')
table.insert(header, '! style="background:#eff7ff" | Dual\n')
table.insert(header, '! style="background:#eff7ff" | Plural\n')
end
return table.concat(header)
end
local function make_cell(args, data, tag, arg_tag, sc_cache, col_span, voice)
local forms, links, trs = {}, {}, {}
if (not match(args.n, "a") and voice == "av") or (not match(args.n, "m") and voice == "mv") or (not match(args.n, "p") and voice == "pv") then
forms = {"-"}
elseif args then
forms = mw.text.split(args, "%s*%s*")
else
forms = data.forms
end
if not forms then
return "| -\n"
end
for i, form in ipairs(forms) do
form = sc_cache.tr(form)
form = gsub(form, 'V', 'f')
form = gsub(form, "Z", "x")
local form_note_tag = get_form_note_tags(forms or {}, data)
table.insert(
links,
m_links.full_link({term = sc_cache.reverse_tr(form), tr = "-", lang = lang, sc = sc_cache.sc}) ..
form_note_tag
)
table.insert(trs, SLP_to_IAST.tr(form) .. form_note_tag)
end
return table.concat {
"| ",
"colspan = ",
col_span,
" | ",
table.concat(links, " / "),
"<br/>",
m_script_utils.tag_translit(table.concat(trs, " / "), lang, "default", 'style="color: #888;"'),
"\n"
}
end
local function format_notes(args, data)
local output = {
'|- class="vsHide"',
'| style="background-color:#eff7ff; font-style:italic;border-top:double #888;" | Notes',
'| style="text-align:left;border-top:double #888;" colspan="' .. args.colspan .. '" |'
}
if #data.form_notes_out > 0 or #data.general_notes > 0 or #args.note > 0 then
for i, form_note in ipairs(data.form_notes_out) do
table.insert(output, "* " .. to_super(i) .. form_note)
end
for _, general_note in ipairs(data.general_notes) do
table.insert(output, "* " .. general_note)
end
for _, note in ipairs(args.note) do
table.insert(output, "* " .. note)
end
return table.concat(output, "\n") .. "\n"
else
return ""
end
end
local function make_nonf_table(args, data, output, sc_cache)
local moods = tenses.moods
if data.forms ~= "-" and data.forms ~= nil then
data.forms = { data.forms .. "vat" } -- these two formed directly from the given forms always
data.forms = { data.forms .. "vatī" }
else
data.forms = { "-" }
data.forms = { "-" }
end
local title_models = ""
local arg_before = false
local tag = moods
local arg_tag = moods
local forms
if args then
forms = mw.text.split(args, "%s*%s*")
else
forms = data.forms
end
for i, title_lem in ipairs(forms) do
title_lem = sc_cache.tr(title_lem)
title_lem = gsub(title_lem, 'V', 'f')
title_lem = gsub(title_lem, "Z", "x")
if i > 1 then
title_models = title_models .. " or "
end
title_models =
title_models ..
m_links.full_link(
{
term = nil,
alt = sc_cache.reverse_tr(title_lem),
tr = SLP_to_IAST.tr(title_lem),
lang = lang,
sc = sc_cache.sc
}
)
end
local title = names .. ": " .. title_models
table.insert(output, 'Forms of Sanskrit verbs are numerous and complicated. The following conjugation shows only a subset of all forms and should be treated as a guide. \n')
table.insert(
output,
'{| class="inflection-table vsSwitcher" data-toggle-category="inflection" style="background:#F9F9F9; text-align:center; border: 1px solid #CCC; width: 40em"\n'
)
table.insert(output, '|- style="background: #d9ebff;"\n')
table.insert(output, '! class="vsToggleElement" style="text-align: left;" colspan="4" | ' .. title .. "\n")
table.insert(output, '|- class="vsHide"\n')
table.insert(output, '! style="background:#eff7ff" |\n')
table.insert(output, '! colspan="2" style="background:#eff7ff" | Undeclinable\n')
table.insert(output, '|- class="vsHide"\n')
for _, mood in ipairs(moods) do
if mood == "gerundive_mn" then
table.insert(output, '! style="background:#eff7ff" |\n')
table.insert(output, '! colspan="2" style="background:#eff7ff" | Participles\n')
table.insert(output, '|- class="vsHide"\n')
end
table.insert(output, '! style="background-color:#eff7ff;" | ' .. names .. "\n")
local tag = mood
local arg_tag = mood
table.insert(output, make_cell(args, data, tag, arg_tag, sc_cache, 1))
table.insert(output, '|- class="vsHide"\n')
end
table.insert(output, format_notes(args, data))
table.insert(output, "|}")
if not args.nocat and #data.categories > 0 then
table.insert(output, m_utils.format_categories(data.categories, lang))
end
return output
end
local function make_voice(title_models, args, data, sc_cache, voice)
local moods = tenses.moods
local tag = moods .. "_" .. voice .. "_3_s"
local arg_tag = moods .. "_" .. voice .. "_3_s"
local forms
if args then
forms = mw.text.split(args, "%s*%s*")
else
forms = data.forms
end
if #title_models > 0 then
table.insert(title_models, ", ")
end
for i, title_lem in ipairs(forms or {"-"}) do
title_lem = sc_cache.tr(title_lem)
if i > 1 then
table.insert(title_models, " or ")
end
title_lem = gsub(title_lem, 'V', 'f')
title_lem = gsub(title_lem, "Z", "x")
table.insert(title_models,
m_links.full_link(
{
term = nil,
alt = sc_cache.reverse_tr(title_lem),
tr = SLP_to_IAST.tr(title_lem),
lang = lang,
sc = sc_cache.sc
}
)
)
end
end
local function make_table_verb(args, data, output, sc_cache)
local moods = tenses.moods
if args.tense == "nonf" then
table.insert(data.categories, "Sanskrit verbs with nonfinite forms")
return make_nonf_table(args, data, output, sc_cache)
end
-- local voices = tenses.voices
local voices = tenses.voices
local numbers = {"s", "d", "p"}
local people = {{"3", "Third"}, {"2", "Second"}, {"1", "First"}}
local title_models = {}
if match(args.n, "a") then
make_voice(title_models, args, data, sc_cache, "av")
end
if match(args.n, "m") then
make_voice(title_models, args, data, sc_cache, "mv")
end
if match(args.n, "p") then
make_voice(title_models, args, data, sc_cache, "pv")
end
table.insert(output, make_header(args, data, table.concat(title_models, ""), sc_cache))
table.insert(output, '|- class="vsHide"\n')
for _, mood in ipairs(moods) do
table.insert(output, '! style="background:#eff7ff" colspan="' .. args.colspan .. '" | ' .. names .. "\n")
table.insert(output, '|- class="vsHide"\n')
if mood == "part" then
table.insert(output, '| style="background-color:#eff7ff; font-style:italic;" | \n')
for _, voice in ipairs(voices) do
local tag = mood .. "_" .. voice
local arg_tag = mood .. "_" .. voice
table.insert(output, make_cell(args, data, tag, arg_tag, sc_cache, 3, voice))
end
else
for i, person_pair in ipairs(people) do
local person, person_name = person_pair, person_pair
table.insert(output, '| style="background-color:#eff7ff; font-style:italic;" | ' .. person_name .. "\n")
for _, voice in ipairs(voices) do
for _, number in ipairs(numbers) do
local tag = mood .. "_" .. voice .. "_" .. person .. "_" .. number
local arg_tag = mood .. "_" .. voice .. "_" .. person .. "_" .. number
table.insert(output, make_cell(args, data, tag, arg_tag, sc_cache, 1, voice))
end
end
table.insert(output, '|- class="vsHide"\n')
end
end
end
table.insert(output, format_notes(args, data))
table.insert(output, "|}")
if not args.nocat and #data.categories > 0 then
table.insert(output, m_utils.format_categories(data.categories, lang))
end
return output
end
local function get_sc_details(args)
local sc, scCode
if args.sc then
sc = require("Module:scripts").getByCode(args.sc)
scCode = args.sc
else
sc = lang:findBestScript(args.lemma)
scCode = sc:getCode()
if scCode == "None" then
sc = lang:findBestScript(PAGENAME)
scCode = sc:getCode()
if scCode == "None" then
-- error("Script code was not specified or detected.")
-- Suppress; this fixes issues where docs pages get errors
return get_sc_details({sc = "Deva"})
end
end
end
local tr, reverse_tr = sa_utils_translit.retrieve_tr_modules(scCode)
return {tr = tr, reverse_tr = reverse_tr, sc = sc, scCode = scCode}
end
--[=[Splits a string by commas and displays
]=]
function export.split(frame)
local args = frame.args
args.lemma = args
local sc_cache = get_sc_details(args)
if not sc_cache then
return "Module failed on page "
end
local output = {}
local splitted = mw.text.split(frame.args, ",")
for i, form in ipairs(splitted) do
if i > 1 then table.insert(output, "<br/>") end
table.insert(
output,
m_links.full_link({term = form, lang = lang, sc = sc_cache.sc})
)
end
return table.concat(output)
end
function export.show(frame)
local params = {
lemma = {default = PAGENAME},
n = {default = "amp"},
sc = {},
= {required = true},
= {alias_of = "lemma"},
= {},
= {},
auto_sandhi = {default = true, type = "boolean"},
set = {default = false, type = "boolean" }, -- set vs anit roots
note = {list = true, type = "boolean"},
o = {default = false, type = "boolean"},
mono = {default = false, type = "boolean"}
}
for tense, tense_l in pairs(tenses) do
if tense == "nonf" then
for _, mood in pairs(tense_l) do
params = {}
end
else
for _, mood in pairs(tense_l) do
for _, voice in pairs(tense_l) do
if mood == "part" then
params = {}
else
for _, number in pairs(numbers) do
params = {}
end
end
end
end
end
end
local data = {
forms = {},
categories = {},
decl_type = nil,
form_notes = {},
form_notes_out = {},
general_notes = {}
}
local args = m_para.process(frame:getParent().args, params)
local sc_cache = get_sc_details(args)
if not sc_cache then
return "Module failed on page "
end
args.lemma = sc_cache.tr(args.lemma)
if args ~= nil then args = sc_cache.tr(args) end
if args ~= nil then args = sc_cache.tr(args) end
local output = {}
args.tense = args
-- conjugate(args, data)
args.colspan = 7
args.n = gsub(args.n, "p", "")
args.strong_lemma = args.lemma -- split(args.lemma, ",")
args.weak_lemma = args -- and split(args, ",")
args.passive_lemma = args -- and split(args, ",")
if not args.o then
sa_verb_data(args, data)
end
make_table_verb(args, data, output, sc_cache)
return table.concat(output)
end
return export