<orderEntry type="module" module-name="intellij.javascript.psi.impl" />
<orderEntry type="module" module-name="intellij.platform.testFramework" scope="TEST" />
<orderEntry type="module" module-name="intellij.platform.statistics" />
+ <orderEntry type="module" module-name="intellij.platform.tasks.impl" />
</component>
</module>
\ No newline at end of file
--- /dev/null
+### Ths file contains strings from lessons.
+
+###############################################################################
+## Common lessons
+###############################################################################
+
+## Editor basics module
+
+goto.action.lesson.name=Search for actions
+goto.action.mac.workaround=\nIf <strong>Terminal</strong> search opens instead of {0}, refer to \
+ <a href="{1}">this article</a>.
+goto.action.use.find.action=One of the most useful shortcuts is {0}. It lets you search through all available \
+ actions without having to know their individual shortcuts. Try it now with {1}.
+goto.action.about.word=about
+goto.action.invoke.about.action=Let''s say you want to learn about the IDE, type {0} and press {1}.
+goto.action.to.return.to.the.editor=Hit {0} to return to the editor.
+goto.action.invoke.again={0} can also be used to change the settings, invoke it again now.
+goto.action.show.line.input.required=show line
+goto.action.show.line.numbers.request=Type {0} to see {1} selector.
+goto.action.first.lines.toggle=Switch the line numbers {0, choice, 0#off|1#on}.
+goto.action.second.lines.toggle=Now switch the line numbers back {0, choice, 0#on|1#off}.
+goto.action.propose.to.go.next=Awesome! Click the button below to start the next lesson, or use {0}.
+
+collapse.lesson.name=Collapse
+collapse.try.collapse=Sometimes you need to collapse a piece of code for better readability. Try to collapse a code fragment with {0}.
+collapse.hit.expand=To expand a code region, hit {0}.
+collapse.all.collapse=If you want to collapse all regions in the file, use {0}.
+collapse.all.expand=Similarly, press {0} to expand all available regions.
+
+duplicate.and.delete.lines.lesson.name=Duplicate and delete lines
+duplicate.and.delete.lines.duplicate.line=Duplicate any line with {0}.
+duplicate.and.delete.lines.duplicate.several.lines=You can do the same action with multiple lines, too. \
+ Simply select two or more lines and duplicate them with {0}.
+duplicate.and.delete.lines.delete.line=To delete the current line you can use action {0}.
+
+move.lesson.name=Move
+move.pull.down=Rearranging lines usually takes two actions: cut and paste. \
+ In this IDE, you can do it with just one. Press {0} to pull down the current line.
+move.pull.up=Similarly, to pull a line up, use {0}.
+move.whole.method.up=Now try to move the whole method up with {0}.
+move.whole.method.down=And move it down with {0}.
+
+multiple.selections.lesson.name=Multiple selections
+multiple.selections.select.symbol=Press {0} to select the symbol at the caret.
+multiple.selections.select.next.symbol=Press {0} again to select the next occurrence of this symbol.
+multiple.selections.deselect.symbol=Press {0} to deselect the last occurrence.
+multiple.selections.select.all=Press {0} to select all occurrences in the file.
+multiple.selections.replace=Type {0} to replace all occurrences of {1} with {0}.
+
+selection.lesson.name=Expand and shrink the code selection
+selection.select.word=Place the caret before any word. Press {0} to move the caret to the next word and select everything in between.
+selection.extend.selection=Press {0} to extend the selection to the next code block.
+selection.extend.until.whole.file=Try to increase your selection with {0} until your whole file is selected.
+selection.shrink.selection={0} shrinks selection. Try pressing it.
+
+comment.line.lesson.name=Comment line
+comment.line.comment.any.line=Comment out any line with {0}.
+comment.line.uncomment.that.line=Uncomment the commented line with the same shortcut, {0}.
+comment.line.comment.several.lines=Select several lines and then comment them with {0}.
+
+surround.and.unwrap.lesson.name=Surround and unwrap
+surround.and.unwrap.invoke.surround=Press {0} to surround the selected code fragment with some template code.
+surround.and.unwrap.choose.surround.item=Choose {0} item.
+surround.and.unwrap.invoke.unwrap=Let''s return to the initial file with unwrapping action by {0}.
+surround.and.unwrap.item=Unwrap {0}
+surround.and.unwrap.choose.unwrap.item=Choose {0} item.
+
+## Completion module
+
+basic.completion.lesson.name=Basic completion
+basic.completion.start.typing=By default, the IDE proposes completion for your code instantly. \
+ Start typing {0} right where the caret is, and you will see the Lookup Menu with matching suggestions.
+basic.completion.continue.typing=Continue typing {0} unless it becomes the first item.
+basic.completion.just.press.to.complete=Now just press {0} to complete this statement.
+basic.completion.activate.explicitly=To activate Basic Completion explicitly, press {0}.
+basic.completion.finish.explicit.completion=Select {0} and press {1}.
+
+completion.with.tab.lesson.name=Completion with tab
+completion.with.tab.begin.completion=Press {0} to show completion options.
+completion.with.tab.finish.with.tab=Choose {0}, for example, and press {1}. \
+ This overwrites the word at the caret rather than simply inserting it.
+
+postfix.completion.lesson.name=Postfix completion
+postfix.completion.type.template=The IDE can offer postfix shortcuts. Type {0}.
+
+rename.lesson.name=Rename
+
+refactoring.menu.lesson.name=Refactoring menu
+
+## Navigation module
+
+declaration.and.usages.lesson.name=Declaration and usages
+declaration.and.usages.jump.to.declaration=Use {0} to jump to the declaration of {1, choice, 0#a method|1#an attribute accessor}.
+declaration.and.usages.show.usages=Now the caret is at the {0, choice, 0#method|1#attribute accessor} declaration. \
+ Use the same shortcut {1} to see all of its usages, then select one of them.
+declaration.and.usages.find.usages=Use {0} to see a more detailed view of usages. You can invoke {0} on either a declaration or usage.
+declaration.and.usages.pin.motivation=From the {0} view you can navigate to both usages and declarations. \
+ The next search will override these results in the {0} view. To prevent it, pin the results:
+declaration.and.usages.tab.name=Usages of
+declaration.and.usages.right.click.tab=Right click the tab title, {0}.
+declaration.and.usages.select.pin.item=Select {0}.
+declaration.and.usages.hide.view=When you have finished browsing usages, use {0} to hide the view.
+declaration.and.usages.open.find.view=Press {0} to open the {1} view again.
+
+file.structure.lesson.name=File structure
+file.structure.open.popup=A large source file can be difficult to read and navigate, sometimes you only need an overview of the file. \
+ Use {0} to see the file structure.
+file.structure.request.prefixes=Suppose you want to find some method with {0} and {1} words in its name. \
+ Type {2} (prefixes of required words) to filter file structure.
+file.structure.navigate=Only one item remains. Now press {0} to jump to the selected item.
+file.structure.toolwindow=The IDE can also show you the file structure as a tool window. Open it with {0}.
+
+extract.method.lesson.name=Extract method
+extract.method.invoke.action=Press {0} to extract the selected code block into a method.
+extract.method.start.refactoring=Click {0} to start refactoring.
+extract.method.confirm.several.replaces=Cocktail Sort has two swap places. The first fragment has just been extracted. \
+ Click {0} to extract both of them.
+extract.method.second.fragment=Now you can confirm or reject the replacement of the second fragment.
+
+extract.variable.lesson.name=Extract variable
+extract.variable.start.refactoring=Press {0} to extract a local variable from the selected expression {1}.
+extract.variable.replace.all=This code block contains 3 occurrences of the selected expression. \
+ Choose the second item on the list to replace all of them.
+extract.variable.choose.name=Choose a name for the new variable or leave it as it is. Press {0} to complete the refactoring.
+
+## Run/Debug module
+
+run.configuration.lesson.name=Run configuration
+run.configuration.hide.toolwindow=IDE automatically opened {0} tool window. \
+ Just a tip, at the top of {0} tool window you can see the full runned command. Now let\u2019s hide the tool window with {1}.
+run.configuration.temporary.to.permanent=For each new run IDE create temporary run configuration. \
+ Temporary configurations are automatically deleted if the default limit of 5 is reached. \
+ Lets convert temporary configuration into permanent one. Open the drop-down menu with run configuration.
+run.configuration.select.save.configuration=Select {0}.
+run.configuration.edit.configuration=Suppose you want to change configuration or create another one manually. \
+ Then you need to open the the drop-down menu again and click {0}. Alternatively you can use {1} action.
+run.configuration.settings.description=This is a place for managing run/debug configurations. \
+ You can set here program parameters, JVM arguments, environment variables and so on.
+run.configuration.tip.about.save.configuration.into.file=Just a tip. Sometimes you may want to save configuration to its own file. \
+ Such configurations will be easy to share between colleagues (usually by version control system). \
+ Now close the settings dialog to finish this lesson.
+
+debug.workflow.lesson.name=Debug workflow
+debug.workflow.incorrect.breakpoints=Breakpoints are set incorrect for this lesson.
+debug.workflow.run.program=Before debugging let''s run the program and see what is going wrong {0}.
+debug.workflow.toggle.breakpoint=So there is a problem. Let''s start investigation with placing breakpoint. \
+ To toggle a breakpoint you should click left editor gutter or just press {0}.
+debug.workflow.start.debug=To start debug selected run configuration you need to click at {0}. Or you can just press {1}.
+debug.workflow.return.to.editor=Many trace actions will focus debug toolwindow. Let''s return to the editor with {0}.
+debug.workflow.use.watches=IDE has several ways to show values. For this step, we selected the call. Lets add it to {0}. \
+ You can copy the expression into clipboard, use {1} button on the debug panel and paste copied text. Or you can just use action {2} {3}.
+debug.workflow.consider.to.add.a.shortcut=(consider to add a shortcut for it later)
+debug.workflow.step.into=Lets step into. You can use action {0} or the button {1} at the debug panel.
+debug.workflow.choose.method.to.step.in=In most cases you will want to skip argument calculating so Smart Step Into feature suggest by \
+ default the wrapping method. But here we need to choose the second one: {0}. \
+ You can choose it by keyboard {1} and press {2} or you can click the call by mouse.
+debug.workflow.quick.evaluate=Lets see what we are going to pass to {0}. We selected the argument. Invoke Quick Evaluate Expression {1}.
+debug.workflow.fix.error=Oh, we made a mistake in the array index! Lets fix it right now. Close popup ({0}) and change 0 to 1.
+debug.workflow.step.over=Let''s check that the call of {0} will not throw an exception now. Use Step Over action {1} or click the button {2}.
+debug.workflow.mute.breakpoints=Ups, same breakpoint again. Now we don''t need to stop at this breakpoint. \
+ So let''s mute breakpoints by the button {0} or by action {1}.
+debug.workflow.run.to.cursor=Let''s check the result of {0}. We''ve moved the editor cursor to the {1} statement. \
+ Let''s use {2} or click {3}. Note that {4} works even if breakpoints are muted.
+debug.workflow.evaluate.expression=It seems the {0} is not an average we want to find. We forgot to divide by length. \
+ Seems we need to return {1}. Let''s check the guess. Press {2} or click button {3}.
+debug.workflow.type.result=Type {0} into the {1} field, completion works.
+debug.workflow.evaluate.it=Hit {0} or click {1}.
+debug.workflow.stop.debug=It will be a correct answer! Lets close the dialog and stop debugging by {0} or button {1}.
+debug.workflow.resume=Seems no exceptions by now. Let''s continue execution with {0} or click the button {1}.
+
+###############################################################################
+## Java lessons
+###############################################################################
+
+java.basic.completion.choose.first=You can choose the first item from the Lookup menu by pressing {0}.
+java.basic.completion.activate=To activate Basic Completion, press {0} and you will see lookup menu again.
+java.basic.completion.choose.item=Select {0} inside the lookup menu and press {1}.
+java.basic.completion.complete=Press {0} to complete this statement.
+java.basic.completion.deeper.level=Sometimes you need to see suggestions for static constants or methods. \
+ Press {0} twice to access a deeper level of Code Completion.
+
+java.run.configuration.lets.run=Any code marked with {0} can be run. Let''s run our simple example with {1}. \
+ Alternatively you can click at {0} and select {2} item.
+
+java.postfix.completion.apply=Postfix Completion helps reduce backward caret jumps as you write code. \
+ It lets you transform an already typed expression into another one based on the postfix you add, the type of expression, and its context. \
+ Type {0} after the parenthesis to see the list of postfix completion suggestions. \
+ Select {1} from the list, or type it in editor, and then press {2} to complete the statement.
+
+java.smart.type.completion.lesson.name=Smart type completion
+java.smart.type.completion.apply=Smart Type Completion filters the list of suggestion to include only those types that are applicable in \
+ the current context. Press {0} to see the list of matching suggestions. Choose the first one by pressing {1}.
+java.smart.type.completion.return=Smart Type Completion can also suggest code for a return statement. \
+ Press {0} twice to see the Lookup menu for a return. Choose the first one by pressing {1}
+
+java.statement.completion.lesson.name=Statement completion
+java.statement.completion.complete.for=Press {0} to complete the {1} statement.
+java.statement.completion.complete.if=Write {0} and press {1} to generate the statement.
+java.statement.completion.complete.condition=Add a condition inside parentheses {0} and press {1} to jump inside the {2} statement.
+java.statement.completion.complete.finish.body=Write on one line: {0} and then press {1} to complete the entered statement and apply formatting.
+
+java.debug.workflow.rebuild=For big programs rerun can take too much time. When you find some mistake in pure method you can just rebuild \
+ the project and apply <strong>Hot Swap</strong> JVM feature. Let''s build project: {0} or {1}.
+java.debug.workflow.confirm.hot.swap=Confirm <strong>Hot Swap</strong> replacement
+java.debug.workflow.drop.frame=We patched our method, but right now we are still executing old obsolete {0} and it will throw the \
+ exception again. Let''s drop the frame and return to the state before {1} call. Click {2} at the debug panel or use {3}.
+
+###############################################################################
+## Python lessons
+###############################################################################
+
+python.f.string.completion.lesson.name=F-string completion
+python.f.string.completion.type.prefix=PyCharm supports automatic f-string conversion. Just start to type {0}
+python.f.string.completion.invoke.manually=You can invoke completion manually with {0}
+python.f.string.completion.complete.it=Complete the statement with {0}. Just press {1} to apply the first item.
+python.f.string.completion.result.message=You may see that simple Python string was replaced by f-string after the completion.
+
+python.postfix.completion.select.item=Select {0} item from completion list.
+
+python.smart.completion.lesson.name=Smart completion
+python.smart.completion.try.basic.completion=Try to use Basic Completion by pressing {0}.
+python.smart.completion.use.smart.completion=Unfortunately IDE has no direct information about {0} type. \
+ But sometimes it can guess completion by the context! Use {1} to invoke Smart Completion.
+python.smart.completion.finish.completion=Now just choose {0} item to finish this lesson.
+
+python.tab.completion.lesson.name=Tab completion
+python.tab.completion.start.completion=Suppose you want to replace {0} with {1}. Invoke completion by pressing {2}.
+python.tab.completion.select.item=Select item {0} by keyboard arrows or just start typing it.
+python.tab.completion.use.tab.completion=If you press {0} you will insert {1} before {2}. Instead press {3} to replace {2} with {1}.
+
+python.search.everywhere.lesson.name=Search everywhere
+python.search.everywhere.invoke.search.everywhere=To open {0} you need to press {1} two times in a row.
+python.search.everywhere.type.prefixes=Suppose you are looking for a class with {0} and {1} words in the name. \
+ Type {2} (prefixes of required words) to the search field.
+python.search.everywhere.preview=We found {0}. Now you can preview the found item. Just select it by keyboard arrows and press {1}.
+python.search.everywhere.navigate.to.class=Press {0} to navigate to {1}.
+python.search.everywhere.goto.class=Use {0} to find class faster or in special places.
+python.search.everywhere.type.node.visitor=Suppose you need some library class responsible for visiting nodes. Type {0}.
+python.search.everywhere.use.all.places=Now you see a class inside this demo project. \
+ Lets Switch {0} filter to {1} and you will see available library variants.
+python.search.everywhere.quick.documentation=Use {0} to quickly look at available documentation.
+python.search.everywhere.finish=<strong>Done!</strong> In the same way you can use {0} to look for a method or global variable and use {1} \
+ to look for a file.
+
+python.in.place.refactoring.lesson.name=In-place refactoring
+python.in.place.refactoring.start.type.new.name=Let''s consider an alternative approach to performing refactorings. \
+ Suppose we want to rename local variable {0} to {1}. Just start typing the new name.
+python.in.place.refactoring.invoke.intentions=IDE is guessing that you are going to rename the variable. \
+ You can notice it by the icon {0} in the left editor gutter. Invoke intentions by {1} when you finish to type the new name.
+python.in.place.refactoring.finish.rename=Press {0} to finish rename.
+python.in.place.refactoring.add.parameter=Let''s add an argument to this method. We place the editor caret just after the first parameter. \
+ Now type comma and parameter''s name: {0}.
+python.in.place.refactoring.invoke.intention.for.parameter=IDE is guessing that you are going to change the method signature. \
+ You can notice it by the same icon {0} at the left editor gutter. Invoke intentions by {1} when you finish typing the new parameter.
+python.in.place.refactoring.update.callers=Press {0} to update the callers.
+python.in.place.refactoring.signature.preview=IDE is showing you the short signature preview. Press {0} to continue.
+python.in.place.refactoring.set.default.value=Now you need to type the value which will be inserted as an argument into the each call. \
+ You can choose {0} for this sample. Then press {1} to continue.
+python.in.place.refactoring.remark.about.application.scope=A small note for the end. In-place refactoring may be applied only in the \
+ definition point whiles direct invocation of rename or change-signature refactorings may be called from both definition and usage.
+
+python.quick.fix.refactoring.lesson.name=Quick fix refactoring
+python.quick.fix.refactoring.type.new.argument=Several refactorings can be performed as quick fixes. \
+ Suppose we want to add a parameter to the method {0} and pass the variable {1} to it. Let''s type {2} after the first argument.
+python.quick.fix.refactoring.wait.completion.showed=Wait a little bit for the completion list...
+python.quick.fix.refactoring.close.completion.list=For now, we don''t want to apply any completion. Close the list ({0}).
+python.quick.fix.refactoring.invoke.intentions=As you may notice, IDE is showing you a warning here. Let''s invoke intentions by {0}.
+python.quick.fix.refactoring.choose.change.signature=Choose {0} quick fix.
+python.quick.fix.refactoring.select.new.parameter=Let''s set the default value for the new parameter. Click at the new parameter line. \
+ Alternatively, you can set focus to the parameter without mouse by {0} and then {1}.
+python.quick.fix.refactoring.set.default.value=You may navigate through the fields (and the checkbox) by using {0}. With the checkbox you can let IDE inline the default value to the other callers or set it as the default value for the new parameter. The Signature Preview will help understand the difference. Now set the default value as 0.
+python.quick.fix.refactoring.finish.refactoring=Press {0} (or click {1} to finish the refactoring.
+
+python.refactoring.menu.show.refactoring.list=PyCharm supports a variety of refactorings. Many of them have own shortcuts. But for rare refactorings you can use {0} and see a partial list of them.
+python.refactoring.menu.required.prefix=pa
+python.refactoring.menu.introduce.parameter=Suppose we want to replace this expression with a parameter. So we need to choose {0}. Now simply type {1} (as prefix of needed refactoring name) to reduce proposed list.
+python.refactoring.menu.start.refactoring=Press {0} to start Introduce Parameter refactoring.
+python.refactoring.menu.finish.refactoring=To complete refactoring, you need to choose some name or leave it as default and press {0}.
+
+python.rename.press.rename=Press {0} to rename field {1} (e.g., to {2}).
+python.rename.expand.dynamic.references=In simple cases PyCharm will just rename without confirmation. But in this sample PyCharm sees two calls of {0} method for objects with unknown type. Expand {1} item.
+#TODO: This prefix can be got from some general bundle when "Dynamic" will be extracted from `BaseRefactoringProcessor.createPresentation`
+python.rename.dynamic.references.prefix=Dynamic references
+python.rename.exclude.item=It seems {0} should be excluded from rename. Select it and press {1}.
+python.rename.finish.refactoring=Now just finish the rename with the {0} button.
+
+python.run.configuration.lets.run=Let''s run our simple example with {0}.
+
+python.debug.workflow.rerun=Let''s rerun our program. Just click again at {0} or use {1}.
+
+###############################################################################
+## Ruby lessons
+###############################################################################
+
+ruby.hippie.completion.lesson.name=Hippie Completion
+ruby.hippie.completion.invoke.hippie.completion=Sometimes you need to complete a word by textual similarity. Press {0} to invoke hippie completion.
+ruby.hippie.completion.repeat.one.time=You can repeat {0} until the desired word is found. Try it once more now.
+ruby.hippie.completion.return.previous=You can return to the previous variant with {0}. Use it now.
+
+ruby.postfix.completion.apply=Now just press {0} to choose the first postfix template.
+ruby.postfix.completion.choose.target=Now choose the second item, {0}.
+
+ruby.class.search.lesson.name=Class Search
+ruby.class.search.invoke.goto.class=Try to find a class with {0}
+ruby.class.search.type.word=Type {0} to see classes that contain the word {1}.
+ruby.class.search.type.second.prefix=You can search for a class by part of its name. Type {0} (the search string will be {1}) to see classes that contain the words {2} and {3}.
+ruby.class.search.preview=To check the selected class before navigating to it, you can use {0} to see its quick definition.
+ruby.class.search.navigate.to.target=Suppose you are looking for {0}.Choose it and then press {1} to navigate.
+
+ruby.refactoring.menu.invoke.refactoring.list=RubyMine supports a variety of refactorings. Press {0} to see a partial list of them.
+ruby.refactoring.menu.use.push.method.down=Some refactorings are seldom used and have no shortcut, but you can find them here. Choose {0} now and complete the refactoring on {1}.
+
+ruby.rename.start.refactoring=Press {0} to rename the attribute accessor {1} (e.g., to {2}).
+ruby.rename.confirm=In order to be confident about the refactoring, RubyMine lets you preview it before confirming.Click {0} to complete the refactoring.
+
import com.intellij.util.ui.tree.TreeUtil
import org.fest.swing.timing.Timeout
import org.intellij.lang.annotations.Language
+import org.jetbrains.annotations.Nls
import training.learn.LearnBundle
import training.learn.lesson.kimpl.LessonUtil
import training.ui.LearningUiHighlightingManager
/**
* Write a text to the learn panel (panel with a learning tasks).
*/
- abstract fun text(@Language("HTML") text: String)
+ abstract fun text(@Language("HTML") @Nls text: String)
/** Write a text to the learn panel (panel with a learning tasks). */
- abstract fun runtimeText(callback: TaskRuntimeContext.() -> String?)
+ abstract fun runtimeText(@Nls callback: TaskRuntimeContext.() -> String?)
/** Simply wait until an user perform particular action */
abstract fun trigger(actionId: String)
return "<code>${StringUtil.escapeXmlEntities(sourceSample)}</code>"
}
+ /** Highlight some [text] */
+ open fun strong(text: String): String {
+ return "<strong>${StringUtil.escapeXmlEntities(text)}</strong>"
+ }
+
/** Show an [icon] inside lesson step message */
open fun icon(icon: Icon): String {
val index = LearningUiManager.getIconIndex(icon)
--- /dev/null
+// Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
+package training.learn
+
+import com.intellij.DynamicBundle
+import org.jetbrains.annotations.Nls
+import org.jetbrains.annotations.NonNls
+import org.jetbrains.annotations.PropertyKey
+
+@NonNls
+private const val BUNDLE = "messages.LessonsBundle"
+
+object LessonsBundle : DynamicBundle(BUNDLE) {
+ @Nls
+ fun message(@PropertyKey(resourceBundle = BUNDLE) key: String, vararg params: Any): String = getMessage(key, *params)
+
+ @Nls
+ fun messagePointer(@PropertyKey(resourceBundle = BUNDLE) key: String,
+ vararg params: Any): java.util.function.Supplier<String> = getLazyMessage(key, *params)
+}
\ No newline at end of file
// Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package training.learn.interfaces
+import org.jetbrains.annotations.Nls
+import org.jetbrains.annotations.NonNls
import training.commands.kotlin.TaskTestContext
import training.learn.lesson.LessonListener
import training.learn.lesson.LessonState
interface Lesson {
- val name: String
+ val name: @Nls String
- val id: String
+ val id: @NonNls String
/** This name will be used for generated file with lesson sample */
val fileName: String
// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package training.learn.lesson.general
+import training.learn.LessonsBundle
import training.learn.interfaces.Module
import training.learn.lesson.kimpl.KLesson
import training.learn.lesson.kimpl.LessonContext
import training.learn.lesson.kimpl.LessonSample
class CollapseLesson(module: Module, lang: String, private val sample: LessonSample)
- : KLesson("Collapse", "Collapse", module, lang) {
+ : KLesson("Collapse", LessonsBundle.message("collapse.lesson.name"), module, lang) {
override val lessonContent: LessonContext.() -> Unit
get() = {
prepareSample(sample)
actionTask("CollapseRegion") {
- "Sometimes you need to collapse a piece of code for better readability. Try to collapse a code fragment with ${action(it)}."
+ LessonsBundle.message("collapse.try.collapse", action(it))
}
actionTask("ExpandRegion") {
- "To expand a code region, hit ${action(it)}."
+ LessonsBundle.message("collapse.hit.expand", action(it))
}
actionTask("CollapseAllRegions") {
- "If you want to collapse all regions in the file, use ${action(it)}."
+ LessonsBundle.message("collapse.all.collapse", action(it))
}
actionTask("ExpandAllRegions") {
- "Similarly, press ${action(it)} to expand all available regions."
+ LessonsBundle.message("collapse.all.expand", action(it))
}
}
}
\ No newline at end of file
// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package training.learn.lesson.general
+import training.learn.LessonsBundle
import training.learn.interfaces.Module
import training.learn.lesson.kimpl.KLesson
import training.learn.lesson.kimpl.LessonContext
import training.learn.lesson.kimpl.LessonSample
abstract class CompletionWithTabLesson(module: Module, lang: String, private val proposal: String) :
- KLesson("Completion with tab", "Completion with tab", module, lang) {
+ KLesson("Completion with tab", LessonsBundle.message("completion.with.tab.lesson.name"), module, lang) {
abstract val sample: LessonSample
get() = {
prepareSample(sample)
- actionTask("CodeCompletion") { "Press ${action(it)} to show completion options." }
+ actionTask("CodeCompletion") { LessonsBundle.message("completion.with.tab.begin.completion", action(it)) }
actionTask("EditorChooseLookupItemReplace") {
- "Choose <code>$proposal</code>, for example, and press ${action("EditorTab")}. " +
- "This overwrites the word at the caret rather than simply inserting it."
+ LessonsBundle.message("completion.with.tab.finish.with.tab", code(proposal), action("EditorTab"))
}
}
}
// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package training.learn.lesson.general
+import training.learn.LessonsBundle
import training.learn.interfaces.Module
import training.learn.lesson.kimpl.KLesson
import training.learn.lesson.kimpl.LessonContext
import training.learn.lesson.kimpl.LessonSample
class DuplicateLesson(module: Module, lang: String, private val sample: LessonSample) :
- KLesson("Duplicate", "Duplicate and delete lines", module, lang) {
+ KLesson("Duplicate", LessonsBundle.message("duplicate.and.delete.lines.lesson.name"), module, lang) {
override val lessonContent: LessonContext.() -> Unit
get() = {
prepareSample(sample)
- actionTask("EditorDuplicate") { "Duplicate any line with ${action(it)}." }
+ actionTask("EditorDuplicate") { LessonsBundle.message("duplicate.and.delete.lines.duplicate.line", action(it)) }
task("EditorDuplicate") {
- text("You can do the same action with multiple lines, too. Simply select two or more lines and duplicate them with ${action(it)}.")
+ text(
+ LessonsBundle.message("duplicate.and.delete.lines.duplicate.several.lines", action(it)))
trigger(it, {
val selection = editor.selectionModel
val start = selection.selectionStartPosition?.line ?: 0
test { actions("EditorUp", "EditorLineStart", "EditorDownWithSelection", "EditorDownWithSelection", it) }
}
actionTask("EditorDeleteLine") {
- "To delete the current line you can use action ${action(it)}."
+ LessonsBundle.message("duplicate.and.delete.lines.delete.line", action(it))
}
}
}
\ No newline at end of file
// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package training.learn.lesson.general
+import com.intellij.ide.IdeBundle
import com.intellij.ide.actions.AboutPopup
import com.intellij.ide.actions.searcheverywhere.SearchEverywhereUIBase
import com.intellij.openapi.editor.ex.EditorSettingsExternalizable
import com.intellij.testGuiFramework.framework.GuiTestUtil
import com.intellij.testGuiFramework.impl.jList
import com.intellij.testGuiFramework.util.Key
-import com.intellij.ui.components.fields.ExtendableTextField
-import training.commands.kotlin.TaskRuntimeContext
+import training.learn.LessonsBundle
import training.learn.interfaces.Module
import training.learn.lesson.kimpl.KLesson
import training.learn.lesson.kimpl.LessonContext
import training.learn.lesson.kimpl.LessonSample
+import training.learn.lesson.kimpl.LessonUtil
import javax.swing.JPanel
class GotoActionLesson(module: Module, lang: String, private val sample: LessonSample) :
- KLesson("Actions", "Search for actions", module, lang) {
+ KLesson("Actions", LessonsBundle.message("goto.action.lesson.name"), module, lang) {
companion object {
private const val FIND_ACTION_WORKAROUND: String = "https://intellij-support.jetbrains.com/hc/en-us/articles/360005137400-Cmd-Shift-A-hotkey-opens-Terminal-with-apropos-search-instead-of-the-Find-Action-dialog"
get() = {
prepareSample(sample)
actionTask("GotoAction") {
- "One of the most useful shortcuts is <strong>Find Action</strong>. It lets you search through all available actions " +
- "without having to know their individual shortcuts.\nTry it now with ${action(it)}." +
- if (SystemInfo.isMacOSMojave) "\nIf <strong>Terminal</strong> search opens instead of <strong>Find Action</strong>, " +
- "refer to <a href=\"$FIND_ACTION_WORKAROUND\">this article</a>." else ""
+ val macOsWorkaround = if (SystemInfo.isMacOSMojave)
+ LessonsBundle.message("goto.action.mac.workaround", LessonUtil.actionName(it), FIND_ACTION_WORKAROUND)
+ else ""
+ LessonsBundle.message("goto.action.use.find.action", LessonUtil.actionName(it), action(it)) + macOsWorkaround
}
actionTask("About") {
- "Let's say you want to learn about the IDE, type <strong>about</strong> and press ${action("EditorEnter")}."
+ LessonsBundle.message("goto.action.invoke.about.action",
+ strong(LessonsBundle.message("goto.action.about.word")), LessonUtil.rawEnter())
}
task {
- text("Hit ${action("EditorEscape")} to return to the editor.")
+ text(LessonsBundle.message("goto.action.to.return.to.the.editor", action("EditorEscape")))
var aboutHasBeenFocused = false
stateCheck {
aboutHasBeenFocused = aboutHasBeenFocused || focusOwner is AboutPopup.PopupPanel
}
}
actionTask("GotoAction") {
- "${action(it)} can also be used to change the settings, invoke it again now."
+ LessonsBundle.message("goto.action.invoke.again", code("Ran"), action(it))
}
- task("show line") {
- text("Type <strong>$it</strong> to see <strong>Show Line Number</strong> selector.")
+ val showLineNumbersName = IdeBundle.message("label.show.line.numbers")
+ task(LessonsBundle.message("goto.action.show.line.input.required")) {
+ text(LessonsBundle.message("goto.action.show.line.numbers.request", strong(it), strong(showLineNumbersName)))
triggerByListItemAndHighlight { item ->
- item.toString().contains("Show Line Numbers")
+ item.toString().contains(showLineNumbersName)
}
test {
waitComponent(SearchEverywhereUIBase::class.java)
val lineNumbersShown = isLineNumbersShown()
task {
- text("Switch the line numbers ${if (lineNumbersShown) "off" else "on"}.")
+ text(LessonsBundle.message("goto.action.first.lines.toggle", if (lineNumbersShown) 0 else 1))
stateCheck { isLineNumbersShown() == !lineNumbersShown }
restoreByUi()
test {
ideFrame {
- jList("Show Line Numbers").item("Show Line Numbers").click()
+ jList(showLineNumbersName).item(showLineNumbersName).click()
}
}
}
task {
- text("Now switch the line numbers back ${if (lineNumbersShown) "on" else "off"}.")
+ text(LessonsBundle.message("goto.action.second.lines.toggle", if (lineNumbersShown) 0 else 1))
stateCheck { isLineNumbersShown() == lineNumbersShown }
test {
ideFrame {
- jList("Show Line Numbers").item("Show Line Numbers").click()
+ jList(showLineNumbersName).item(showLineNumbersName).click()
}
}
}
task {
- text("Awesome! Click the button below to start the next lesson, or use ${action("learn.next.lesson")}.")
+ text(LessonsBundle.message("goto.action.propose.to.go.next", action("learn.next.lesson")))
}
}
private fun isLineNumbersShown() = EditorSettingsExternalizable.getInstance().isLineNumbersShown
-
- private fun TaskRuntimeContext.checkWordInSearch(expected: String): Boolean =
- (focusOwner as? ExtendableTextField)?.text?.toLowerCase()?.contains(expected.toLowerCase()) == true
}
\ No newline at end of file
package training.learn.lesson.general
import training.lang.JavaLangSupport
+import training.learn.LessonsBundle
import training.learn.interfaces.Module
import training.learn.lesson.kimpl.KLesson
import training.learn.lesson.kimpl.LessonContext
import training.learn.lesson.kimpl.LessonSample
class MoveLesson(module: Module, lang: String, private val sample: LessonSample)
- : KLesson("Move", "Move", module, lang) {
+ : KLesson("Move", LessonsBundle.message("move.lesson.name"), module, lang) {
override val lessonContent: LessonContext.() -> Unit
get() = {
prepareSample(sample)
actionTask("MoveLineDown") {
- "Rearranging lines usually takes two actions: cut and paste. In this IDE, you can do it with just one. " +
- "Press ${action(it)} to pull down the current line."
+ LessonsBundle.message("move.pull.down", action(it))
}
actionTask("MoveLineUp") {
- "Similarly, to pull a line up, use ${action(it)}."
+ LessonsBundle.message("move.pull.up", action(it))
}
if (lang == JavaLangSupport.lang) caret(9, 5)
task("MoveStatementUp") {
- text("Now try to move the whole method up with ${action(it)}.")
+ text(LessonsBundle.message("move.whole.method.up", action(it)))
trigger(it, { editor.document.text }, { before, now ->
checkSwapMoreThan2Lines(before, now)
})
test { actions("EditorUp", it) }
}
actionTask("MoveStatementDown") {
- "And move it down with ${action(it)}."
+ LessonsBundle.message("move.whole.method.down", action(it))
}
}
}
private fun <T> commonSuffix(list1: List<T>, list2: List<T>): Int {
val size = Integer.min(list1.size, list2.size)
for (i in 0 until size) {
- if (list1[list1.size - i - 1] != list2[list2.size - i -1])
+ if (list1[list1.size - i - 1] != list2[list2.size - i - 1])
return i
}
return size
import com.intellij.psi.html.HtmlTag
import com.intellij.psi.util.PsiTreeUtil
import training.commands.kotlin.TaskRuntimeContext
+import training.learn.LessonsBundle
import training.learn.interfaces.Module
import training.learn.lesson.kimpl.KLesson
import training.learn.lesson.kimpl.LessonContext
import training.learn.lesson.kimpl.parseLessonSample
class MultipleSelectionHtmlLesson(module: Module)
- : KLesson("Multiple selections", "Multiple selections", module, "HTML") {
+ : KLesson("Multiple selections", LessonsBundle.message("multiple.selections.lesson.name"), module, "HTML") {
private val sample = parseLessonSample("""<!doctype html>
<html lang="en">
<head>
prepareSample(sample)
actionTask("SelectNextOccurrence") {
- "Press ${action(it)} to select the symbol at the caret."
+ LessonsBundle.message("multiple.selections.select.symbol", action(it))
}
actionTask("SelectNextOccurrence") {
- "Press ${action(it)} again to select the next occurrence of this symbol."
+ LessonsBundle.message("multiple.selections.select.next.symbol", action(it))
}
actionTask("UnselectPreviousOccurrence") {
- "Press ${action(it)} to deselect the last occurrence."
+ LessonsBundle.message("multiple.selections.deselect.symbol", action(it))
}
actionTask("SelectAllOccurrences") {
- "Press ${action(it)} to select all occurrences in the file."
+ LessonsBundle.message("multiple.selections.select.all", action(it))
}
task {
- text("Type <code>td</code> to replace all occurrences of <code>th</code> with <code>td</code>.")
+ text(LessonsBundle.message("multiple.selections.replace", code("td"), code("th")))
stateCheck { checkMultiChange() }
test { type("td") }
}
// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package training.learn.lesson.general
+import training.learn.LessonsBundle
import training.learn.interfaces.Module
import training.learn.lesson.kimpl.KLesson
import training.learn.lesson.kimpl.LessonContext
import training.learn.lesson.kimpl.LessonSample
class SelectLesson(module: Module, lang: String, private val sample: LessonSample) :
- KLesson("Select", "Expand and shrink the code selection", module, lang) {
+ KLesson("Select", LessonsBundle.message("selection.lesson.name"), module, lang) {
override val lessonContent: LessonContext.() -> Unit
get() = {
prepareSample(sample)
actionTask("EditorNextWordWithSelection") {
- "Place the caret before any word. Press ${action(it)} to move the caret to the next word and select everything in between."
+ LessonsBundle.message("selection.select.word", action(it))
}
actionTask("EditorSelectWord") {
- "Press ${action(it)} to extend the selection to the next code block."
+ LessonsBundle.message("selection.extend.selection", action(it))
}
task("EditorSelectWord") {
- text("Try to increase your selection with ${action(it)} until your whole file is selected.")
+ text(LessonsBundle.message("selection.extend.until.whole.file", action(it)))
trigger(it) {
editor.selectionModel.selectionStart == 0 && editor.document.textLength == editor.selectionModel.selectionEnd
}
}
}
actionTask("EditorUnSelectWord") {
- "${action(it)} shrinks selection. Try pressing it."
+ LessonsBundle.message("selection.shrink.selection", action(it))
}
}
}
\ No newline at end of file
import com.intellij.psi.PsiDocumentManager
import com.intellij.psi.PsiElement
import training.commands.kotlin.TaskRuntimeContext
+import training.learn.LessonsBundle
import training.learn.interfaces.Module
import training.learn.lesson.kimpl.KLesson
import training.learn.lesson.kimpl.LessonContext
import training.learn.lesson.kimpl.LessonSample
class SingleLineCommentLesson(module: Module, lang: String, private val sample: LessonSample)
- : KLesson("Comment line", "Comment line", module, lang) {
+ : KLesson("Comment line", LessonsBundle.message("comment.line.lesson.name"), module, lang) {
override val lessonContent: LessonContext.() -> Unit
get() = {
prepareSample(sample)
actionTask("CommentByLineComment") {
- "Comment out any line with ${action(it)}."
+ LessonsBundle.message("comment.line.comment.any.line", action(it))
}
task("CommentByLineComment") {
- text("Uncomment the commented line with the same shortcut, ${action(it)}.")
+ text(LessonsBundle.message("comment.line.uncomment.that.line", action(it)))
trigger(it, { countCommentedLines() }, { _, now -> now == 0 })
test { actions("EditorUp", it) }
}
task("CommentByLineComment") {
- text("Select several lines and then comment them with ${action(it)}.")
+ text(LessonsBundle.message("comment.line.comment.several.lines", action(it)))
trigger(it, { countCommentedLines() }, { before, now -> now >= before + 2 })
test { actions("EditorDownWithSelection", "EditorDownWithSelection", it) }
}
import training.commands.kotlin.TaskContext
import training.commands.kotlin.TaskRuntimeContext
+import training.learn.LessonsBundle
import training.learn.interfaces.Module
import training.learn.lesson.kimpl.KLesson
import training.learn.lesson.kimpl.LessonContext
import training.learn.lesson.kimpl.LessonUtil.checkExpectedStateOfEditor
abstract class SurroundAndUnwrapLesson(module: Module, lang: String)
- : KLesson("Surround and unwrap", "Surround and unwrap", module, lang) {
+ : KLesson("Surround and unwrap", LessonsBundle.message("surround.and.unwrap.lesson.name"), module, lang) {
protected abstract val sample: LessonSample
editor.caretModel.currentCaret.selectionStart != previous.sample.selection?.first ||
editor.caretModel.currentCaret.selectionEnd != previous.sample.selection?.second
}
- text("Press ${action(it)} to surround the selected code fragment with some template code.")
+ text(LessonsBundle.message("surround.and.unwrap.invoke.surround", action(it)))
triggerByListItemAndHighlight { item ->
surroundItems.all { need -> wordIsPresent(item.toString(), need) }
}
}
task {
- text("Choose <code>$surroundItemName</code> item.")
+ text(LessonsBundle.message("surround.and.unwrap.choose.surround.item", code(surroundItemName)))
stateCheck {
editor.document.charsSequence.let { sequence ->
surroundItems.all { sequence.contains(it) }
proposeIfModified {
editor.caretModel.currentCaret.logicalPosition.line != previous.position.line
}
- text("Let's return to the initial file with unwrapping action by ${action(it)}.")
+ text(LessonsBundle.message("surround.and.unwrap.invoke.unwrap", action(it)))
triggerByListItemAndHighlight { item ->
wordIsPresent(item.toString(), surroundItems[0])
}
}
task {
restoreByUi()
- text("Choose <code>Unwrap ${surroundItems[0]}</code> item.")
+ text(LessonsBundle.message("surround.and.unwrap.choose.unwrap.item",
+ strong(LessonsBundle.message("surround.and.unwrap.item", surroundItems[0]))))
stateCheck {
editor.document.charsSequence.let { sequence ->
!surroundItems.any { sequence.contains(it) }
import com.intellij.testGuiFramework.framework.GuiTestUtil
import com.intellij.testGuiFramework.util.Key
+import training.learn.LessonsBundle
import training.learn.interfaces.Module
import training.learn.lesson.kimpl.KLesson
import training.learn.lesson.kimpl.LessonContext
import javax.swing.JList
abstract class BasicCompletionLessonBase(module: Module, lang: String)
- : KLesson("Basic completion", "Basic completion", module, lang) {
+ : KLesson("Basic completion", LessonsBundle.message("basic.completion.lesson.name"), module, lang) {
protected abstract val sample1: LessonSample
protected abstract val sample2: LessonSample
val result1 = LessonUtil.insertIntoSample(sample1, item1Completion)
prepareSample(sample1)
task {
- text("By default, the IDE proposes completion for your code instantly. Start typing <code>$item1Completion</code> right where " +
- "the caret is, and you will see the Lookup Menu with matching suggestions.")
+ text(LessonsBundle.message("basic.completion.start.typing", code(item1Completion)))
triggerByListItemAndHighlight(highlightBorder = false, highlightInside = false) { // no highlighting
it.toString().contains(item1Completion)
}
}
}
task {
- text("Continue typing <code>$item1Completion</code> unless it becomes the first item.")
+ text(LessonsBundle.message("basic.completion.continue.typing", code(item1Completion)))
stateCheck {
(previous.ui as? JList<*>)?.let {
isTheFirstVariant(it)
}
restoreByUi()
}
- task {
- text("Now just press <action>EditorEnter</action> to complete this statement.")
- trigger("EditorChooseLookupItem") {
+ task("EditorChooseLookupItem") {
+ text(LessonsBundle.message("basic.completion.just.press.to.complete", action(it)))
+ trigger(it) {
editor.document.text == result1
}
restoreState {
val result2 = LessonUtil.insertIntoSample(sample2, item2Inserted)
prepareSample(sample2)
task("CodeCompletion") {
- text("To activate Basic Completion explicitly, press ${action(it)}.")
+ text(LessonsBundle.message("basic.completion.activate.explicitly", action(it)))
trigger(it)
triggerByListItemAndHighlight { item ->
item.toString().contains(item2Completion)
}
}
task {
- text("Select <code>$item2Completion</code> and press <action>EditorEnter</action>.")
+ text(LessonsBundle.message("basic.completion.finish.explicit.completion",
+ code(item2Completion), action("EditorChooseLookupItem")))
stateCheck {
editor.document.text == result2
}
import com.intellij.psi.PsiFile
import com.intellij.testGuiFramework.framework.GuiTestUtil.shortcut
import com.intellij.testGuiFramework.util.Key
+import com.intellij.ui.UIBundle
import com.intellij.ui.table.JBTable
import training.commands.kotlin.TaskRuntimeContext
+import training.learn.LessonsBundle
import training.learn.interfaces.Module
import training.learn.lesson.kimpl.KLesson
import training.learn.lesson.kimpl.LessonContext
abstract class DeclarationAndUsagesLesson(module: Module, lang: String)
- : KLesson("Declaration and usages", "Declaration and usages", module, lang) {
+ : KLesson("Declaration and usages", LessonsBundle.message("declaration.and.usages.lesson.name"), module, lang) {
abstract fun LessonContext.setInitialPosition()
- abstract val typeOfEntity: String
+ abstract val typeOfEntity: Int // 0 - method, 1 - attribute accessor
abstract override val existedFile: String
override val lessonContent: LessonContext.() -> Unit
setInitialPosition()
task("GotoDeclaration") {
- text("Use ${action(it)} to jump to the declaration of $typeOfEntity")
+ text(LessonsBundle.message("declaration.and.usages.jump.to.declaration", action(it), typeOfEntity))
trigger(it, { state() }) { before, _ ->
before != null && !isInsidePsi(before.target.navigationElement, before.position)
}
}
task("GotoDeclaration") {
- text("Now the caret is at the attribute accessor declaration. " +
- "Use the same shortcut ${action(it)} to see all of its usages, then select one of them.")
+ text(LessonsBundle.message("declaration.and.usages.show.usages", typeOfEntity, action(it)))
trigger(it, { state() }) l@{ before, now ->
if (before == null || now == null) {
return@l false
}
task("FindUsages") {
- text("Use ${action(it)} to see a more detailed view of usages. You can invoke ${action(it)} on either a declaration or usage.")
+ text(LessonsBundle.message("declaration.and.usages.find.usages", action(it)))
triggerByUiComponentAndHighlight { ui: BaseLabel ->
ui.text?.contains("Usages of") ?: false
}
}
+ val pinTabText = UIBundle.message("tabbed.pane.pin.tab.action.name")
task {
test {
ideFrame {
}
}
triggerByUiComponentAndHighlight(highlightInside = false) { ui: ActionMenuItem ->
- ui.text?.contains("Pin Tab") ?: false
+ ui.text?.contains(pinTabText) ?: false
}
restoreByUi()
- text("From the <strong>Find view</strong> you can navigate to both usages and declarations. " +
- "The next search will override these results in the <strong>Find view</strong> window. " +
- "To prevent it, pin the results: ")
- text("Right click the tab title, <strong>Usages of</strong>.")
+ text(LessonsBundle.message("declaration.and.usages.pin.motivation", strong(UIBundle.message("tool.window.name.find"))))
+ text(LessonsBundle.message("declaration.and.usages.right.click.tab",
+ strong(LessonsBundle.message("declaration.and.usages.tab.name"))))
}
task("PinToolwindowTab") {
trigger(it)
restoreByUi()
- text("Select <strong>Pin tab</strong>.")
+ text(LessonsBundle.message("declaration.and.usages.select.pin.item", strong(pinTabText)))
test {
ideFrame {
jComponent(previous.ui!!).click()
}
actionTask("HideActiveWindow") {
- "When you have finished browsing usages, use ${action(it)} to hide the view."
+ LessonsBundle.message("declaration.and.usages.hide.view", action(it))
}
actionTask("ActivateFindToolWindow") {
- "Press ${action(it)} to open the <strong>Find view</strong> again."
+ LessonsBundle.message("declaration.and.usages.open.find.view",
+ action(it), strong(UIBundle.message("tool.window.name.find")))
}
}
import com.intellij.testGuiFramework.util.Key
import com.intellij.ui.speedSearch.SpeedSearchSupply
import training.commands.kotlin.TaskRuntimeContext
+import training.learn.LessonsBundle
import training.learn.interfaces.Module
import training.learn.lesson.kimpl.KLesson
import training.learn.lesson.kimpl.LessonContext
+import training.learn.lesson.kimpl.LessonUtil
abstract class FileStructureLesson(module: Module, lang: String)
- : KLesson("File structure", "File structure", module, lang) {
+ : KLesson("File structure", LessonsBundle.message("file.structure.lesson.name"), module, lang) {
abstract override val existedFile: String
- abstract val searchSubstring : String
- abstract val firstWord : String
- abstract val secondWord : String
+ abstract val searchSubstring: String
+ abstract val firstWord: String
+ abstract val secondWord: String
override val lessonContent: LessonContext.() -> Unit
get() = {
caret(0)
actionTask("FileStructurePopup") {
- "A large source file can be difficult to read and navigate, sometimes you only need an overview of the file." +
- "Use ${action(it)} to see the file structure."
+ LessonsBundle.message("file.structure.open.popup", action(it))
}
task(searchSubstring) {
- text("Suppose you want to find some method with ${code(firstWord)} and ${code(secondWord)} words in its name. " +
- "Type ${code(searchSubstring)} (prefixes of required words) to filter file structure.")
+ text(LessonsBundle.message("file.structure.request.prefixes", code(firstWord), code(secondWord), code(searchSubstring)))
stateCheck { checkWordInSearch(it) }
test {
ideFrame {
}
}
task {
- text("Only one item remains. Now press <strong>Enter</strong> to jump to the selected item.")
+ text(LessonsBundle.message("file.structure.navigate", LessonUtil.rawEnter()))
stateCheck { focusOwner is EditorComponentImpl }
test { GuiTestUtil.shortcut(Key.ENTER) }
}
task("ActivateStructureToolWindow") {
- text("The IDE can also show you the file structure as a tool window. Open it with ${action(it)}.")
+ text(LessonsBundle.message("file.structure.toolwindow", action(it)))
stateCheck { focusOwner?.javaClass?.name?.contains("StructureViewComponent") ?: false }
test { actions(it) }
}
// Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package training.learn.lesson.general.refactorings
+import com.intellij.CommonBundle
+import com.intellij.refactoring.RefactoringBundle
import com.intellij.testGuiFramework.impl.button
+import com.intellij.ui.UIBundle
import training.commands.kotlin.TaskTestContext
import training.learn.interfaces.Module
import training.learn.lesson.kimpl.KLesson
import training.learn.lesson.kimpl.LessonContext
import training.learn.lesson.kimpl.LessonSample
import javax.swing.JDialog
+import training.learn.LessonsBundle
+import training.learn.lesson.kimpl.dropMnemonic
class ExtractMethodCocktailSortLesson(module: Module, lang: String, private val sample: LessonSample)
- : KLesson("Extract method", "Extract method", module, lang) {
+ : KLesson("Extract method", LessonsBundle.message("extract.method.lesson.name"), module, lang) {
override val lessonContent: LessonContext.() -> Unit
get() = {
prepareSample(sample)
actionTask("ExtractMethod") {
- "Press ${action(it)} to extract the selected code block into a method."
+ LessonsBundle.message("extract.method.invoke.action", action(it))
}
// Now will be open the first dialog
+ val okButtonText = CommonBundle.getOkButtonText()
+ val extractMethodDialogTitle = RefactoringBundle.message("extract.method.title")
+ val replaceFragmentDialogTitle = RefactoringBundle.message("replace.fragment")
task {
- text("Click <strong>Ok</strong> to start refactoring.")
+ text(LessonsBundle.message("extract.method.start.refactoring", strong(okButtonText)))
// Wait until the second dialog
stateCheck {
test {
with(TaskTestContext.guiTestCase) {
- dialog("Extract Method", needToKeepDialog=true) {
- button("OK").click()
+ dialog(extractMethodDialogTitle, needToKeepDialog = true) {
+ button(okButtonText).click()
}
}
}
}
+ val yesButtonText = CommonBundle.getYesButtonText().dropMnemonic()
task {
- text("Cocktail Sort has two swap places. The first fragment has just been extracted. Click <strong>Yes</strong> to extract both of them.")
+ text(LessonsBundle.message("extract.method.confirm.several.replaces", strong(yesButtonText)))
// Wait until the third dialog
- triggerByUiComponentAndHighlight(highlightBorder = false, highlightInside = false) { dialog : JDialog ->
- dialog.title == "Replace Fragment"
+ triggerByUiComponentAndHighlight(highlightBorder = false, highlightInside = false) { dialog: JDialog ->
+ dialog.title == replaceFragmentDialogTitle
}
test {
with(TaskTestContext.guiTestCase) {
- dialog("Extract Method") {
- button("Yes").click()
+ dialog(extractMethodDialogTitle) {
+ button(yesButtonText).click()
}
}
}
}
task {
- text("Now you can confirm or reject the replacement of the second fragment.")
+ text(LessonsBundle.message("extract.method.second.fragment"))
stateCheck {
previous.ui?.isShowing?.not() ?: true
test {
with(TaskTestContext.guiTestCase) {
- dialog("Replace Fragment") {
- button("Replace").click()
+ dialog(replaceFragmentDialogTitle) {
+ button(UIBundle.message("replace.prompt.replace.button").dropMnemonic()).click()
}
}
}
package training.learn.lesson.general.refactorings
import com.intellij.testGuiFramework.impl.jList
+import training.learn.LessonsBundle
import training.learn.interfaces.Module
import training.learn.lesson.kimpl.KLesson
import training.learn.lesson.kimpl.LessonContext
import training.learn.lesson.kimpl.LessonSample
+import training.learn.lesson.kimpl.LessonUtil
class ExtractVariableFromBubbleLesson(module: Module, lang: String, private val sample: LessonSample)
- : KLesson("Extract variable", "Extract variable", module, lang) {
+ : KLesson("Extract variable", LessonsBundle.message("extract.variable.lesson.name"), module, lang) {
override val lessonContent: LessonContext.() -> Unit
get() = {
prepareSample(sample)
task("IntroduceVariable") {
- text("Press ${action(it)} to extract a local variable from the selected expression ${code("i + 1")}.")
+ text(LessonsBundle.message("extract.variable.start.refactoring", action(it), code("i + 1")))
triggerStart("IntroduceVariable")
test {
actions(it)
}
task {
- text("This code block contains 3 occurrences of the selected expression. " +
- "Choose the second item on the list to replace all of them.")
+ text(LessonsBundle.message("extract.variable.replace.all"))
stateCheck {
editor.document.text.split("i + 1").size == 2
}
actionTask("NextTemplateVariable") {
- "Choose a name for the new variable or leave it as it is. " +
- "Press <strong>Enter</strong> to complete the refactoring."
+ //TODO: fix the shortcut: it should be ${action(it)} but with preference for Enter
+ LessonsBundle.message("extract.variable.choose.name", LessonUtil.rawEnter())
}
}
}
import com.intellij.openapi.application.runWriteAction
import com.intellij.openapi.command.WriteCommandAction
import com.intellij.openapi.editor.LogicalPosition
-import com.intellij.openapi.editor.event.DocumentEvent
-import com.intellij.openapi.editor.event.DocumentListener
import com.intellij.openapi.editor.ex.EditorGutterComponentEx
import com.intellij.openapi.editor.impl.EditorComponentImpl
import com.intellij.openapi.fileEditor.FileDocumentManager
import com.intellij.psi.PsiDocumentManager
+import com.intellij.tasks.TaskBundle
import com.intellij.testGuiFramework.framework.GuiTestUtil
import com.intellij.testGuiFramework.util.Key
import com.intellij.ui.tabs.impl.JBTabsImpl
import com.intellij.xdebugger.impl.frame.XDebuggerFramesList
import com.intellij.xdebugger.impl.ui.tree.XDebuggerTree
import org.fest.swing.timing.Timeout
+import org.jetbrains.annotations.Nls
import training.commands.kotlin.TaskContext
import training.commands.kotlin.TaskRuntimeContext
import training.commands.kotlin.TaskTestContext
import training.keymap.KeymapUtil
import training.learn.CourseManager
+import training.learn.LessonsBundle
import training.learn.interfaces.Module
import training.learn.lesson.LessonManager
import training.learn.lesson.kimpl.*
import javax.swing.JDialog
import javax.swing.text.JTextComponent
-abstract class CommonDebugLesson(module: Module, id: String, languageId: String) : KLesson(id, "Debug workflow", module, languageId) {
+abstract class CommonDebugLesson(module: Module, id: String, languageId: String)
+ : KLesson(id, LessonsBundle.message("debug.workflow.lesson.name"), module, languageId) {
protected abstract val sample: LessonSample
protected abstract val configurationName: String
protected abstract val quickEvaluationArgument: String
private var debugSession: XDebugSession? by WeakReferenceDelegator()
private var logicalPosition: LogicalPosition = LogicalPosition(0, 0)
- private val incorrectBreakPointsMessage = "Breakpoints are set incorrect for this lesson."
+ @Nls
+ private val incorrectBreakPointsMessage = LessonsBundle.message("debug.workflow.incorrect.breakpoints")
override val lessonContent: LessonContext.() -> Unit = {
prepareSample(sample)
- if (false) {
- prepareRuntimeTask {
- editor.document.addDocumentListener(object : DocumentListener {
- override fun documentChanged(event: DocumentEvent) {
-
- }
- }, lessonDisposable)
- }
- }
-
prepareTask()
toggleBreakpointTask()
if (needToRun) {
// Normally this step should not be shown!
task {
- text("Before debugging let's run the program and see what is going wrong ${action("RunClass")}.")
+ text(LessonsBundle.message("debug.workflow.run.program", action("RunClass")))
addFutureStep {
subscribeForMessageBus(RunManagerListener.TOPIC, object : RunManagerListener {
override fun runConfigurationSelected(settings: RunnerAndConfigurationSettings?) {
}
task("ToggleLineBreakpoint") {
- text(
- "So there is a problem. Let's start investigation with placing breakpoint." +
- "To toggle a breakpoint you should click left editor gutter or just press ${action(it)}.")
+ text(LessonsBundle.message("debug.workflow.toggle.breakpoint", action(it)))
stateCheck {
lineWithBreakpoints() == setOf(logicalPosition.line)
}
mayBeStopped = false
task("Debug") {
- text("To start debug selected run configuration you need to click at ${icon(AllIcons.Actions.StartDebugger)}. " +
- "Or you can just press ${action(it)}.")
+ text(LessonsBundle.message("debug.workflow.start.debug", icon(AllIcons.Actions.StartDebugger), action(it)))
addFutureStep {
project.messageBus.connect(lessonDisposable).subscribe(XDebuggerManager.TOPIC, object : XDebuggerManagerListener {
override fun processStarted(debugProcess: XDebugProcess) {
before {
LearningUiHighlightingManager.clearHighlights()
}
- text("Many trace actions will focus debug toolwindow. Lets return to the editor with ${action(it)}")
+ text(LessonsBundle.message("debug.workflow.return.to.editor", action(it)))
stateCheck {
focusOwner is EditorComponentImpl
}
?: error("Invalid sample data")
caret(position)
val hasShortcut = KeymapUtil.getShortcutByActionId(it) != null
- text("IDE has several ways to show values. For this step, we selected the call. Lets add it to <strong>Watches</strong>. " +
- "You can copy the expression into clipboard, use ${icon(AllIcons.General.Add)} button on the debug panel and paste copied text. " +
- "Or you can just use action ${action(it)} ${if (hasShortcut) "" else " (consider to add a shortcut for it later)"}.")
+ val shortcut = if (hasShortcut) "" else " " + LessonsBundle.message("debug.workflow.consider.to.add.a.shortcut")
+
+ text(LessonsBundle.message("debug.workflow.use.watches",
+ strong(TaskBundle.message("debugger.watches")), icon(AllIcons.General.Add), action(it), shortcut))
stateCheck {
val watches = (XDebuggerManager.getInstance(project) as XDebuggerManagerImpl).watchesManager.getWatches(confNameForWatches)
watches.any { watch -> watch.expression == needAddToWatch }
actionTask("StepInto") {
proposeModificationRestore(sample.text)
- "Lets step into. You can use action ${action(it)} or the button ${icon(AllIcons.Actions.TraceInto)} at the debug panel."
+ LessonsBundle.message("debug.workflow.step.into", action(it), icon(AllIcons.Actions.TraceInto))
}
task {
before {
LearningUiHighlightingManager.clearHighlights()
}
- text("In most cases you will want to skip argument calculating so Smart Step Into feature suggest by default the wrapping method. " +
- "But here we need to choose the second one: ${code(methodForStepInto)}. You can choose it by keyboard " +
- "<raw_action>$stepIntoDirection</raw_action> and press ${action("EditorEnter")} or you can click the call by mouse.")
+ text(LessonsBundle.message("debug.workflow.choose.method.to.step.in",
+ code(methodForStepInto),
+ "<raw_action>$stepIntoDirection</raw_action>",
+ action("EditorEnter")))
stateCheck {
val debugLine = debugSession?.currentStackFrame?.sourcePosition?.line
val sampleLine = editor.offsetToLogicalPosition(sample.getPosition(2).startOffset).line
}
val position = sample.getPosition(2)
caret(position)
- text("Lets see what we are going to pass to ${code(quickEvaluationArgument)}. We selected the argument. " +
- "Invoke Quick Evaluate Expression ${action(it)}.")
+ text(LessonsBundle.message("debug.workflow.quick.evaluate", code(quickEvaluationArgument), action(it)))
trigger(it)
proposeRestore {
checkPositionOfEditor(LessonSample(sample.text, position)) ?: checkForBreakpoints()
private fun LessonContext.fixTheErrorTask() {
task {
- text("Oh, we made a mistake in the array index! Lets fix it right now. " +
- "Close popup (${action("EditorEscape")}) and change 0 to 1.")
+ text(LessonsBundle.message("debug.workflow.fix.error", action("EditorEscape")))
val intermediate = sample.text.replaceFirst("[0]", "[]")
val restorePosition = sample.text.indexOf("[0]") + 2
stateCheck {
actionTask("StepOver") {
proposeModificationRestore(afterFixText)
- "Let's check that the call of ${code("extract_number")} will not throw an exception now. " +
- "Use Step Over action ${action(it)} or click the button ${icon(AllIcons.Actions.TraceOver)}."
+ LessonsBundle.message("debug.workflow.step.over", code("extract_number"), action(it), icon(AllIcons.Actions.TraceOver))
}
}
actionTask("Resume") {
proposeModificationRestore(afterFixText)
- "Seems no exceptions by now. Let's continue execution with ${action(it)} or" +
- "click the button ${icon(AllIcons.Actions.Resume)}."
+ LessonsBundle.message("debug.workflow.resume", action(it), icon(AllIcons.Actions.Resume))
}
}
actionTask("XDebugger.MuteBreakpoints") {
proposeModificationRestore(afterFixText)
- "Ups, same breakpoint again. Now we don't need to stop at this breakpoint. " +
- "So let's mute breakpoints by the button ${icon(AllIcons.Debugger.MuteBreakpoints)} or by action ${action(it)}."
+ LessonsBundle.message("debug.workflow.mute.breakpoints", icon(AllIcons.Debugger.MuteBreakpoints), action(it))
}
}
proposeRestore {
checkPositionOfEditor(LessonSample(afterFixText, position))
}
- "Let's check the result of ${code(debuggingMethodName)}. " +
- "We've moved the editor cursor to the ${code("return")} statement. " +
- "Lets use <strong>Run to Cursor</strong> action ${action(it)} or click ${icon(AllIcons.Actions.RunToCursor)}. " +
- "Note that <strong>Run to Cursor</strong> works even if breakpoints are muted."
+ LessonsBundle.message("debug.workflow.run.to.cursor",
+ code(debuggingMethodName),
+ code("return"),
+ action(it),
+ icon(AllIcons.Actions.RunToCursor),
+ LessonUtil.actionName(it))
}
}
actionTask("EvaluateExpression") {
proposeModificationRestore(afterFixText)
- "It seems the ${code("result")} is not an average we want to find. " +
- "We forgot to divide by length. Seems we need to return ${code(expressionToBeEvaluated)}. " +
- "Let's calculate this expresion. Invoke the <strong>Evaluate Expression</strong> action by pressing ${action(it)} or " +
- "click button ${icon(AllIcons.Debugger.EvaluateExpression)}. "
+ LessonsBundle.message("debug.workflow.evaluate.expression", code("result"), code(expressionToBeEvaluated), action(it),
+ icon(AllIcons.Debugger.EvaluateExpression))
}
task(expressionToBeEvaluated) {
- text("Type ${code(it)} into the <strong>Expression</strong> field, completion works.")
+ text(LessonsBundle.message("debug.workflow.type.result", code(it),
+ strong(XDebuggerBundle.message("xdebugger.evaluate.label.expression"))))
stateCheck { checkWordInTextField(it) }
proposeModificationRestore(afterFixText)
test {
before {
LearningUiHighlightingManager.clearHighlights()
}
- text("Click <strong>Evaluate</strong> or hit ${action("EditorEnter")}.")
+ text(LessonsBundle.message("debug.workflow.evaluate.it", LessonUtil.rawEnter(),
+ strong(XDebuggerBundle.message("xdebugger.button.evaluate").dropMnemonic())))
triggerByUiComponentAndHighlight(highlightBorder = false, highlightInside = false) { debugTree: XDebuggerTree ->
val dialog = UIUtil.getParentOfType(JDialog::class.java, debugTree)
val root = debugTree.root
actionTask("Stop") {
before { mayBeStopped = true }
- "It will be a correct answer! Lets close the dialog and stop debugging by ${action(it)}" +
- "or button ${icon(AllIcons.Actions.Suspend)}."
+ LessonsBundle.message("debug.workflow.stop.debug", action(it), icon(AllIcons.Actions.Suspend))
}
}
// Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package training.learn.lesson.general.run
+import com.intellij.execution.ExecutionBundle
import com.intellij.execution.RunManager
+import com.intellij.idea.ActionsBundle
import com.intellij.openapi.editor.impl.EditorComponentImpl
import com.intellij.testGuiFramework.impl.button
import com.intellij.testGuiFramework.impl.jList
+import com.intellij.ui.UIBundle
import com.intellij.ui.components.JBCheckBox
+import training.commands.kotlin.TaskContext
import training.commands.kotlin.TaskRuntimeContext
import training.commands.kotlin.TaskTestContext
+import training.learn.LessonsBundle
import training.learn.interfaces.Module
-import training.learn.lesson.kimpl.KLesson
-import training.learn.lesson.kimpl.LessonContext
-import training.learn.lesson.kimpl.LessonSample
-import training.learn.lesson.kimpl.LessonUtil
+import training.learn.lesson.kimpl.*
import training.ui.LearningUiHighlightingManager
import javax.swing.JButton
-abstract class CommonRunConfigurationLesson(module: Module, id: String, languageId: String) : KLesson(id, "Run configuration", module, languageId) {
+abstract class CommonRunConfigurationLesson(module: Module, id: String, languageId: String)
+ : KLesson(id, LessonsBundle.message("run.configuration.lesson.name"), module, languageId) {
protected abstract val sample: LessonSample
protected abstract val demoConfigurationName: String
protected fun TaskRuntimeContext.configurations() =
runManager().allSettings.filter { it.name.contains(demoConfigurationName) }
+ private fun TaskContext.runToolWindow() = strong(UIBundle.message("tool.window.name.run"))
+
override val lessonContent: LessonContext.() -> Unit
get() = {
prepareSample(sample)
actionTask("HideActiveWindow") {
LearningUiHighlightingManager.clearHighlights()
- "IDE automatically opened <strong>Run</strong> tool window. Just a tip, at the top of <strong>Run</strong> tool window you can see the full runned command." +
- " Now let’s hide the tool window with ${action(it)}."
+ LessonsBundle.message("run.configuration.hide.toolwindow", runToolWindow(), action(it))
}
task {
}
}
+ val saveConfigurationItemName = ExecutionBundle.message("save.temporary.run.configuration.action.name", demoConfigurationName)
+ .dropMnemonic()
task {
- text("For each new run IDE create temporary run configuration. Temporary configurations are automatically deleted if the default limit of 5 is reached. " +
- "Lets convert temporary configuration into permanent one. Open the drop-down menu with run configuration.")
+ text(LessonsBundle.message("run.configuration.temporary.to.permanent"))
triggerByListItemAndHighlight { item ->
- item.toString() == "Save '$demoConfigurationName' Configuration"
+ item.toString() == saveConfigurationItemName
}
test {
ideFrame {
}
task {
- text("Select <strong>Save '$demoConfigurationName' Configuration</strong>.")
+ text(LessonsBundle.message("run.configuration.select.save.configuration", strong(saveConfigurationItemName)))
restoreByUi()
stateCheck {
val selectedConfiguration = RunManager.getInstance(project).selectedConfiguration ?: return@stateCheck false
}
test {
ideFrame {
- jList("Save '$demoConfigurationName' Configuration").click()
+ jList(saveConfigurationItemName).click()
}
}
}
task("editRunConfigurations") {
LearningUiHighlightingManager.clearHighlights()
- text("Suppose you want to change configuration or create another one manually. Then you need to open the the drop-down menu again and click <strong>Edit Configurations</strong>. " +
- "Alternatively you can use ${action(it)} action.")
+ text(LessonsBundle.message("run.configuration.edit.configuration",
+ strong(ActionsBundle.message("action.editRunConfigurations.text").dropMnemonic()),
+ action(it)))
triggerByUiComponentAndHighlight<JBCheckBox>(highlightInside = false) { ui ->
- ui.text == "Store as project file"
+ ui.text == ExecutionBundle.message("run.configuration.store.as.project.file").dropMnemonic()
}
test {
actions(it)
}
task {
- text("This is a place for managing run/debug configurations. You can set here program parameters, JVM arguments, environment variables and so on.")
- text("Just a tip. Sometimes you may want to save configuration to its own file. " +
- "Such configurations will be easy to share between colleagues (usually by version control system)." +
- "Now close the settings dialog to finish this lesson.")
+ text(LessonsBundle.message("run.configuration.settings.description"))
+ text(LessonsBundle.message("run.configuration.tip.about.save.configuration.into.file"))
stateCheck {
focusOwner is EditorComponentImpl
}
package training.learn.lesson.java.completion
import training.lang.JavaLangSupport
+import training.learn.LessonsBundle
import training.learn.interfaces.Module
import training.learn.lesson.kimpl.KLesson
import training.learn.lesson.kimpl.LessonContext
import training.learn.lesson.kimpl.parseLessonSample
-class BasicCompletionLesson(module: Module) : KLesson("Basic completion", "Basic completion", module, JavaLangSupport.lang) {
+class BasicCompletionLesson(module: Module)
+ : KLesson("Basic completion", LessonsBundle.message("basic.completion.lesson.name"), module, JavaLangSupport.lang) {
val sample = parseLessonSample("""import java.lang.*;
import java.util.*;
return {
prepareSample(sample)
actionTask("EditorChooseLookupItem") {
- "By default, IntelliJ IDEA completes your code instantly. Start typing <code>Ran</code> right where the caret is, and you will see the Lookup Menu with matching suggestions. You can choose the first item from the Lookup menu by pressing ${action("EditorEnter")}."
+ LessonsBundle.message("basic.completion.start.typing", code("Run")) + " " +
+ LessonsBundle.message("java.basic.completion.choose.first", action(it))
}
caret(18, 36)
actionTask("CodeCompletion") {
- "To activate Basic Completion, press ${action(it)} and you will see lookup menu again."
+ LessonsBundle.message("java.basic.completion.activate", action(it))
}
actionTask("EditorChooseLookupItem") {
- "Select <code>i</code> inside the lookup menu and press <action>EditorEnter</action>."
+ LessonsBundle.message("java.basic.completion.choose.item", code("i"), action(it))
}
actionTask("EditorCompleteStatement") {
- "Press ${action(it)} to complete this statement."
+ LessonsBundle.message("java.basic.completion.complete", action(it))
}
task("CodeCompletion") {
caret(13, 27)
- text("Sometimes you need to see suggestions for static constants or methods. Press ${action(it)} twice to access a deeper level of Code Completion.")
+ text(
+ LessonsBundle.message("java.basic.completion.deeper.level", action(it)))
triggers(it, it)
}
package training.learn.lesson.java.completion
import training.lang.JavaLangSupport
+import training.learn.LessonsBundle
import training.learn.interfaces.Module
import training.learn.lesson.kimpl.KLesson
import training.learn.lesson.kimpl.LessonContext
import training.learn.lesson.kimpl.parseLessonSample
class PostfixCompletionLesson(module: Module)
- : KLesson("Postfix completion", "Postfix completion", module, JavaLangSupport.lang) {
+ : KLesson("Postfix completion", LessonsBundle.message("postfix.completion.lesson.name"), module, JavaLangSupport.lang) {
val sample = parseLessonSample("""class PostfixCompletionDemo{
prepareSample(sample)
caret(4, 27)
actionTask("EditorChooseLookupItem") {
- "Postfix Completion helps reduce backward caret jumps as you write code. It lets you transform an already typed expression into another one based on the postfix you add, the type of expression, and its context. Type <code>.</code> after the parenthesis to see the list of postfix completion suggestions. Select <code>if</code> from the list, or type it in editor, and then press ${action("EditorEnter")} to complete the statement."
+ LessonsBundle.message("java.postfix.completion.apply", code("."), code("if"), action("EditorChooseLookupItem"))
}
}
-
}
\ No newline at end of file
package training.learn.lesson.java.completion
import training.lang.JavaLangSupport
+import training.learn.LessonsBundle
import training.learn.interfaces.Module
import training.learn.lesson.kimpl.KLesson
import training.learn.lesson.kimpl.LessonContext
import training.learn.lesson.kimpl.parseLessonSample
class SmartTypeCompletionLesson(module: Module)
- : KLesson("Smart type completion", "Smart type completion", module, JavaLangSupport.lang) {
+ : KLesson("Smart type completion", LessonsBundle.message("java.smart.type.completion.lesson.name"), module, JavaLangSupport.lang) {
val sample = parseLessonSample("""import java.lang.String;
import java.util.HashSet;
prepareSample(sample)
task {
caret(13, 19)
- text("Smart Type Completion filters the list of suggestion to include only those types that are applicable in the current context. Press ${action("SmartTypeCompletion")} to see the list of matching suggestions. Choose the first one by pressing ${action("EditorEnter")}.")
+ text(LessonsBundle.message("java.smart.type.completion.apply", action("SmartTypeCompletion"), action("EditorChooseLookupItem")))
trigger("SmartTypeCompletion")
trigger("EditorChooseLookupItem")
}
task {
caret(20, 16)
- text("Smart Type Completion can also suggest code for a return statement. Press ${action("SmartTypeCompletion")} twice to see the Lookup menu for a return. Choose the first one by pressing ${action("EditorEnter")}")
+ text(LessonsBundle.message("java.smart.type.completion.return", action("SmartTypeCompletion"), action("EditorChooseLookupItem")))
triggers("SmartTypeCompletion", "SmartTypeCompletion")
trigger("EditorChooseLookupItem")
}
import com.intellij.psi.util.PsiTreeUtil
import training.commands.kotlin.TaskRuntimeContext
import training.lang.JavaLangSupport
+import training.learn.LessonsBundle
import training.learn.interfaces.Module
import training.learn.lesson.kimpl.KLesson
import training.learn.lesson.kimpl.LessonContext
import training.learn.lesson.kimpl.parseLessonSample
class StatementCompletionLesson(module: Module)
- : KLesson("Statement completion", "Statement completion", module, JavaLangSupport.lang) {
+ : KLesson("Statement completion", LessonsBundle.message("java.statement.completion.lesson.name"), module, JavaLangSupport.lang) {
val sample = parseLessonSample("""class PrimeNumbers {
public static void main(String[] args) {
prepareSample(sample)
caret(8, 40)
actionTask("EditorCompleteStatement") {
- "Press ${action(it)} to complete the <code>for</code> statement."
+ LessonsBundle.message("java.statement.completion.complete.for", action(it), code("for"))
}
task("EditorCompleteStatement") {
- text("Write <code>if</code> and press ${action(it)} to generate the statement.")
+ text(LessonsBundle.message("java.statement.completion.complete.if", code("if"), action(it)))
stateCheck {
return@stateCheck checkIfAppended()
}
}
actionTask("EditorCompleteStatement") {
- "Add a condition inside parentheses <code>i % j == 0</code> and press ${action(it)} to jump inside the <code>if</code> statement."
+ LessonsBundle.message("java.statement.completion.complete.condition", code("i % j == 0"), action(it), code("if"))
}
actionTask("EditorCompleteStatement") {
- "Write on one line: <code>isPrime = false; break</code> and then press ${action(it)} to complete the entered statement and apply formatting."
+ LessonsBundle.message("java.statement.completion.complete.finish.body", code("isPrime = false; break"), action(it))
}
}
import com.intellij.icons.AllIcons
import com.intellij.testGuiFramework.impl.button
import training.commands.kotlin.TaskTestContext
+import training.learn.LessonsBundle
import training.learn.interfaces.Module
import training.learn.lesson.general.run.CommonDebugLesson
import training.learn.lesson.kimpl.LessonContext
class JavaDebugLesson(module: Module) : CommonDebugLesson(module, "java.debug.workflow", "JAVA") {
- val demoClassName = JavaRunLessonsUtils.demoClassName
+ private val demoClassName = JavaRunLessonsUtils.demoClassName
override val configurationName: String = demoClassName
override val sample = JavaRunLessonsUtils.demoSample
highlightButtonById("CompileDirty")
task("CompileDirty") {
- text("For big programs rerun can take too much time. " +
- "When you find some mistake in pure method you can just rebuild the project and apply <strong>Hot Swap</strong> JVM feature. " +
- "Let's build project: ${action(it)} or ${icon(AllIcons.Actions.Compile)}.")
+ text(LessonsBundle.message("java.debug.workflow.rebuild", action(it), icon(AllIcons.Actions.Compile)))
stateCheck {
inHotSwapDialog()
}
}
task {
- text("Confirm <strong>Hot Swap</strong> replacement")
+ text(LessonsBundle.message("java.debug.workflow.confirm.hot.swap"))
stateCheck {
!inHotSwapDialog()
}
actionTask("Debugger.PopFrame") {
proposeModificationRestore(afterFixText)
- "We patched our method, but right now we are still executing old obsolete ${code("extractNumber")} and it will throw " +
- "the exception again. Let's drop the frame and return to the state before ${code("extractNumber")} call. " +
- "Click ${icon(AllIcons.Actions.PopFrame)} at the debug panel or use ${action(it)}."
+ LessonsBundle.message("java.debug.workflow.drop.frame", code("extractNumber"), code("extractNumber"), icon(AllIcons.Actions.PopFrame), action(it))
}
}
// Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package training.learn.lesson.java.run
+import com.intellij.execution.ExecutionBundle
import com.intellij.icons.AllIcons
import com.intellij.openapi.actionSystem.CommonDataKeys
import com.intellij.openapi.actionSystem.DataProvider
import com.intellij.openapi.editor.ex.EditorGutterComponentEx
+import training.learn.LessonsBundle
import training.learn.interfaces.Module
import training.learn.lesson.general.run.CommonRunConfigurationLesson
import training.learn.lesson.kimpl.LessonContext
import training.learn.lesson.kimpl.LessonSample
+import training.learn.lesson.kimpl.dropMnemonic
import training.learn.lesson.kimpl.toolWindowShowed
import java.awt.Rectangle
}
task("RunClass") {
- text("Any code marked with ${icon(AllIcons.Actions.Execute)} can be run. Let's run our simple example with ${action(it)}. " +
- "Alternatively you can click at ${icon(AllIcons.Actions.Execute)} and select <strong>Run</strong> item.")
+ text(LessonsBundle.message("java.run.configuration.lets.run", icon(AllIcons.Actions.Execute), action(it),
+ strong(ExecutionBundle.message("default.runner.start.action.text").dropMnemonic())))
//Wait toolwindow
toolWindowShowed("Run")
stateCheck {
// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package training.learn.lesson.kimpl
+import org.jetbrains.annotations.Nls
+import org.jetbrains.annotations.NonNls
import training.learn.interfaces.Lesson
import training.learn.interfaces.Module
import training.learn.lesson.LessonListener
-abstract class KLesson(final override val id: String,
- final override val name: String,
+abstract class KLesson(@NonNls final override val id: String,
+ @Nls final override val name: String,
override var module: Module,
override val lang: String) : Lesson {
import com.intellij.openapi.application.ModalityState
import com.intellij.openapi.application.invokeLater
+import org.jetbrains.annotations.Nls
import com.intellij.util.concurrency.annotations.RequiresEdt
import training.commands.kotlin.TaskContext
import training.commands.kotlin.TaskRuntimeContext
abstract fun task(taskContent: TaskContext.() -> Unit)
/** Describe a simple task: just one action required */
- fun actionTask(action: String, getText: TaskContext.(action: String) -> String) {
+ fun actionTask(action: String, @Nls getText: TaskContext.(action: String) -> String) {
task {
text(getText(action))
trigger(action)
override fun code(sourceSample: String): String = "" //Doesn't matter what to return
+ override fun strong(text: String): String = "" //Doesn't matter what to return
+
override fun icon(icon: Icon): String = "" //Doesn't matter what to return
}
\ No newline at end of file
// Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package training.learn.lesson.kimpl
+import com.intellij.openapi.actionSystem.ActionManager
import com.intellij.openapi.editor.Editor
import com.intellij.openapi.editor.EditorModificationUtil
import com.intellij.openapi.editor.ex.EditorEx
import com.intellij.openapi.fileEditor.FileDocumentManager
+import com.intellij.openapi.util.NlsActions
+import com.intellij.openapi.util.SystemInfo
+import com.intellij.openapi.util.text.StringUtil
+import com.intellij.openapi.util.text.TextWithMnemonic
import com.intellij.openapi.wm.ToolWindow
import com.intellij.openapi.wm.ex.ToolWindowManagerListener
import com.intellij.util.messages.Topic
import com.intellij.xdebugger.XDebuggerManager
import training.commands.kotlin.TaskContext
import training.commands.kotlin.TaskRuntimeContext
+import training.keymap.KeymapUtil
import training.learn.LearnBundle
+import java.awt.event.KeyEvent
import javax.swing.JList
+import javax.swing.KeyStroke
object LessonUtil {
fun insertIntoSample(sample: LessonSample, inserted: String): String {
editor.isViewer = true
EditorModificationUtil.setReadOnlyHint(editor, LearnBundle.message("learn.task.read.only.hint"))
}
+
+ fun actionName(actionId: String): @NlsActions.ActionText String {
+ val name = ActionManager.getInstance().getAction(actionId).templatePresentation.text ?: error("No action with ID $actionId")
+ return "<strong>${name}</strong>"
+ }
+
+ fun rawEnter(): String {
+ val keyStrokeEnter = KeymapUtil.getKeyStrokeText(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0))
+ return "<raw_action>$keyStrokeEnter</raw_action>"
+ }
+
+ fun rawCtrlEnter(): String {
+ return "<raw_action>${if (SystemInfo.isMacOSMojave) "\u2318\u23CE" else "Ctrl + Enter"}</raw_action>"
+ }
}
fun TaskContext.toolWindowShowed(toolWindowId: String) {
it.sourcePosition?.line
}.toSet()
}
+
+fun String.dropMnemonic(): String {
+ return TextWithMnemonic.parse(this).dropMnemonic(true).text
+}
\ No newline at end of file
import com.intellij.testGuiFramework.framework.GuiTestUtil
import com.intellij.testGuiFramework.util.Key
+import training.learn.LessonsBundle
import training.learn.interfaces.Module
import training.learn.lesson.kimpl.KLesson
import training.learn.lesson.kimpl.LessonContext
-import training.learn.lesson.kimpl.LessonUtil
import training.learn.lesson.kimpl.LessonUtil.checkExpectedStateOfEditor
import training.learn.lesson.kimpl.parseLessonSample
-class FStringCompletionLesson(module: Module) : KLesson("completion.f.string", "F-string completion", module, "Python") {
+class FStringCompletionLesson(module: Module)
+ : KLesson("completion.f.string", LessonsBundle.message("python.f.string.completion.lesson.name"), module, "Python") {
private val template = """
import sys
override val lessonContent: LessonContext.() -> Unit = {
prepareSample(sample)
task("\${my") {
- text("PyCharm supports automatic f-string conversion. Just start to type ${code(it)}")
+ text(LessonsBundle.message("python.f.string.completion.type.prefix", code(it)))
runtimeText {
val prefixTyped = checkExpectedStateOfEditor(sample) { change ->
"\${my_car".startsWith(change) && change.startsWith(it)
} == null
- if (prefixTyped) "You can invoke completion manually with ${action("CodeCompletion")}" else null
+ if (prefixTyped) LessonsBundle.message("python.f.string.completion.invoke.manually", action("CodeCompletion")) else null
}
triggerByListItemAndHighlight(highlightBorder = false) { item ->
item.toString().contains(completionItem)
test { type(it) }
}
task {
- text("Complete the statement with ${code(completionItem)}. Just press ${action("EditorEnter")} to apply the first item.")
+ text(LessonsBundle.message("python.f.string.completion.complete.it", code(completionItem), action("EditorChooseLookupItem")))
val result = template.replace("<f-place>", "f").replace("<caret>", "\${$completionItem}")
restoreByUi()
stateCheck {
test { GuiTestUtil.shortcut(Key.ENTER) }
}
task {
- text("You may see that simple Python string was replaced by f-string after the completion.")
+ text(LessonsBundle.message("python.f.string.completion.result.message"))
}
}
}
import com.intellij.testGuiFramework.framework.GuiTestUtil.typeText
import com.intellij.testGuiFramework.impl.jList
+import training.learn.LessonsBundle
import training.learn.interfaces.Module
import training.learn.lesson.kimpl.KLesson
import training.learn.lesson.kimpl.LessonContext
-import training.learn.lesson.kimpl.LessonUtil
import training.learn.lesson.kimpl.LessonUtil.checkExpectedStateOfEditor
import training.learn.lesson.kimpl.parseLessonSample
private const val completionSuffix = ".ifnn"
class PythonPostfixCompletionLesson(module: Module)
- : KLesson("Postfix completion", "Postfix completion", module, "Python") {
+ : KLesson("Postfix completion", LessonsBundle.message("postfix.completion.lesson.name"), module, "Python") {
private val sample = parseLessonSample("""
movies_dict = {
'title': 'Aviator',
get() = {
prepareSample(sample)
task {
- text("The IDE can offer postfix shortcuts. Type ${code(completionSuffix)}.")
+ text(LessonsBundle.message("postfix.completion.type.template", code(completionSuffix)))
triggerByListItemAndHighlight {
it.toString() == completionSuffix
}
}
}
task {
- text("Select ${code(completionSuffix)} item from completion list.")
+ text(LessonsBundle.message("python.postfix.completion.select.item", code(completionSuffix)))
stateCheck { editor.document.text == result }
restoreByUi()
test {
package training.learn.lesson.python.completion
import training.commands.kotlin.TaskContext
+import training.learn.LessonsBundle
import training.learn.interfaces.Module
import training.learn.lesson.kimpl.KLesson
import training.learn.lesson.kimpl.LessonContext
import training.learn.lesson.kimpl.parseLessonSample
class PythonSmartCompletionLesson(module: Module)
- : KLesson("Smart completion", "Smart completion", module, "Python") {
+ : KLesson("Smart completion", LessonsBundle.message("python.smart.completion.lesson.name"), module, "Python") {
private val sample = parseLessonSample("""
def f(x, file):
x.append(file)
prepareSample(sample)
actionTask("CodeCompletion") {
proposeRestoreMe()
- "Try to use Basic Completion by pressing ${action(it)}."
+ LessonsBundle.message("python.smart.completion.try.basic.completion", action(it))
}
task("SmartTypeCompletion") {
- text("Unfortunately IDE has no direct information about ${code("x")} type. " +
- "But sometimes it can guess completion by the context! Use ${action(it)} to invoke Smart Completion.")
+ text(LessonsBundle.message("python.smart.completion.use.smart.completion", code("x"), action(it)))
triggerByListItemAndHighlight { ui ->
ui.toString().contains(methodName)
}
}
task {
val result = LessonUtil.insertIntoSample(sample, insertedCode)
- text("Now just choose ${code(methodName)} item to finish this lesson.")
+ text(LessonsBundle.message("python.smart.completion.finish.completion", code(methodName)))
restoreByUi()
stateCheck {
editor.document.text == result
import com.intellij.testGuiFramework.util.Key
import training.commands.kotlin.TaskContext
import training.commands.kotlin.TaskRuntimeContext
+import training.learn.LessonsBundle
import training.learn.interfaces.Module
import training.learn.lesson.kimpl.*
import training.learn.lesson.kimpl.LessonUtil.checkExpectedStateOfEditor
import javax.swing.JList
class PythonTabCompletionLesson(module: Module)
- : KLesson("Tab completion", "Tab completion", module, "Python") {
+ : KLesson("Tab completion", LessonsBundle.message("python.tab.completion.lesson.name"), module, "Python") {
private val template = parseLessonSample("""
class Calculator:
def __init__(self):
return {
prepareSample(sample)
task("CodeCompletion") {
- text("Suppose you want to replace ${code("current")} with ${code("total")}. Invoke completion by pressing ${action(it)}.")
+ text(LessonsBundle.message("python.tab.completion.start.completion",
+ code("current"), code("total"), action(it)))
triggerByListItemAndHighlight(checkList = { ui -> isTotalItem(ui) })
proposeRestoreMe()
test { actions(it) }
}
task {
- text("Select item ${code("total")} by keyboard arrows or just start typing it.")
+ text(LessonsBundle.message("python.tab.completion.select.item", code("total")))
restoreState {
(previous.ui as? JList<*>)?.let { ui ->
!ui.isShowing || LessonUtil.findItem(ui, isTotalItem) == null
}
task {
val result = LessonUtil.insertIntoSample(template, "total")
- text("If you press ${action("EditorEnter")} you will insert ${code("total")} before ${code("current")}. " +
- "Instead press ${action("EditorTab")} to replace ${code("current")} with ${code("total")}")
+ text(LessonsBundle.message("python.tab.completion.use.tab.completion",
+ action("EditorEnter"), code("total"), code("current"),
+ action("EditorTab")))
trigger("EditorChooseLookupItemReplace") {
editor.document.text == result
class PythonDeclarationAndUsagesLesson(module: Module) : DeclarationAndUsagesLesson(module, "Python") {
override fun LessonContext.setInitialPosition() = caret(652, 30)
- override val typeOfEntity = "a method"
+ override val typeOfEntity = 0
override val existedFile: String = "src/jinja2/ext.py"
}
import com.intellij.openapi.actionSystem.impl.ActionButtonWithText
import com.intellij.openapi.editor.impl.EditorComponentImpl
import com.intellij.openapi.fileEditor.FileEditorManager
+import com.intellij.psi.search.EverythingGlobalScope
+import com.intellij.psi.search.ProjectScope
import com.intellij.testGuiFramework.framework.GuiTestUtil
import com.intellij.testGuiFramework.util.Key
import com.intellij.testGuiFramework.util.Modifier
import com.intellij.ui.components.fields.ExtendableTextField
import training.commands.kotlin.TaskRuntimeContext
import training.commands.kotlin.TaskTestContext
+import training.learn.LessonsBundle
import training.learn.interfaces.Module
import training.learn.lesson.kimpl.KLesson
import training.learn.lesson.kimpl.LessonContext
+import training.learn.lesson.kimpl.LessonUtil
import training.ui.LearningUiHighlightingManager
import java.awt.event.InputEvent
import java.awt.event.KeyEvent
class PythonSearchEverywhereLesson(module: Module)
- : KLesson("Search everywhere", "Search everywhere", module, "Python") {
+ : KLesson("Search everywhere", LessonsBundle.message("python.search.everywhere.lesson.name"), module, "Python") {
override val lessonContent: LessonContext.() -> Unit = {
caret(0)
val shift = KeyEvent.getKeyModifiersText(InputEvent.SHIFT_MASK)
actionTask("SearchEverywhere") {
- "To open <strong>Search Everywhere</strong> you need to press <shortcut>$shift</shortcut> two times in a row."
+ val shortcut = "<shortcut>$shift</shortcut>"
+ LessonsBundle.message("python.search.everywhere.invoke.search.everywhere", LessonUtil.actionName(it), shortcut)
}
task("cae") {
- text("Suppose you are looking for a class with ${code("cache")} and ${code("extension")} words in the name. " +
- "Type ${code(it)} (prefixes of required words) to the search field.")
+ text(LessonsBundle.message("python.search.everywhere.type.prefixes", code("cache"), code("extension"), code(it)))
stateCheck { checkWordInSearch(it) }
test {
Thread.sleep(500)
type("f")
Thread.sleep(500)
}
- "We found ${code("FragmentCacheExtension")}. " +
- "Now you can preview the found item. Just select it by keyboard arrows and press ${action(it)}."
+ LessonsBundle.message("python.search.everywhere.preview", code("FragmentCacheExtension"), action(it))
}
task {
- text("Press <strong>Enter</strong> to navigate to ${code("FragmentCacheExtension")}.")
+ text(LessonsBundle.message("python.search.everywhere.navigate.to.class", LessonUtil.rawEnter(), code("FragmentCacheExtension")))
stateCheck {
FileEditorManager.getInstance(project).selectedEditor?.file?.name.equals("cache_extension.py")
}
actionTask("GotoClass") {
// Try to add (class tab in <strong>Search Everywhere</strong>)
- "Use ${action(it)} to find class faster or in special places."
+ LessonsBundle.message("python.search.everywhere.goto.class", action(it))
}
task("nodevisitor") {
- text("Suppose you need some library class responsible for visiting nodes. Type ${code(it)}.")
+ text(LessonsBundle.message("python.search.everywhere.type.node.visitor", code(it)))
stateCheck { checkWordInSearch(it) }
test { type(it) }
}
triggerByUiComponentAndHighlight { _: ActionButtonWithText -> true }
}
- task("All Places") {
- text("Now you see a class inside this demo project. " +
- "Lets Switch <strong>Project Files</strong> filter to <strong>$it</strong> and you will see available library variants.")
+ task(EverythingGlobalScope.getNameText()) {
+ text(LessonsBundle.message("python.search.everywhere.use.all.places",
+ strong(ProjectScope.getProjectFilesScopeName()), strong(it)))
stateCheck {
(previous.ui as? ActionButtonWithText)?.accessibleContext?.accessibleName == it
}
actionTask("QuickJavaDoc") {
LearningUiHighlightingManager.clearHighlights()
- "Use ${action(it)} to quickly look at available documentation."
+ LessonsBundle.message("python.search.everywhere.quick.documentation", action(it))
}
task {
- text("<strong>Done!</strong> In the same way you can use ${action("GotoSymbol")} to look for a method or global variable " +
- "and use ${action("GotoFile")} to look for a file.")
+ text(LessonsBundle.message("python.search.everywhere.finish", action("GotoSymbol"), action("GotoFile")))
}
if (TaskTestContext.inTestMode) task {
import com.intellij.testGuiFramework.framework.GuiTestUtil
import com.intellij.testGuiFramework.util.Key
import training.commands.kotlin.TaskRuntimeContext
+import training.learn.LessonsBundle
import training.learn.interfaces.Module
import training.learn.lesson.kimpl.*
import training.learn.lesson.kimpl.LessonUtil.checkExpectedStateOfEditor
import javax.swing.JLabel
import javax.swing.JPanel
-class PythonInPlaceRefactoringLesson(module: Module) : KLesson("refactoring.in.place", "In-place refactoring", module, "Python") {
+class PythonInPlaceRefactoringLesson(module: Module)
+ : KLesson("refactoring.in.place", LessonsBundle.message("python.in.place.refactoring.lesson.name"), module, "Python") {
private val template = """
def fibonacci(stop):
first = 0
checkExpectedStateOfEditor(sample) { change -> "econd".startsWith(change) }
task {
- text("Let's consider an alternative approach to performing refactorings. Suppose we want to rename local variable ${code(variableName)} " +
- "to ${code("second")}. Just start typing the new name.")
+ text(LessonsBundle.message("python.in.place.refactoring.start.type.new.name", code(variableName), code("second")))
stateCheck {
editor.document.text != sample.text && checkFirstChange() == null
}
}
task("ShowIntentionActions") {
- text("IDE is guessing that you are going to rename the variable. " +
- "You can notice it by the icon ${icon(AllIcons.Gutter.SuggestedRefactoringBulb)} in the left editor gutter. " +
- "Invoke intentions by ${action(it)} when you finish to type the new name.")
+ text(
+ LessonsBundle.message("python.in.place.refactoring.invoke.intentions",
+ icon(AllIcons.Gutter.SuggestedRefactoringBulb), action(it)))
triggerByListItemAndHighlight(highlightBorder = true, highlightInside = false) { ui -> // no highlighting
ui.toString().contains("Rename usages")
}
task {
val prefix = template.indexOf("<name>")
- text("Press ${action("EditorEnter")} to finish rename.")
+ text(LessonsBundle.message("python.in.place.refactoring.finish.rename", action("EditorChooseLookupItem")))
restoreByUi(500)
stateCheck {
val newName = newName(editor.document.charsSequence, prefix)
}
task {
- text("Let's add an argument to this method. We place the editor caret just after the first parameter. " +
- "Now type comma and parameter's name: ${code(", start")} .")
+ text(LessonsBundle.message("python.in.place.refactoring.add.parameter", code(", start")))
stateCheck {
val text = editor.document.text
val parameter = text.substring(secondSample.startOffset, text.indexOf(')'))
}
task("ShowIntentionActions") {
- text("IDE is guessing that you are going to change the method signature. " +
- "You can notice it by the same icon ${icon(AllIcons.Gutter.SuggestedRefactoringBulb)} at the left editor gutter. " +
- "Invoke intentions by ${action(it)} when you finish typing the new parameter.")
+ text(LessonsBundle.message("python.in.place.refactoring.invoke.intention.for.parameter",
+ icon(AllIcons.Gutter.SuggestedRefactoringBulb), action(it)))
triggerByListItemAndHighlight(highlightBorder = true, highlightInside = false) { item ->
item.toString().contains("Update usages to")
}
}
task {
- text("Press ${action("EditorEnter")} to update the callers.")
+ text(LessonsBundle.message("python.in.place.refactoring.update.callers", action("EditorChooseLookupItem")))
triggerByUiComponentAndHighlight(highlightBorder = false, highlightInside = false) { ui: JPanel -> // no highlighting
ui.javaClass.name.contains("ChangeSignaturePopup")
}
}
task {
- text("IDE is showing you the short signature preview. Press ${action("EditorEnter")} to continue.")
+ text(LessonsBundle.message("python.in.place.refactoring.signature.preview", LessonUtil.rawEnter()))
triggerByUiComponentAndHighlight(highlightBorder = false, highlightInside = false) { ui: JLabel -> // no highlighting
ui.text == "Add values for new parameters:"
}
before {
beforeSecondRefactoring = editor.document.text
}
- text("Now you need to type the value which will be inserted as an argument into the each call. " +
- "You can choose ${code("0")} for this sample. Then press ${action("EditorEnter")} to continue.")
+ text(LessonsBundle.message("python.in.place.refactoring.set.default.value", code("0"),LessonUtil.rawEnter()))
restoreByUi()
stateCheck {
editor.document.text != beforeSecondRefactoring && Thread.currentThread().stackTrace.any {
GuiTestUtil.shortcut(Key.ENTER)
}
}
- task { text("A small note for the end. In-place refactoring may be applied only in the definition point whiles direct invocation" +
- " of rename or change-signature refactorings may be called from both definition and usage.") }
+ task { text(LessonsBundle.message("python.in.place.refactoring.remark.about.application.scope")) }
}
private fun newName(text: CharSequence, prefix: Int): String {
import com.intellij.openapi.application.ModalityState
import com.intellij.openapi.application.invokeAndWaitIfNeeded
import com.intellij.openapi.editor.impl.EditorComponentImpl
-import com.intellij.openapi.util.SystemInfo
import com.intellij.openapi.wm.IdeFocusManager
+import com.intellij.refactoring.RefactoringBundle
import com.intellij.testGuiFramework.framework.GuiTestUtil
import com.intellij.testGuiFramework.impl.button
import com.intellij.testGuiFramework.util.Key
import com.intellij.util.ui.UIUtil
import com.intellij.util.ui.table.JBTableRow
+import com.jetbrains.python.PyBundle
import com.jetbrains.python.inspections.quickfix.PyChangeSignatureQuickFix
import training.commands.kotlin.TaskContext
import training.commands.kotlin.TaskTestContext
+import training.learn.LessonsBundle
import training.learn.interfaces.Module
-import training.learn.lesson.kimpl.KLesson
-import training.learn.lesson.kimpl.LessonContext
-import training.learn.lesson.kimpl.LessonUtil
+import training.learn.lesson.kimpl.*
import training.learn.lesson.kimpl.LessonUtil.checkExpectedStateOfEditor
-import training.learn.lesson.kimpl.parseLessonSample
import javax.swing.JDialog
import javax.swing.JTable
-class PythonQuickFixesRefactoringLesson(module: Module) : KLesson("refactoring.quick.fix", "Quick fix refactoring", module, "Python") {
+class PythonQuickFixesRefactoringLesson(module: Module)
+ : KLesson("refactoring.quick.fix", LessonsBundle.message("python.quick.fix.refactoring.lesson.name"), module, "Python") {
private val sample = parseLessonSample("""
def foo(x):
print("Hello ", x)
override val lessonContent: LessonContext.() -> Unit = {
prepareSample(sample)
task {
- text("Several refactorings can be performed as quick fixes. Suppose we want to add a parameter to the method ${code("foo")} " +
- "and pass the variable ${code("y")} to it. Let's type ${code(", y")} after the first argument.")
+ text(LessonsBundle.message("python.quick.fix.refactoring.type.new.argument", code("foo"), code("y"), code(", y")))
stateCheck {
editor.document.text == StringBuilder(sample.text).insert(sample.startOffset, ", y").toString()
}
}
task {
- text("Wait a little bit for the completion list...")
+ text(LessonsBundle.message("python.quick.fix.refactoring.wait.completion.showed"))
triggerByListItemAndHighlight(highlightBorder = false, highlightInside = false) { item ->
item.toString().contains("string=y")
}
}
task {
- text("For now, we don't want to apply any completion. Close the list (${action("EditorEscape")}).")
+ text(LessonsBundle.message("python.quick.fix.refactoring.close.completion.list", action("EditorEscape")))
stateCheck { previous.ui?.isShowing != true }
proposeMyRestore()
test { GuiTestUtil.shortcut(Key.ESCAPE) }
}
task("ShowIntentionActions") {
- text("As you may notice, IDE is showing you a warning here. Let's invoke intentions by ${action(it)}.")
+ text(LessonsBundle.message("python.quick.fix.refactoring.invoke.intentions", action(it)))
triggerByListItemAndHighlight(highlightBorder = true, highlightInside = false) { item ->
item.toString().contains("Change signature of")
}
}
}
task {
- text("Choose <strong>Change signature</strong> quick fix.")
+ text(LessonsBundle.message("python.quick.fix.refactoring.choose.change.signature",
+ strong(PyBundle.message("QFIX.NAME.change.signature"))))
- triggerByPartOfComponent { table : JTable ->
+ triggerByPartOfComponent { table: JTable ->
val model = table.model
if (model.rowCount >= 2 && (model.getValueAt(1, 0) as? JBTableRow)?.getValueAt(0) == "y") {
table.getCellRect(1, 0, true)
}
}
task {
- text("Let's set the default value for the new parameter. Click at the new parameter line. " +
- "Alternatively, you can set focus to the parameter without mouse by ${action("EditorTab")} and then ${action("EditorEnter")}.")
+ text(LessonsBundle.message("python.quick.fix.refactoring.select.new.parameter",
+ action("EditorTab"), LessonUtil.rawEnter()))
val selector = { collection: Collection<EditorComponentImpl> ->
collection.takeIf { it.size > 2 }?.maxBy { it.locationOnScreen.x }
}
- triggerByUiComponentAndHighlight(selector = selector) { editor : EditorComponentImpl ->
+ triggerByUiComponentAndHighlight(selector = selector) { editor: EditorComponentImpl ->
UIUtil.getParentOfType(JDialog::class.java, editor) != null
}
restoreByUi()
}
}
task {
- text("You may navigate through the fields (and the checkbox) by using ${action("EditorTab")}. " +
- "With the checkbox you can let IDE inline the default value to the other callers or set it as the default value for the new parameter. " +
- "The Signature Preview will help understand the difference. Now set the default value as 0.")
+ text(LessonsBundle.message("python.quick.fix.refactoring.set.default.value", action("EditorTab")))
restoreByUi()
stateCheck {
(previous.ui as? EditorComponentImpl)?.text == "0"
before {
beforeRefactoring = editor.document.text
}
- text("Press <raw_action>${if (SystemInfo.isMacOSMojave) "\u2318\u23CE" else "Ctrl + Enter"}</raw_action> " +
- "(or click <strong>Refactor</strong>) to finish the refactoring.")
+ text(LessonsBundle.message("python.quick.fix.refactoring.finish.refactoring",
+ LessonUtil.rawCtrlEnter(), strong(RefactoringBundle.message("refactor.button").dropMnemonic())))
stateCheck {
val b = editor.document.text != beforeRefactoring
// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package training.learn.lesson.python.refactorings
+import com.intellij.idea.ActionsBundle
import com.intellij.refactoring.rename.inplace.InplaceRefactoring
import com.intellij.testGuiFramework.framework.GuiTestUtil
import com.intellij.testGuiFramework.util.Key
import training.commands.kotlin.TaskRuntimeContext
+import training.learn.LessonsBundle
import training.learn.interfaces.Module
-import training.learn.lesson.kimpl.KLesson
-import training.learn.lesson.kimpl.LessonContext
-import training.learn.lesson.kimpl.parseLessonSample
+import training.learn.lesson.kimpl.*
import javax.swing.JList
class PythonRefactorMenuLesson(module: Module)
- : KLesson("Refactoring menu", "Refactoring menu", module, "Python") {
+ : KLesson("Refactoring menu", LessonsBundle.message("refactoring.menu.lesson.name"), module, "Python") {
private val sample = parseLessonSample("""
# Need to think about better sample!
import random
override val lessonContent: LessonContext.() -> Unit = {
prepareSample(sample)
actionTask("Refactorings.QuickListPopupAction") {
- "PyCharm supports a variety of refactorings. Many of them have own shortcuts. " +
- "But for rare refactorings you can use ${action(it)} and see a partial list of them."
+ LessonsBundle.message("python.refactoring.menu.show.refactoring.list", action(it))
}
- task("Introduce Parameter") {
- text("Suppose we want to replace this expression with a parameter. So we need to choose <strong>$it...</strong>. " +
- "Now simply type ${code("pa")} (as prefix of Parameter) to reduce proposed list.")
+ task(ActionsBundle.message("action.IntroduceParameter.text").dropMnemonic()) {
+ val prefix = LessonsBundle.message("python.refactoring.menu.required.prefix")
+ text(LessonsBundle.message("python.refactoring.menu.introduce.parameter", strong(it), strong(prefix)))
triggerByUiComponentAndHighlight(highlightBorder = false, highlightInside = false) { ui: JList<*> ->
ui.model.size > 0 && ui.model.getElementAt(0).toString().contains(it)
}
test {
- type("pa")
+ type(prefix)
}
}
task {
- text("Press ${action("EditorEnter")} to start Introduce Parameter refactoring.")
+ text(LessonsBundle.message("python.refactoring.menu.start.refactoring", action("EditorChooseLookupItem")))
trigger("IntroduceParameter")
stateCheck { hasInplaceRename() }
test {
}
task {
- text("To complete refactoring, you need to choose some name or leave it as default and press ${action("EditorEnter")}.")
+ text(LessonsBundle.message("python.refactoring.menu.finish.refactoring", LessonUtil.rawEnter()))
stateCheck {
!hasInplaceRename()
}
import com.intellij.ide.DataManager
import com.intellij.ide.actions.exclusion.ExclusionHandler
import com.intellij.openapi.application.runReadAction
+import com.intellij.refactoring.RefactoringBundle
import com.intellij.testGuiFramework.framework.GuiTestUtil
import com.intellij.testGuiFramework.framework.Timeouts
import com.intellij.testGuiFramework.impl.button
import com.intellij.util.ui.tree.TreeUtil
import org.jetbrains.annotations.Nullable
import training.commands.kotlin.TaskTestContext
+import training.learn.LessonsBundle
import training.learn.interfaces.Module
import training.learn.lesson.kimpl.KLesson
import training.learn.lesson.kimpl.LessonContext
+import training.learn.lesson.kimpl.dropMnemonic
import training.learn.lesson.kimpl.parseLessonSample
import java.util.regex.Pattern
import javax.swing.JButton
import javax.swing.tree.TreePath
class PythonRenameLesson(module: Module)
- : KLesson("Rename", "Rename", module, "Python") {
+ : KLesson("Rename", LessonsBundle.message("rename.lesson.name"), module, "Python") {
private val template = """
class Championship:
def __init__(self):
prepareSample(sample)
var replace: String? = null
task("RenameElement") {
- text("Press ${action(it)} to rename field <code>teams</code> (e.g., to <code>teams_number</code>).")
+ text(LessonsBundle.message("python.rename.press.rename", action(it), code("teams"), code("teams_number")))
triggerByFoundPathAndHighlight { tree: JTree, path: TreePath ->
if (path.pathCount == 2 && path.getPathComponent(1).toString().contains("Dynamic")) {
replace = replacePreviewPattern.matcher(tree.model.root.toString()).takeIf { m -> m.find() }?.group(1)
TreeUtil.collapseAll(tree, 1)
}
}
- text("In simple cases PyCharm will just rename without confirmation. But in this sample PyCharm sees two calls of " +
- "${code("teams")} method for objects with unknown type. Expand <strong>Dynamic references</strong> item.")
+ val dynamicReferencesString = LessonsBundle.message("python.rename.dynamic.references.prefix")
+ text(LessonsBundle.message("python.rename.expand.dynamic.references",
+ code("teams"), strong("dynamicReferencesString")))
triggerByFoundPathAndHighlight { _: JTree, path: TreePath ->
path.pathCount == 6 && path.getPathComponent(5).toString().contains("company_members")
test {
ideFrame {
val jTree = runReadAction {
- jTree("Dynamic references", timeout = Timeouts.seconds03, predicate = substringPredicate)
+ jTree(dynamicReferencesString, timeout = Timeouts.seconds03, predicate = substringPredicate)
}
// WARNING: several exception will be here because of UsageNode#toString inside info output during this operation
jTree.doubleClickPath()
}
task {
- text("It seems ${code("company_members")} should be excluded from rename. " +
- "Select it and press ${action("EditorDelete")}.")
+ text(LessonsBundle.message("python.rename.exclude.item", code("company_members"), action("EditorDelete")))
stateCheck {
val tree = previous.ui as? JTree ?: return@stateCheck false
}
}
+ val confirmRefactoringButton = RefactoringBundle.message("usageView.doAction").dropMnemonic()
task {
triggerByUiComponentAndHighlight(highlightInside = false) { button: JButton ->
- button.text == "Do Refactor"
+ button.text == confirmRefactoringButton
}
}
task {
val result = replace?.let { template.replace("<name>", it).replace("<caret>", "") }
- text("Now just finish the rename with the <strong>Do Refactor</strong> button.")
+ text(LessonsBundle.message("python.rename.finish.refactoring", strong(confirmRefactoringButton)))
stateCheck { editor.document.text == result }
test {
ideFrame {
- button("Do Refactor").click()
+ button(confirmRefactoringButton).click()
}
}
}
import com.intellij.icons.AllIcons
import training.commands.kotlin.TaskTestContext
+import training.learn.LessonsBundle
import training.learn.interfaces.Module
import training.learn.lesson.general.run.CommonDebugLesson
import training.learn.lesson.kimpl.LessonContext
mayBeStopped = true
}
proposeModificationRestore(afterFixText)
- "Let's rerun our program. Just click again at ${icon(AllIcons.Actions.Restart)} or use ${action(it)}."
+ LessonsBundle.message("python.debug.workflow.rerun", icon(AllIcons.Actions.Restart), action(it))
}
}
// Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package training.learn.lesson.python.run
+import training.learn.LessonsBundle
import training.learn.interfaces.Module
import training.learn.lesson.general.run.CommonRunConfigurationLesson
import training.learn.lesson.kimpl.LessonContext
override fun LessonContext.runTask() {
task("RunClass") {
- text("Let's run our simple example with ${action(it)}.")
+ text(LessonsBundle.message("python.run.configuration.lets.run", action(it)))
//Wait toolwindow
toolWindowShowed("Run")
stateCheck {
// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package training.learn.lesson.ruby.completion
+import training.learn.LessonsBundle
import training.learn.interfaces.Module
import training.learn.lesson.kimpl.KLesson
import training.learn.lesson.kimpl.LessonContext
import training.learn.lesson.kimpl.parseLessonSample
class RubyHippieCompletionLesson(module: Module)
- : KLesson("Hippie Completion", "Hippie Completion", module, "ruby") {
+ : KLesson("Hippie Completion", LessonsBundle.message("ruby.hippie.completion.lesson.name"), module, "ruby") {
private val sample = parseLessonSample("""class SomeExampleClass
attr_reader :callbacks
val step1 = calculateResult("fore_save")
val step2 = calculateResult("fore_create")
task("HippieCompletion") {
- text("Sometimes you need to complete a word by textual similarity. Press ${action(it)} to invoke hippie completion.")
+ text(LessonsBundle.message("ruby.hippie.completion.invoke.hippie.completion", action(it)))
trigger(it) { editor.document.text == step1 }
test { actions(it) }
}
task("HippieCompletion") {
- text("You can repeat ${action(it)} until the desired word is found. Try it once more now.")
+ text(LessonsBundle.message("ruby.hippie.completion.repeat.one.time", action(it)))
trigger(it) { editor.document.text == step2 }
test { actions(it) }
}
task("HippieBackwardCompletion") {
- text("You can return to the previous variant with ${action(it)}. Use it now.")
+ text(LessonsBundle.message("ruby.hippie.completion.return.previous", action(it)))
trigger(it) { editor.document.text == step1 }
test { actions(it) }
}
import com.intellij.testGuiFramework.framework.GuiTestUtil.typeText
import com.intellij.testGuiFramework.impl.jList
+import training.learn.LessonsBundle
import training.learn.interfaces.Module
import training.learn.lesson.kimpl.KLesson
import training.learn.lesson.kimpl.LessonContext
-import training.learn.lesson.kimpl.LessonUtil
import training.learn.lesson.kimpl.LessonUtil.checkExpectedStateOfEditor
import training.learn.lesson.kimpl.parseLessonSample
class RubyPostfixCompletionLesson(module: Module)
- : KLesson("Postfix completion", "Postfix completion", module, "ruby") {
+ : KLesson("Postfix completion", LessonsBundle.message("postfix.completion.lesson.name"), module, "ruby") {
private val sample = parseLessonSample("""class SomeExampleClass
# @param string_array [Array<String>]
get() = {
prepareSample(sample)
task {
- text("The IDE can offer postfix shortcuts. Type ${code(".if")}.")
+ text(LessonsBundle.message("postfix.completion.type.template", code(".if")))
triggerByListItemAndHighlight {
it.toString() == ".if"
}
}
}
task {
- text("Now just press ${action("EditorEnter")} to choose the first postfix template.")
+ text(LessonsBundle.message("ruby.postfix.completion.apply", action("EditorChooseLookupItem")))
triggerByListItemAndHighlight {
it.toString() == "string_array.length > 1"
}
}
task("string_array.length > 1") {
- text("Now choose the second item, ${code(it)}.")
+ text(LessonsBundle.message("ruby.postfix.completion.choose.target", code(it)))
stateCheck { editor.document.text == result }
restoreByUi()
test {
import com.intellij.testGuiFramework.util.Key
import com.intellij.ui.components.fields.ExtendableTextField
import training.commands.kotlin.TaskRuntimeContext
+import training.learn.LessonsBundle
import training.learn.interfaces.Module
import training.learn.lesson.kimpl.KLesson
import training.learn.lesson.kimpl.LessonContext
+import training.learn.lesson.kimpl.LessonUtil
class RubyClassSearchLesson(module: Module)
- : KLesson("Class Search", "Class Search", module, "ruby") {
+ : KLesson("Class Search", LessonsBundle.message("ruby.class.search.lesson.name"), module, "ruby") {
override val lessonContent: LessonContext.() -> Unit
get() = {
caret(0)
actionTask("GotoClass") {
- "Try to find a class with ${action(it)}"
+ LessonsBundle.message("ruby.class.search.invoke.goto.class", action(it))
}
task("date") {
- text("Type <code>$it</code> to see classes that contain the word <strong>$it</strong>.")
+ text(LessonsBundle.message("ruby.class.search.type.word", code(it), strong(it)))
stateCheck { checkWordInSearch(it) }
test { type(it) }
}
task("datebe") {
- text("You can search for a class by part of its name. Type <code>be</code> (the search string will be <code>$it</code>) " +
- "to see classes that contain the words <strong>date</strong> and <strong>be</strong>.")
+ text(LessonsBundle.message("ruby.class.search.type.second.prefix", code("be"), code(it), strong("date"), strong("be")))
stateCheck { checkWordInSearch(it) }
test { type("be") }
}
task("QuickImplementations") {
- text("To check the selected class before navigating to it, you can use ${action(it)} to see its quick definition.")
+ text(LessonsBundle.message("ruby.class.search.preview", action(it)))
trigger(it)
test { actions(it) }
}
task {
- text("Suppose you are looking for ${code("DateAndTimeBehavior")}." +
- "Choose it and then press <strong>Enter</strong> to navigate.")
+ text(LessonsBundle.message("ruby.class.search.navigate.to.target", code("DateAndTimeBehavior"), LessonUtil.rawEnter()))
stateCheck {
FileEditorManager.getInstance(project).selectedEditor?.file?.name.equals("date_and_time_behavior.rb")
}
class RubyDeclarationAndUsagesLesson(module: Module) : DeclarationAndUsagesLesson(module, "ruby") {
override fun LessonContext.setInitialPosition() = caret(20, 45)
- override val typeOfEntity = "an attribute accessor"
+ override val typeOfEntity = 1
override val existedFile: String = "lib/active_support/core_ext/date/calculations.rb"
}
package training.learn.lesson.ruby.refactorings
import com.intellij.openapi.project.Project
+import com.intellij.refactoring.RefactoringBundle
import com.intellij.testGuiFramework.impl.button
import com.intellij.testGuiFramework.impl.jList
import org.jetbrains.plugins.ruby.ruby.codeInsight.symbols.Types
import org.jetbrains.plugins.ruby.ruby.codeInsight.symbols.fqn.FQN
import org.jetbrains.plugins.ruby.ruby.codeInsight.symbols.structure.SymbolUtil
import training.commands.kotlin.TaskTestContext
+import training.learn.LessonsBundle
import training.learn.interfaces.Module
import training.learn.lesson.kimpl.KLesson
import training.learn.lesson.kimpl.LessonContext
import training.learn.lesson.kimpl.parseLessonSample
class RubyRefactorMenuLesson(module: Module)
- : KLesson("Refactoring menu", "Refactoring menu", module, "ruby") {
+ : KLesson("Refactoring menu", LessonsBundle.message("refactoring.menu.lesson.name"), module, "ruby") {
private val sample = parseLessonSample("""
class Animal
get() = {
prepareSample(sample)
actionTask("Refactorings.QuickListPopupAction") {
- "RubyMine supports a variety of refactorings. Press ${action(it)} to see a partial list of them."
+ LessonsBundle.message("ruby.refactoring.menu.invoke.refactoring.list", action(it))
}
- task("Push Members Down") {
- text("Some refactorings are seldom used and have no shortcut, but you can find them here. " +
- "Choose <strong>$it...</strong> now and complete the refactoring on <code>meow()</code>.")
+ task(RefactoringBundle.message("push.members.down.title")) {
+ text(LessonsBundle.message("ruby.refactoring.menu.use.push.method.down", strong(it), code("meow()")))
trigger("MemberPushDown") { checkMethodMoved(project) }
test {
ideFrame {
// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package training.learn.lesson.ruby.refactorings
+import com.intellij.refactoring.RefactoringBundle
import com.intellij.testGuiFramework.impl.button
import com.intellij.ui.treeStructure.Tree
import training.commands.kotlin.TaskTestContext
+import training.learn.LessonsBundle
import training.learn.interfaces.Module
import training.learn.lesson.kimpl.KLesson
import training.learn.lesson.kimpl.LessonContext
+import training.learn.lesson.kimpl.dropMnemonic
import training.learn.lesson.kimpl.parseLessonSample
import java.util.concurrent.Future
import java.util.concurrent.TimeUnit
import java.util.regex.Pattern
class RubyRenameLesson(module: Module)
- : KLesson("Rename", "Rename", module, "ruby") {
+ : KLesson("Rename", LessonsBundle.message("rename.lesson.name"), module, "ruby") {
private val template = """
class Championship
prepareSample(sample)
lateinit var replace: Future<String>
task("RenameElement") {
- text("Press ${action(it)} to rename the attribute accessor <code>teams</code> (e.g., to <code>teams_number</code>).")
+ text(LessonsBundle.message("ruby.rename.start.refactoring", action(it), code("teams"), code("teams_number")))
replace = stateRequired {
(focusOwner as? Tree)?.model?.root?.toString()?.let { root: String ->
replacePreviewPattern.matcher(root).takeIf { m -> m.find() }?.group(1)
}
}
}
- task("Do Refactor") {
+ task(RefactoringBundle.message("usageView.doAction").dropMnemonic()) {
var result = ""
before {
result = template.replace("<name>", replace.get(2, TimeUnit.SECONDS)).replace("<caret>", "")
}
- text("In order to be confident about the refactoring, RubyMine lets you preview it before confirming." +
- "Click <strong>$it</strong> to complete the refactoring.")
+ text(LessonsBundle.message("ruby.rename.confirm", strong(it)))
stateCheck { editor.document.text == result }
test {
ideFrame {