diff --git a/Writerside/topics/Code-navigation.md b/Writerside/topics/Code-navigation.md
index 29c372f91..13860b36e 100644
--- a/Writerside/topics/Code-navigation.md
+++ b/Writerside/topics/Code-navigation.md
@@ -154,3 +154,19 @@ An example:
On Linux, the Mendeley format is also supported, which is of the form
`file = {:home/user/.local/share/data/Mendeley Ltd./Mendeley Desktop/Downloaded/filename.pdf:pdf;:home/user/.local/share/data/Mendeley Ltd./Mendeley Desktop/Downloaded/filename2.pdf:pdf}`
+
+## TODO view
+
+_Since b0.9.9_
+
+View | Tool Windows | TODO
+
+The TODO view by default shows all `todo` comments and `\todo{}` and `\missingfigure{}` commands.
+Highlighting of the commands in the IDE by default is currently not enabled due to API limitations, but can be achieved by adding the following patterns to File | Settings | Editor | TODO :
+
+ - `\\todo\b`, case sensitive is `true`
+ - `\\missingfigure\b`, case sensitive is `true`
+
+However, this adds the items to the tool window a second time.
+To avoid this, create a filter and include all patterns.
+Magic.
diff --git a/resources/META-INF/extensions/index.xml b/resources/META-INF/extensions/index.xml
index be6f9166a..459643e5e 100644
--- a/resources/META-INF/extensions/index.xml
+++ b/resources/META-INF/extensions/index.xml
@@ -17,5 +17,8 @@
+
+
+
\ No newline at end of file
diff --git a/src/nl/hannahsten/texifyidea/index/LatexTodoIndexPatternProvider.kt b/src/nl/hannahsten/texifyidea/index/LatexTodoIndexPatternProvider.kt
new file mode 100644
index 000000000..0a8a189a4
--- /dev/null
+++ b/src/nl/hannahsten/texifyidea/index/LatexTodoIndexPatternProvider.kt
@@ -0,0 +1,11 @@
+package nl.hannahsten.texifyidea.index
+
+import com.intellij.psi.search.IndexPattern
+import com.intellij.psi.search.IndexPatternProvider
+import nl.hannahsten.texifyidea.util.magic.CommandMagic
+
+class LatexTodoIndexPatternProvider : IndexPatternProvider {
+ override fun getIndexPatterns(): Array {
+ return CommandMagic.todoCommands.map { IndexPattern("${it.replace("\\", "\\\\")}\\b", true) }.toTypedArray()
+ }
+}
\ No newline at end of file
diff --git a/src/nl/hannahsten/texifyidea/index/LatexTodoIndexer.kt b/src/nl/hannahsten/texifyidea/index/LatexTodoIndexer.kt
new file mode 100644
index 000000000..7a758200e
--- /dev/null
+++ b/src/nl/hannahsten/texifyidea/index/LatexTodoIndexer.kt
@@ -0,0 +1,29 @@
+package nl.hannahsten.texifyidea.index
+
+import com.intellij.lexer.Lexer
+import com.intellij.psi.impl.cache.impl.BaseFilterLexer
+import com.intellij.psi.impl.cache.impl.OccurrenceConsumer
+import com.intellij.psi.impl.cache.impl.todo.LexerBasedTodoIndexer
+import nl.hannahsten.texifyidea.grammar.LatexLexerAdapter
+import nl.hannahsten.texifyidea.grammar.LatexTokenSets
+import nl.hannahsten.texifyidea.psi.LatexTypes
+import nl.hannahsten.texifyidea.util.magic.CommandMagic
+
+/**
+ * Counts the "to do" item, so that it shows up in the Project "to do" window and the count of the number of items is correct.
+ */
+class LatexTodoIndexer : LexerBasedTodoIndexer() {
+ override fun createLexer(consumer: OccurrenceConsumer): Lexer {
+ return LatexFilterLexer(consumer)
+ }
+}
+
+class LatexFilterLexer(consumer: OccurrenceConsumer) : BaseFilterLexer(LatexLexerAdapter(), consumer) {
+ override fun advance() {
+ val tokenType = delegate.tokenType
+ if (tokenType in LatexTokenSets.COMMENTS || (tokenType == LatexTypes.COMMAND_TOKEN && delegate.tokenText in CommandMagic.todoCommands)) {
+ advanceTodoItemCountsInToken()
+ }
+ delegate.advance()
+ }
+}
\ No newline at end of file
diff --git a/src/nl/hannahsten/texifyidea/index/LatexTodoSearcher.kt b/src/nl/hannahsten/texifyidea/index/LatexTodoSearcher.kt
new file mode 100644
index 000000000..8700da6f9
--- /dev/null
+++ b/src/nl/hannahsten/texifyidea/index/LatexTodoSearcher.kt
@@ -0,0 +1,36 @@
+package nl.hannahsten.texifyidea.index
+
+import com.intellij.openapi.application.QueryExecutorBase
+import com.intellij.openapi.util.TextRange
+import com.intellij.psi.PsiFile
+import com.intellij.psi.search.IndexPattern
+import com.intellij.psi.search.IndexPatternOccurrence
+import com.intellij.psi.search.searches.IndexPatternSearch
+import com.intellij.util.Processor
+import nl.hannahsten.texifyidea.file.LatexFile
+import nl.hannahsten.texifyidea.util.files.commandsInFile
+import nl.hannahsten.texifyidea.util.magic.CommandMagic
+import nl.hannahsten.texifyidea.util.matches
+
+/**
+ * Provides the "to do" item in the toolwindow.
+ */
+@Suppress("UnstableApiUsage")
+class LatexTodoSearcher : QueryExecutorBase() {
+ override fun processQuery(queryParameters: IndexPatternSearch.SearchParameters, consumer: Processor) {
+ val file = queryParameters.file as? LatexFile ?: return
+
+ queryParameters.patternProvider.indexPatterns.forEach { pattern ->
+ file.commandsInFile().filter { it.name in CommandMagic.todoCommands }.filter { pattern.pattern?.matches(it.name) == true }
+ .forEach {
+ consumer.process(LatexTodoOccurrence(file, it.textRange, pattern))
+ }
+ }
+ }
+}
+
+private data class LatexTodoOccurrence(private val file: LatexFile, private val textRange: TextRange, private val pattern: IndexPattern) : IndexPatternOccurrence {
+ override fun getFile(): PsiFile = file
+ override fun getTextRange(): TextRange = textRange
+ override fun getPattern(): IndexPattern = pattern
+}
\ No newline at end of file
diff --git a/src/nl/hannahsten/texifyidea/lang/LatexPackage.kt b/src/nl/hannahsten/texifyidea/lang/LatexPackage.kt
index 9847c4bfa..a03bf213d 100644
--- a/src/nl/hannahsten/texifyidea/lang/LatexPackage.kt
+++ b/src/nl/hannahsten/texifyidea/lang/LatexPackage.kt
@@ -86,6 +86,7 @@ open class LatexPackage @JvmOverloads constructor(
val TCOLORBOX = LatexPackage("tcolorbox")
val TEXTCOMP = LatexPackage("textcomp")
val TIKZ = LatexPackage("tikz")
+ val TODONOTES = LatexPackage("todonotes")
val ULEM = LatexPackage("ulem")
val VARIOREF = LatexPackage("varioref")
val WASYSYM = LatexPackage("wasysym")
diff --git a/src/nl/hannahsten/texifyidea/lang/commands/LatexRegularCommand.kt b/src/nl/hannahsten/texifyidea/lang/commands/LatexRegularCommand.kt
index b6a6ea0db..1d7f194f3 100644
--- a/src/nl/hannahsten/texifyidea/lang/commands/LatexRegularCommand.kt
+++ b/src/nl/hannahsten/texifyidea/lang/commands/LatexRegularCommand.kt
@@ -25,9 +25,10 @@ object LatexRegularCommand {
private val LISTINGS: Set = LatexListingCommand.entries.toSet()
private val LOREM_IPSUM: Set = LatexLoremIpsumCommand.entries.toSet()
private val GLOSSARY: Set = LatexGlossariesCommand.entries.toSet()
+ private val TODO: Set = LatexTodoCommand.entries.toSet()
val ALL: Set = GENERIC + TEXTCOMP + EURO + TEXT_SYMBOLS + NEW_DEFINITIONS + MATHTOOLS +
- XCOLOR + XPARSE + NATBIB + BIBLATEX + SIUNITX + ALGORITHMICX + IFS + LISTINGS + LOREM_IPSUM + GLOSSARY
+ XCOLOR + XPARSE + NATBIB + BIBLATEX + SIUNITX + ALGORITHMICX + IFS + LISTINGS + LOREM_IPSUM + GLOSSARY + TODO
private val lookup = HashMap>()
private val lookupDisplay = HashMap>()
diff --git a/src/nl/hannahsten/texifyidea/lang/commands/LatexTodoCommand.kt b/src/nl/hannahsten/texifyidea/lang/commands/LatexTodoCommand.kt
new file mode 100644
index 000000000..10b0f00d9
--- /dev/null
+++ b/src/nl/hannahsten/texifyidea/lang/commands/LatexTodoCommand.kt
@@ -0,0 +1,22 @@
+package nl.hannahsten.texifyidea.lang.commands
+
+import nl.hannahsten.texifyidea.lang.LatexPackage
+import nl.hannahsten.texifyidea.lang.LatexPackage.Companion.TODONOTES
+
+enum class LatexTodoCommand(
+ override val command: String,
+ override vararg val arguments: Argument = emptyArray(),
+ override val dependency: LatexPackage = LatexPackage.DEFAULT,
+ override val display: String? = null,
+ override val isMathMode: Boolean = false,
+ val collapse: Boolean = false
+) : LatexCommand {
+
+ TODO("todo", "note".asRequired(), dependency = TODONOTES),
+ MISSINGFIGURE("missingfigure", "note".asRequired(), dependency = TODONOTES),
+ LISTOFTODOS("listoftodos", "name".asOptional(), dependency = TODONOTES)
+ ;
+
+ override val identifier: String
+ get() = name
+}
\ No newline at end of file
diff --git a/src/nl/hannahsten/texifyidea/util/magic/CommandMagic.kt b/src/nl/hannahsten/texifyidea/util/magic/CommandMagic.kt
index e8cbb0f42..7eeec422f 100644
--- a/src/nl/hannahsten/texifyidea/util/magic/CommandMagic.kt
+++ b/src/nl/hannahsten/texifyidea/util/magic/CommandMagic.kt
@@ -17,6 +17,7 @@ import nl.hannahsten.texifyidea.lang.commands.LatexNatbibCommand.*
import nl.hannahsten.texifyidea.lang.commands.LatexNewDefinitionCommand.*
import nl.hannahsten.texifyidea.lang.commands.LatexOperatorCommand.*
import nl.hannahsten.texifyidea.lang.commands.LatexRegularCommand
+import nl.hannahsten.texifyidea.lang.commands.LatexTodoCommand
import nl.hannahsten.texifyidea.lang.commands.LatexUncategorizedStmaryrdSymbols.BIG_SQUARE_CAP
import nl.hannahsten.texifyidea.lang.commands.LatexXparseCommand.*
@@ -499,4 +500,9 @@ object CommandMagic {
val foldableFootnotes = listOf(
FOOTNOTE.cmd, FOOTCITE.cmd
)
+
+ /**
+ * Commands that should be contributed to the to do toolwindow.
+ */
+ val todoCommands = setOf(LatexTodoCommand.TODO.cmd, LatexTodoCommand.MISSINGFIGURE.cmd)
}
\ No newline at end of file