Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix optional parameters parsing for \newcommand #1453

Merged
merged 4 commits into from
Jun 7, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ plugins {
}

group 'nl.hannahsten'
version '0.6.10'
version '0.7-alpha.76'

repositories {
mavenCentral()
Expand Down
22 changes: 15 additions & 7 deletions src/nl/hannahsten/texifyidea/psi/LatexCommandsImplUtil.kt
Original file line number Diff line number Diff line change
Expand Up @@ -136,25 +136,33 @@ fun stripGroup(text: String): String {
}

/**
* Generates a map of parameter names and values for all optional parameters
* Generates a map of parameter names and values (assuming they are in the form []name=]value) for all optional parameters, comma-separated and separate optional parameters are treated equally.
* If a value does not have a name, the value will be the key in the hashmap mapping to the empty string.
*/
// Explicitly use a LinkedHashMap to preserve iteration order
fun getOptionalParameters(parameters: List<LatexParameter>): LinkedHashMap<String, String> {
val parameterMap = LinkedHashMap<String, String>()
// Parameters can be defined using multiple optional parameters, like \command[opt1][opt2]{req1}
// But within a parameter, there can be different content like [name={value in group}]
val parameterString = parameters.mapNotNull { it.optionalParam }
// extract the content of each parameter element
.flatMap { param ->
param.optionalParamContentList
}
.mapNotNull { content: LatexOptionalParamContent ->
// extract the content of each parameter element
.map { param ->
param.optionalParamContentList
}
.map { contentList ->
contentList.mapNotNull { content: LatexOptionalParamContent ->
// the content is either simple text
val text = content.parameterText
if (text != null) return@mapNotNull text.text
// or a group like in param={some value}
if (content.group == null) return@mapNotNull null
content.group!!.contentList.joinToString { it.text }
}
.joinToString(separator = "")
// Join different content types (like name= and {value}) together without separator
.joinToString("")
}
// Join different parameters (like [param1][param2]) together with separator
.joinToString(",")

if (parameterString.trim { it <= ' ' }.isNotEmpty()) {
for (parameter in parameterString.split(",")) {
Expand Down
14 changes: 14 additions & 0 deletions test/nl/hannahsten/texifyidea/psi/LatexPsiImplUtilTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -136,4 +136,18 @@ class LatexPsiImplUtilTest : BasePlatformTestCase() {

assertEquals("lst:listing", element.label)
}

@Test
fun testDefaultOptionalParameter() {
myFixture.configureByText(LatexFileType, """
% Second optional parameter of \newcommand makes the first parameter of \lvec optional with as default value 'n' (see LaTeX Companion page 845)
\newcommand{\lvec}[2][n]{\ensuremath{#2_1+\cdots + #2_{#1}}}
For the series \lvec{x} we have \[ \lvec{x} = \sum_{k=1}^{n} G_{\lvec[k]{y}} \]
""".trimIndent())

val psiFile = PsiDocumentManager.getInstance(myFixture.project).getPsiFile(myFixture.editor.document)!!
val element = psiFile.firstChildOfType(LatexCommands::class)!!
assertTrue("2" in element.optionalParameters)
assertTrue("n" in element.optionalParameters)
}
}