Skip to content

Commit de83635

Browse files
committed
feat(intellij): implemented support for 4 spaces tab
- this is enabled by default for robot files
1 parent 68bd93c commit de83635

20 files changed

+428
-160
lines changed

intellij-client/README.md

Lines changed: 26 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -6,29 +6,37 @@
66

77
<!-- Plugin description -->
88

9-
**RobotCode** is a PyCharm/IntelliJ Plugin that enhances your workflow with [Robot Framework](https://robotframework.org/).
10-
It provides a rich set of features to help you write, run, and debug your Robot Framework tests directly within your IDE.
11-
9+
**RobotCode** is a PyCharm/IntelliJ Plugin that enhances your workflow
10+
with [Robot Framework](https://robotframework.org/).
11+
It provides a rich set of features to help you write, run, and debug your Robot Framework tests directly within your
12+
IDE.
1213

1314
⚠️ **Important Notice** ⚠️
14-
This plugin is currently under active development and is not yet ready for production use. Please note that it may contain bugs or lack certain features.
15+
This plugin is currently under active development and is not yet ready for production use. Please note that it may
16+
contain bugs or lack certain features.
1517

16-
We invite you to join the Robot Framework and RobotCode community by reporting issues, suggesting features, and helping us improve the plugin.
18+
We invite you to join the Robot Framework and RobotCode community by reporting issues, suggesting features, and helping
19+
us improve the plugin.
1720

1821
Your feedback is greatly appreciated! 🙂
1922

20-
2123
## Why RobotCode?
2224

2325
**Built on Robot Framework Core**
24-
RobotCode is based on the Robot Framework Core and uses its parser, ensuring complete compatibility and consistency. This means you get the same syntax validation, error messages, and behavior as if you were running Robot Framework directly.
26+
RobotCode is based on the Robot Framework Core and uses its parser, ensuring complete compatibility and consistency.
27+
This means you get the same syntax validation, error messages, and behavior as if you were running Robot Framework
28+
directly.
2529

2630
**Powered by the Language Server Protocol**
27-
RobotCode is built on the Language Server Protocol (LSP), a modern standard for implementing language support across multiple editors and IDEs. This ensures a seamless and responsive user experience, while making it easier to maintain compatibility with evolving IDE features.
31+
RobotCode is built on the Language Server Protocol (LSP), a modern standard for implementing language support across
32+
multiple editors and IDEs. This ensures a seamless and responsive user experience, while making it easier to maintain
33+
compatibility with evolving IDE features.
2834

2935
**Powerful Command Line Tools**
30-
RobotCode extends the Robot Framework CLI with enhanced tools for test execution, analysis, and debugging. It supports [`robot.toml`](https://robotcode.io/03_reference/) configurations, integrates a Debug Adapter Protocol (DAP) compatible debugger, and provides an interactive REPL environment for experimenting with Robot Framework commands. Modular and flexible, these tools streamline your workflow for both development and production.
31-
36+
RobotCode extends the Robot Framework CLI with enhanced tools for test execution, analysis, and debugging. It supports [
37+
`robot.toml`](https://robotcode.io/03_reference/) configurations, integrates a Debug Adapter Protocol (DAP) compatible
38+
debugger, and provides an interactive REPL environment for experimenting with Robot Framework commands. Modular and
39+
flexible, these tools streamline your workflow for both development and production.
3240

3341
## Key Features
3442

@@ -37,31 +45,30 @@ RobotCode extends the Robot Framework CLI with enhanced tools for test execution
3745
- **Integrated Debugging**: Debug Robot Framework tests directly within the IDE.
3846
- **Test Management**: Discover, run, and monitor Robot Framework tests without leaving your IDE.
3947
- **Rich Test Reports**: View detailed test results and logs directly in the IDE.
40-
- **Code Analysis**: Leverage tools like [Robocop](https://robocop.readthedocs.io/) for linting and static code analysis.
48+
- **Code Analysis**: Leverage tools like [Robocop](https://robocop.readthedocs.io/) for linting and static code
49+
analysis.
4150
- **Formatting Made Easy**: Use [Robotidy](https://robotidy.readthedocs.io/) for consistent code formatting.
4251
- **Support for `robot.toml`**: Manage your Robot Framework projects with ease.
4352
- **More Features Coming Soon!**
4453

45-
4654
## Requirements
4755

4856
- Python 3.8 or newer
4957
- Robot Framework 4.1 or newer
5058
- PyCharm 2024.3.1 or newer
5159

52-
5360
## Getting Started
5461

5562
1. Install the [RobotCode Plugin](https://plugins.jetbrains.com/plugin/26216) from the JETBRAINS Marketplace.
5663
2. Configure your Robot Framework Python environment
5764
3. Start writing and running your Robot Framework tests!
5865

5966
(Comming soon...)
60-
For a more detailed guide, check out the [Let's get started](https://robotcode.io/02_get_started/) Guide on the [RobotCode](https://robotcode.io) website.
67+
For a more detailed guide, check out the [Let's get started](https://robotcode.io/02_get_started/) Guide on
68+
the [RobotCode](https://robotcode.io) website.
6169

6270
<!-- Plugin description end -->
6371

64-
6572
## Installation
6673

6774
- Using the IDE built-in plugin system:
@@ -71,9 +78,11 @@ For a more detailed guide, check out the [Let's get started](https://robotcode.i
7178

7279
- Using JetBrains Marketplace:
7380

74-
Go to [JetBrains Marketplace](https://plugins.jetbrains.com/plugin/26216) and install it by clicking the <kbd>Install to ...</kbd> button in case your IDE is running.
81+
Go to [JetBrains Marketplace](https://plugins.jetbrains.com/plugin/26216) and install it by clicking the <kbd>Install
82+
to ...</kbd> button in case your IDE is running.
7583

76-
You can also download the [latest release](https://plugins.jetbrains.com/plugin/26216/versions) from JetBrains Marketplace and install it manually using
84+
You can also download the [latest release](https://plugins.jetbrains.com/plugin/26216/versions) from JetBrains
85+
Marketplace and install it manually using
7786
<kbd>Settings/Preferences</kbd> > <kbd>Plugins</kbd> > <kbd>⚙️</kbd> > <kbd>Install plugin from disk...</kbd>
7887

7988
- Manually:

intellij-client/gradle.properties

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,5 +34,5 @@ org.gradle.configuration-cache = true
3434
org.gradle.caching = true
3535

3636

37-
kotlin.daemon.jvmargs=-Xmx4096m
38-
kotlin.code.style=official
37+
kotlin.daemon.jvmargs = -Xmx4096m
38+
kotlin.code.style = official
Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
distributionBase=GRADLE_USER_HOME
2-
distributionPath=wrapper/dists
3-
distributionUrl=https\://services.gradle.org/distributions/gradle-8.12-bin.zip
4-
networkTimeout=10000
5-
validateDistributionUrl=true
6-
zipStoreBase=GRADLE_USER_HOME
7-
zipStorePath=wrapper/dists
1+
distributionBase = GRADLE_USER_HOME
2+
distributionPath = wrapper/dists
3+
distributionUrl = https\://services.gradle.org/distributions/gradle-8.12-bin.zip
4+
networkTimeout = 10000
5+
validateDistributionUrl = true
6+
zipStoreBase = GRADLE_USER_HOME
7+
zipStorePath = wrapper/dists
Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
package dev.robotcode.robotcode4ij
22

33
import com.intellij.openapi.util.IconLoader
4-
import javax.swing.Icon
54

65
class RobotIcons {
76
companion object {
8-
val Resource: Icon? = IconLoader.findIcon("/images/robot.svg", Companion::class.java)
9-
val Suite: Icon? = IconLoader.findIcon("/images/robot.svg", Companion::class.java)
10-
val RobotCode: Icon? = IconLoader.findIcon("/images/robotcode.svg", Companion::class.java)
7+
val Resource = IconLoader.findIcon("/images/resource.svg", Companion::class.java)!!
8+
val Suite = IconLoader.findIcon("/images/suite.svg", Companion::class.java)!!
9+
val RobotCode = IconLoader.findIcon("/images/robotcode.svg", Companion::class.java)!!
10+
val Robot = IconLoader.findIcon("/images/suite.robot", Companion::class.java)!!
1111
}
1212

1313
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
package dev.robotcode.robotcode4ij.configuration
2+
3+
import com.intellij.psi.codeStyle.CodeStyleSettings
4+
import com.intellij.psi.codeStyle.CustomCodeStyleSettings
5+
6+
class RobotCodeCodeStyleSettings(container: CodeStyleSettings) :
7+
CustomCodeStyleSettings(RobotCodeCodeStyleSettings::class.java.simpleName, container) {
8+
@JvmField
9+
var use4SpacesIndentation: Boolean = true
10+
}
Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package dev.robotcode.robotcode4ij.settings
1+
package dev.robotcode.robotcode4ij.configuration
22

33
import com.intellij.application.options.CodeStyleAbstractConfigurable
44
import com.intellij.application.options.CodeStyleAbstractPanel
@@ -28,6 +28,9 @@ class RobotCodeCodeStyleSettingsProvider : CodeStyleSettingsProvider() {
2828
}
2929

3030
private class CodeStyleMainPanel(currentSettings: CodeStyleSettings, settings: CodeStyleSettings) :
31-
TabbedLanguageCodeStylePanel(RobotFrameworkLanguage, currentSettings, settings)
32-
31+
TabbedLanguageCodeStylePanel(RobotFrameworkLanguage, currentSettings, settings) {
32+
override fun initTabs(settings: CodeStyleSettings?) {
33+
addIndentOptionsTab(settings)
34+
}
35+
}
3336
}

intellij-client/src/main/kotlin/dev/robotcode/robotcode4ij/settings/RobotCodeColorSettingsPage.kt renamed to intellij-client/src/main/kotlin/dev/robotcode/robotcode4ij/configuration/RobotCodeColorSettingsPage.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package dev.robotcode.robotcode4ij.settings
1+
package dev.robotcode.robotcode4ij.configuration
22

33
import com.intellij.openapi.editor.colors.TextAttributesKey
44
import com.intellij.openapi.fileTypes.SyntaxHighlighter
@@ -22,6 +22,7 @@ class RobotCodeColorSettingsPage : ColorSettingsPage {
2222
AttributesDescriptor("Control flow", Colors.CONTROL_FLOW),
2323
AttributesDescriptor("Argument", Colors.ARGUMENT),
2424
AttributesDescriptor("Embedded argument", Colors.EMBEDDED_ARGUMENT),
25+
AttributesDescriptor("Named argument", Colors.NAMED_ARGUMENT),
2526
AttributesDescriptor("Variable", Colors.VARIABLE),
2627
AttributesDescriptor("Variable expression", Colors.VARIABLE_EXPRESSION),
2728
AttributesDescriptor("Variable begin", Colors.VARIABLE_BEGIN),
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
package dev.robotcode.robotcode4ij.configuration
2+
3+
import com.intellij.application.options.IndentOptionsEditor
4+
import com.intellij.application.options.SmartIndentOptionsEditor
5+
import com.intellij.lang.Language
6+
import com.intellij.openapi.project.Project
7+
import com.intellij.psi.PsiFile
8+
import com.intellij.psi.PsiFileFactory
9+
import com.intellij.psi.codeStyle.CodeStyleSettings
10+
import com.intellij.psi.codeStyle.CommonCodeStyleSettings
11+
import com.intellij.psi.codeStyle.CustomCodeStyleSettings
12+
import com.intellij.psi.codeStyle.LanguageCodeStyleSettingsProvider
13+
import dev.robotcode.robotcode4ij.RobotFrameworkLanguage
14+
import dev.robotcode.robotcode4ij.RobotSuiteFileType
15+
import javax.swing.JCheckBox
16+
17+
class RobotCodeLanguageCodeStyleSettingsProvider : LanguageCodeStyleSettingsProvider() {
18+
override fun getLanguage(): Language {
19+
return RobotFrameworkLanguage
20+
}
21+
22+
override fun getFileExt(): String {
23+
return "robot"
24+
}
25+
26+
override fun getIndentOptionsEditor(): IndentOptionsEditor {
27+
return object : SmartIndentOptionsEditor(this) {
28+
private lateinit var use4SpacesTabCheckBox: JCheckBox
29+
30+
override fun addComponents() {
31+
super.addComponents()
32+
use4SpacesTabCheckBox = JCheckBox("Use 4 spaces indentation")
33+
@Suppress("removal")
34+
add(use4SpacesTabCheckBox)
35+
}
36+
37+
override fun setEnabled(enabled: Boolean) {
38+
super.setEnabled(enabled)
39+
use4SpacesTabCheckBox.isEnabled = enabled
40+
}
41+
42+
override fun isModified(
43+
settings: CodeStyleSettings,
44+
options: CommonCodeStyleSettings.IndentOptions
45+
): Boolean {
46+
var result = super.isModified(settings, options)
47+
val settings = settings.getCustomSettings(RobotCodeCodeStyleSettings::class.java)
48+
result = result || isFieldModified(use4SpacesTabCheckBox, settings.use4SpacesIndentation)
49+
return result
50+
}
51+
52+
override fun apply(settings: CodeStyleSettings, options: CommonCodeStyleSettings.IndentOptions?) {
53+
super.apply(settings, options)
54+
settings.getCustomSettings(RobotCodeCodeStyleSettings::class.java).use4SpacesIndentation =
55+
use4SpacesTabCheckBox.isSelected
56+
}
57+
58+
override fun reset(settings: CodeStyleSettings, options: CommonCodeStyleSettings.IndentOptions) {
59+
super.reset(settings, options)
60+
val customSettings = settings.getCustomSettings(RobotCodeCodeStyleSettings::class.java)
61+
use4SpacesTabCheckBox.isSelected = customSettings.use4SpacesIndentation
62+
}
63+
}
64+
}
65+
66+
override fun createCustomSettings(settings: CodeStyleSettings): CustomCodeStyleSettings {
67+
return RobotCodeCodeStyleSettings(settings)
68+
}
69+
70+
override fun createFileFromText(project: Project, text: String): PsiFile? {
71+
return PsiFileFactory.getInstance(project).createFileFromText("dummy.robot", RobotSuiteFileType, text)
72+
}
73+
74+
override fun getCodeSample(settingsType: SettingsType): String {
75+
return """
76+
*** Settings ***
77+
Library SeleniumLibrary
78+
79+
*** Variables ***
80+
${'$'}{URL} http://example.com # a comment
81+
82+
*** Test Cases ***
83+
Example Test
84+
Open Application ${'$'}{URL}
85+
Log %{APP_DATA:unknown}
86+
Close Application
87+
88+
BDD Example Test
89+
Given application is open
90+
When I enter something into the Search Field
91+
Then Something Should Happen
92+
93+
*** Keywords ***
94+
Open Application
95+
[Arguments] ${'$'}{url}
96+
Open Browser ${'$'}{url}
97+
98+
Close Application
99+
Close Browser
100+
101+
*** Comments ***
102+
this is a comment block
103+
with multiple lines
104+
""".trimIndent()
105+
}
106+
107+
override fun customizeDefaults(
108+
commonSettings: CommonCodeStyleSettings,
109+
indentOptions: CommonCodeStyleSettings.IndentOptions
110+
) {
111+
indentOptions.INDENT_SIZE = 4
112+
indentOptions.USE_TAB_CHARACTER = false
113+
indentOptions.CONTINUATION_INDENT_SIZE = 4
114+
}
115+
}

intellij-client/src/main/kotlin/dev/robotcode/robotcode4ij/settings/ProjectSettingsConfigurableProvider.kt renamed to intellij-client/src/main/kotlin/dev/robotcode/robotcode4ij/configuration/RobotCodeProjectSettingsConfigurableProvider.kt

Lines changed: 14 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package dev.robotcode.robotcode4ij.settings
1+
package dev.robotcode.robotcode4ij.configuration
22

33
import com.google.gson.GsonBuilder
44
import com.google.gson.JsonElement
@@ -8,7 +8,7 @@ import com.intellij.openapi.components.SimplePersistentStateComponent
88
import com.intellij.openapi.components.State
99
import com.intellij.openapi.components.Storage
1010
import com.intellij.openapi.components.service
11-
import com.intellij.openapi.options.BoundSearchableConfigurable
11+
import com.intellij.openapi.options.BoundConfigurable
1212
import com.intellij.openapi.options.Configurable
1313
import com.intellij.openapi.options.ConfigurableProvider
1414
import com.intellij.openapi.project.Project
@@ -17,24 +17,21 @@ import com.intellij.ui.dsl.builder.AlignX
1717
import com.intellij.ui.dsl.builder.bindSelected
1818
import com.intellij.ui.dsl.builder.bindText
1919
import com.intellij.ui.dsl.builder.panel
20+
import dev.robotcode.robotcode4ij.configuration.SimplePersistentStateComponentHelper.delegate
21+
import dev.robotcode.robotcode4ij.configuration.SimplePersistentStateComponentHelper.stringDelegate
2022
import dev.robotcode.robotcode4ij.lsp.langServerManager
21-
import dev.robotcode.robotcode4ij.settings.SimplePersistentStateComponentHelper.delegate
22-
import dev.robotcode.robotcode4ij.settings.SimplePersistentStateComponentHelper.stringDelegate
2323

2424

25-
class ProjectSettingsConfigurableProvider(private val project: Project) : ConfigurableProvider() {
25+
class RobotCodeProjectSettingsConfigurableProvider(private val project: Project) : ConfigurableProvider() {
2626
override fun createConfigurable(): Configurable {
27-
return ProjectSettingsConfigurable(project)
27+
return RobotCodeProjectSettingsConfigurable(project)
2828
}
29-
3029
}
3130

3231

33-
class ProjectSettingsConfigurable(private val project: Project) : BoundSearchableConfigurable(
34-
"Robot Framework", "robotcode.robotframework.settings"
35-
) {
32+
class RobotCodeProjectSettingsConfigurable(private val project: Project) : BoundConfigurable("RobotCode") {
3633

37-
private val settings = ProjectSettings.getInstance(project)
34+
private val settings = RobotCodeProjectConfiguration.getInstance(project)
3835

3936
override fun createPanel(): DialogPanel {
4037
return panel {
@@ -49,8 +46,7 @@ class ProjectSettingsConfigurable(private val project: Project) : BoundSearchabl
4946
comboBox(listOf("default", "rpa", "norpa")).label("Mode")
5047
}.rowComment("Specifies robot execution mode. Corresponds to the `--rpa` or `--norpa` option of __robot__.")
5148
}
52-
group("Editing") {
53-
// TODO: not supported in IntelliJ
49+
group("Editing") { // TODO: not supported in IntelliJ
5450
// group("Editor") {
5551
// row {
5652
// checkBox("4 Spaces Tab").bindSelected(settings::editor4SpacesTab)
@@ -87,9 +83,10 @@ class ProjectSettingsConfigurable(private val project: Project) : BoundSearchabl
8783
}
8884

8985
@Service(Service.Level.PROJECT) @State(name = "ProjectSettings", storages = [Storage("robotcodeSettings.xml")])
90-
class ProjectSettings : SimplePersistentStateComponent<ProjectSettings.ProjectState>(ProjectState()) {
86+
class RobotCodeProjectConfiguration :
87+
SimplePersistentStateComponent<RobotCodeProjectConfiguration.ProjectState>(ProjectState()) {
9188
companion object {
92-
fun getInstance(project: Project): ProjectSettings = project.service()
89+
fun getInstance(project: Project): RobotCodeProjectConfiguration = project.service()
9390
}
9491

9592
fun asJson(): JsonElement {
@@ -123,13 +120,11 @@ data class InlayHints(
123120
)
124121

125122
data class Completion(
126-
var filterDefaultLanguage: Boolean = false,
127-
var headerStyle: String? = null
123+
var filterDefaultLanguage: Boolean = false, var headerStyle: String? = null
128124
)
129125

130126
data class All(
131-
var completion: Completion = Completion(),
132-
var inlayHints: InlayHints = InlayHints()
127+
var completion: Completion = Completion(), var inlayHints: InlayHints = InlayHints()
133128
)
134129

135130
data class RobotCodeSettings(
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package dev.robotcode.robotcode4ij.settings
1+
package dev.robotcode.robotcode4ij.configuration
22

33
import com.intellij.openapi.components.BaseState
44
import com.intellij.openapi.components.SimplePersistentStateComponent

0 commit comments

Comments
 (0)