Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
13eebb5
create plugin settings - usages in later commits
Traben-0 Sep 29, 2025
307819a
merge `Versions` and `MainProject` functionality into new general `Pr…
Traben-0 Sep 29, 2025
cb39d3c
add general utils for retrieving directives
Traben-0 Sep 29, 2025
b605366
fixed and moved preprocessor condition checking logic into its own cl…
Traben-0 Sep 29, 2025
f6c14c5
added option to allow preprocessor blocks to be folded by default dep…
Traben-0 Sep 29, 2025
eccf095
use new version object
Traben-0 Sep 29, 2025
dfe9eeb
improve file jump action and dialog to be able to filter results via …
Traben-0 Sep 29, 2025
4edf40c
add preprocessor styling syntax highlights:
Traben-0 Sep 29, 2025
8359847
Merge branch 'Polyfrost:main' into main
Traben-0 Sep 29, 2025
5916d9e
fix caret position after jump action, also trigger a scroll to the ca…
Traben-0 Sep 30, 2025
7de227f
fix newline `//$$` only being placed in the line after directives
Traben-0 Sep 30, 2025
b0afbd5
Keyboard navigation: Down arrow focuses into the list from the search…
Traben-0 Sep 30, 2025
961e439
alternate highlighting
Traben-0 Oct 3, 2025
0ffe70b
fix kotlin folding
Traben-0 Oct 3, 2025
fdf6a68
ensure this util only runs on a psifile
Traben-0 Oct 3, 2025
3f93965
support grabbing the preprocessor version for certain additional PsiF…
Traben-0 Oct 3, 2025
39c0aea
no longer used util, prevSibling behaviour has proved inconsistent an…
Traben-0 Oct 3, 2025
e1fb704
add setting to disable PreprocessorNewLineHandler
Traben-0 Oct 3, 2025
4eb2775
restore order="first"
Traben-0 Oct 3, 2025
508ed2f
minor formatting
Traben-0 Oct 3, 2025
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
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,21 @@ package org.polyfrost.intelliprocessor.action
import com.intellij.openapi.actionSystem.AnActionEvent
import com.intellij.openapi.actionSystem.LangDataKeys
import com.intellij.openapi.actionSystem.PlatformDataKeys
import com.intellij.openapi.editor.Editor
import com.intellij.openapi.editor.ScrollType
import com.intellij.openapi.fileEditor.FileEditorManager
import com.intellij.openapi.fileEditor.TextEditor
import com.intellij.openapi.project.DumbAwareAction
import com.intellij.openapi.project.Project
import com.intellij.openapi.vfs.VfsUtil
import com.intellij.psi.PsiFile
import com.intellij.psi.PsiManager
import org.polyfrost.intelliprocessor.utils.*
import org.polyfrost.intelliprocessor.utils.PreprocessorVersion.Companion.preprocessorMainVersion
import java.nio.file.Path
import kotlin.io.path.relativeToOrNull

class PreprocessorFileJumpAction : DumbAwareAction() {
open class PreprocessorFileJumpAction : DumbAwareAction() {

private companion object {
private const val GROUP_ID = "Jump Failure"
Expand All @@ -32,7 +36,7 @@ class PreprocessorFileJumpAction : DumbAwareAction() {
val rootDirectory = findModuleDirForFile(currentPsiFile)
?.toPath()
?: return warning(project, "Could not find module directory for file")
val mainVersion = MainProject.get(currentPsiFile)
val mainVersion = currentPsiFile.preprocessorMainVersion
?: return warning(project, "Could not find mainProject. Is this a preprocessor project?")
val currentlyEditingFile = currentPsiFile.virtualFile?.toNioPath()
?: return warning(project, "Could not find file on disk")
Expand All @@ -55,8 +59,12 @@ class PreprocessorFileJumpAction : DumbAwareAction() {
val ideView = LangDataKeys.IDE_VIEW.getData(e.dataContext)
?: return warning(project, "Could not find IDE view")

val caret = editor.caretModel.currentCaret.visualPosition
SourceSetFileDialog(project, targets) { selected ->
val caret = editor.caretModel.currentCaret.offset

// For if the caret is inside a preprocessor conditional block, test each target version against the conditions
val foundConditionContext = testTargetsAgainstPreprocessorConditions(currentPsiFile, editor, targets)

SourceSetFileDialog(project, targets, foundConditionContext) { selected ->
val virtualFile = VfsUtil.findFile(rootDirectory.resolve(selected.toRelativePath()), true)
if (virtualFile == null) {
warning(
Expand All @@ -76,13 +84,28 @@ class PreprocessorFileJumpAction : DumbAwareAction() {
ideView.selectElement(psiFile)
val newEditor = FileEditorManager.getInstance(project).getSelectedEditor(virtualFile)
if (newEditor is TextEditor) {
newEditor.editor.caretModel.moveToVisualPosition(caret)
newEditor.editor.caretModel.moveToOffset(caret)
newEditor.editor.scrollingModel.scrollToCaret(ScrollType.CENTER)
} else {
warning(project, "Could not set cursor for non-text file")
}
}.show()
}

// If the caret is inside a preprocessor conditional block, test each target version against the conditions there
private fun testTargetsAgainstPreprocessorConditions(
file: PsiFile,
editor: Editor,
targets: List<SourceSetFile>
): Boolean {
val selectedPos = editor.caretModel.currentCaret.offset
val conditions = PreprocessorConditions.findEnclosingConditionsOrNull(selectedPos, file)
if (conditions != null) {
targets.forEach { it.metOpeningCondition = conditions.testVersion(it.version) }
}
return conditions != null
}

private fun getSourceSetFrom(path: List<Path>, mainVersion: String, rootDirectory: Path): SourceSetFile? {
if (path.size < 4) {
return null
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
package org.polyfrost.intelliprocessor.config

import com.intellij.openapi.options.Configurable
import javax.swing.BoxLayout
import javax.swing.JCheckBox
import javax.swing.JComponent
import javax.swing.JLabel
import javax.swing.JPanel
import javax.swing.border.EtchedBorder
import javax.swing.border.TitledBorder

class PluginConfigurable : Configurable {
private lateinit var panel: JPanel
private lateinit var foldInactiveBlocksByDefaultCheckbox: JCheckBox
private lateinit var foldAllBlocksByDefaultCheckbox: JCheckBox
private lateinit var inspectionHighlightNonIndentedNestedIfsCheckbox: JCheckBox
private lateinit var inspectionHighlightCommentsNotMatchingIfIndentsCheckbox: JCheckBox
private lateinit var hideUnmatchedVersionsCheckbox: JCheckBox
private lateinit var addPreprocessorCommentOnEnterCheckbox: JCheckBox


override fun getDisplayName(): String = "IntelliProcessor"

override fun createComponent(): JComponent {

// Setup components

fun <J : JComponent> J.tooltip(str: String): J = apply { toolTipText = str }

foldInactiveBlocksByDefaultCheckbox = JCheckBox("Fold inactive preprocessor blocks by default")
.tooltip("Automatically folds preprocessor blocks that are conditionally inactive. (E.G. 'MC>=1.20' blocks in a 1.19 file)")

foldAllBlocksByDefaultCheckbox = JCheckBox("Fold all preprocessor blocks by default").apply {
addChangeListener { event ->
// Disable the "fold inactive blocks" option if "fold all blocks" is enabled
foldInactiveBlocksByDefaultCheckbox.isEnabled = !(event.source as JCheckBox).isSelected
}
}

inspectionHighlightNonIndentedNestedIfsCheckbox =
JCheckBox("Highlight non-indented nested \"if\" preprocessor directives (Code clarity)")
.tooltip(
"Highlights nested \"if\" preprocessor directives that are not indented more than their enclosing preprocessor block.\n" +
"\nThis does not break preprocessing, but can help improve code clarity by visually indicating the nested structure of preprocessor blocks."
)

inspectionHighlightCommentsNotMatchingIfIndentsCheckbox =
JCheckBox("Highlight preprocessor comments not matching their \"if\"'s indent (Code clarity)")
.tooltip(
"Highlights preprocessor comments whose indent does not match the indent of the corresponding \"if\" directive.\n" +
"\nThis does not break preprocessing, but can help improve code clarity by visually linking preprocessor comments to their corresponding \"if\" directives."
)

hideUnmatchedVersionsCheckbox = JCheckBox("Hide results that do not meet preprocessor conditions at the caret")
.tooltip("Hides version results in the 'Jump To Pre-Processed File' dialog that do not match the current file's preprocessor conditions found at the caret position.")

addPreprocessorCommentOnEnterCheckbox = JCheckBox("Add preprocessor comment '//$$ ' automatically to new lines in a disabled preprocessor block")
.tooltip("When pressing Enter inside a disabled preprocessor block, automatically adds a preprocessor comment '//$$ ' to the new line.")

// Arrange components

fun titledBlock(str: String, block: JPanel.() -> Unit): JPanel = JPanel().apply {
border = TitledBorder(EtchedBorder(),str)
layout = BoxLayout(this, BoxLayout.Y_AXIS)
block()
}

panel = JPanel()

panel.apply {
layout = BoxLayout(this, BoxLayout.Y_AXIS)

add(titledBlock("Folding") {
add(foldAllBlocksByDefaultCheckbox)
add(foldInactiveBlocksByDefaultCheckbox)
})

add(titledBlock("Formatting") {
add(inspectionHighlightNonIndentedNestedIfsCheckbox)
add(inspectionHighlightCommentsNotMatchingIfIndentsCheckbox)
})

add(titledBlock("Jump To Pre-Processed File Action") {
add(hideUnmatchedVersionsCheckbox)
})

add(titledBlock("Misc") {
add(addPreprocessorCommentOnEnterCheckbox)
})

add(titledBlock("Info") {
add(JLabel("The keybinds can be configured from: Keymap > Plugins > IntelliProcessor"))
})
}

reset()
return panel
}

override fun isModified(): Boolean =
foldAllBlocksByDefaultCheckbox.isSelected != PluginSettings.instance.foldAllBlocksByDefault
|| foldInactiveBlocksByDefaultCheckbox.isSelected != PluginSettings.instance.foldInactiveBlocksByDefault
|| inspectionHighlightNonIndentedNestedIfsCheckbox.isSelected != PluginSettings.instance.inspectionHighlightNonIndentedNestedIfs
|| inspectionHighlightCommentsNotMatchingIfIndentsCheckbox.isSelected != PluginSettings.instance.inspectionHighlightCommentsNotMatchingIfIndents
|| hideUnmatchedVersionsCheckbox.isSelected != PluginSettings.instance.hideUnmatchedVersions
|| addPreprocessorCommentOnEnterCheckbox.isSelected != PluginSettings.instance.addPreprocessorCommentOnEnter

override fun apply() {
PluginSettings.instance.foldAllBlocksByDefault = foldAllBlocksByDefaultCheckbox.isSelected
PluginSettings.instance.foldInactiveBlocksByDefault = foldInactiveBlocksByDefaultCheckbox.isSelected
PluginSettings.instance.inspectionHighlightNonIndentedNestedIfs = inspectionHighlightNonIndentedNestedIfsCheckbox.isSelected
PluginSettings.instance.inspectionHighlightCommentsNotMatchingIfIndents = inspectionHighlightCommentsNotMatchingIfIndentsCheckbox.isSelected
PluginSettings.instance.hideUnmatchedVersions = hideUnmatchedVersionsCheckbox.isSelected
PluginSettings.instance.addPreprocessorCommentOnEnter = addPreprocessorCommentOnEnterCheckbox.isSelected
}

override fun reset() {
foldAllBlocksByDefaultCheckbox.isSelected = PluginSettings.instance.foldAllBlocksByDefault
foldInactiveBlocksByDefaultCheckbox.isSelected = PluginSettings.instance.foldInactiveBlocksByDefault
inspectionHighlightNonIndentedNestedIfsCheckbox.isSelected = PluginSettings.instance.inspectionHighlightNonIndentedNestedIfs
inspectionHighlightCommentsNotMatchingIfIndentsCheckbox.isSelected = PluginSettings.instance.inspectionHighlightCommentsNotMatchingIfIndents
hideUnmatchedVersionsCheckbox.isSelected = PluginSettings.instance.hideUnmatchedVersions
addPreprocessorCommentOnEnterCheckbox.isSelected = PluginSettings.instance.addPreprocessorCommentOnEnter
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package org.polyfrost.intelliprocessor.config

import com.intellij.openapi.components.PersistentStateComponent
import com.intellij.openapi.components.Service
import com.intellij.openapi.components.State
import com.intellij.openapi.components.Storage
import com.intellij.openapi.components.service

@State(name = "IntelliProcessor", storages = [Storage("IntelliProcessor.xml")])
@Service
class PluginSettings : PersistentStateComponent<PluginSettings> {
var foldAllBlocksByDefault: Boolean = false
var foldInactiveBlocksByDefault: Boolean = true
var inspectionHighlightNonIndentedNestedIfs: Boolean = true
var inspectionHighlightCommentsNotMatchingIfIndents: Boolean = true
var hideUnmatchedVersions: Boolean = false
var addPreprocessorCommentOnEnter = true

override fun getState(): PluginSettings = this

override fun loadState(state: PluginSettings) {
this.foldAllBlocksByDefault = state.foldAllBlocksByDefault
this.foldInactiveBlocksByDefault = state.foldInactiveBlocksByDefault
this.inspectionHighlightNonIndentedNestedIfs = state.inspectionHighlightNonIndentedNestedIfs
this.inspectionHighlightCommentsNotMatchingIfIndents = state.inspectionHighlightCommentsNotMatchingIfIndents
this.hideUnmatchedVersions = state.hideUnmatchedVersions
this.addPreprocessorCommentOnEnter = state.addPreprocessorCommentOnEnter
}

companion object {
val instance: PluginSettings
get() = service()

// Helper to modify settings and correctly persist changes
fun modify(action: PluginSettings.() -> Unit) {
val settings = PluginSettings().also { it.loadState(instance) }
settings.action()
instance.loadState(settings) // Pass changes back to instance via loadState() to persist
}
}
}

This file was deleted.

Loading
Loading