Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Add custom digraph support #984

Merged
merged 17 commits into from
Sep 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 3 additions & 7 deletions src/main/java/com/maddyhome/idea/vim/VimPlugin.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,7 @@
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.util.SystemInfo;
import com.maddyhome.idea.vim.api.VimEditor;
import com.maddyhome.idea.vim.api.VimInjectorKt;
import com.maddyhome.idea.vim.api.VimKeyGroup;
import com.maddyhome.idea.vim.api.VimOptionGroup;
import com.maddyhome.idea.vim.api.*;
import com.maddyhome.idea.vim.config.VimState;
import com.maddyhome.idea.vim.config.migration.ApplicationConfigurationMigrator;
import com.maddyhome.idea.vim.extension.VimExtensionRegistrar;
Expand All @@ -36,7 +33,6 @@
import com.maddyhome.idea.vim.group.visual.VisualMotionGroup;
import com.maddyhome.idea.vim.helper.MacKeyRepeat;
import com.maddyhome.idea.vim.listener.VimListenerManager;
import com.maddyhome.idea.vim.newapi.IjVimInjector;
import com.maddyhome.idea.vim.newapi.IjVimInjectorKt;
import com.maddyhome.idea.vim.newapi.IjVimSearchGroup;
import com.maddyhome.idea.vim.ui.StatusBarIconFactory;
Expand Down Expand Up @@ -141,8 +137,8 @@ public class VimPlugin implements PersistentStateComponent<Element>, Disposable
return (MacroGroup)VimInjectorKt.getInjector().getMacro();
}

public static @NotNull DigraphGroup getDigraph() {
return (DigraphGroup)VimInjectorKt.getInjector().getDigraphGroup();
public static @NotNull VimDigraphGroup getDigraph() {
return VimInjectorKt.getInjector().getDigraphGroup();
}

public static @NotNull HistoryGroup getHistory() {
Expand Down
83 changes: 0 additions & 83 deletions src/main/java/com/maddyhome/idea/vim/group/DigraphGroup.java

This file was deleted.

25 changes: 19 additions & 6 deletions src/main/java/com/maddyhome/idea/vim/helper/EditorHelper.java
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,19 @@ public static int getApproximateScreenWidth(final @NotNull Editor editor) {
return (int)(getVisibleArea(editor).width / getPlainSpaceWidthFloat(editor));
}

/**
* Gets the number of characters that can be fit inside the output panel for an editor.
* <p>
* This will be greater than the approximate screen width as it also includes any gutter components in the editor.
* </p>
*
* @param editor The editor
* @return The approximate number of columns that can fit in the output panel
*/
public static int getApproximateOutputPanelWidth(final @NotNull Editor editor) {
return (int)(editor.getComponent().getWidth() / getPlainSpaceWidthFloat(editor));
}

/**
* Gets the width of the space character in the editor's plain font as a float.
* <p>
Expand Down Expand Up @@ -273,7 +286,7 @@ else if (bottomInlayHeight > visibleArea.height - caretScreenOffset + editor.get

// Scroll the given visual line to the caret location, but do not scroll down passed the end of file, or the current
// virtual space at the bottom of the screen
@NotNull final VimEditor editor1 = new IjVimEditor(editor);
final @NotNull VimEditor editor1 = new IjVimEditor(editor);
final int lastVisualLine = EngineEditorHelperKt.getVisualLineCount(editor1) - 1;
final int yBottomLineOffset = max(getOffsetToScrollVisualLineToBottomOfScreen(editor, lastVisualLine), visibleArea.y);
scrollVertically(editor, min(yVisualLine - caretScreenOffset - inlayOffset, yBottomLineOffset));
Expand Down Expand Up @@ -325,7 +338,7 @@ public static void scrollVisualLineToMiddleOfScreen(@NotNull Editor editor, int
final int lineHeight = editor.getLineHeight();

final int offset = y - ((screenHeight - lineHeight) / lineHeight / 2 * lineHeight);
@NotNull final VimEditor editor1 = new IjVimEditor(editor);
final @NotNull VimEditor editor1 = new IjVimEditor(editor);
final int lastVisualLine = EngineEditorHelperKt.getVisualLineCount(editor1) - 1;
final int offsetForLastLineAtBottom = getOffsetToScrollVisualLineToBottomOfScreen(editor, lastVisualLine);

Expand Down Expand Up @@ -379,7 +392,7 @@ private static int getExEntryHeight() {
return 0;
}

private static int getHorizontalScrollbarHeight(@NotNull final Editor editor) {
private static int getHorizontalScrollbarHeight(final @NotNull Editor editor) {
// Horizontal scrollbars on macOS are either transparent AND auto-hide, so we don't need to worry about obscured
// text, or always visible, opaque and outside the content area, so we don't need to adjust for them
// Transparent scrollbars on Windows and Linux are overlays on the editor content area, and always visible. That
Expand Down Expand Up @@ -462,7 +475,7 @@ public static void scrollColumnToRightOfScreen(@NotNull Editor editor, int visua
*/
public static Pair<Boolean, Integer> scrollFullPageDown(final @NotNull Editor editor, int pages) {
final Rectangle visibleArea = getVisibleArea(editor);
@NotNull final VimEditor editor2 = new IjVimEditor(editor);
final @NotNull VimEditor editor2 = new IjVimEditor(editor);
final int lastVisualLine = EngineEditorHelperKt.getVisualLineCount(editor2) - 1;

int y = visibleArea.y + visibleArea.height;
Expand All @@ -480,7 +493,7 @@ public static Pair<Boolean, Integer> scrollFullPageDown(final @NotNull Editor ed
caretVisualLine = lastVisualLine;
}
else {
@NotNull final VimEditor editor1 = new IjVimEditor(editor);
final @NotNull VimEditor editor1 = new IjVimEditor(editor);
caretVisualLine = EngineEditorHelperKt.getVisualLineCount(editor1) - 1;
completed = false;
}
Expand Down Expand Up @@ -515,7 +528,7 @@ public static Pair<Boolean, Integer> scrollFullPageDown(final @NotNull Editor ed
public static Pair<Boolean, Integer> scrollFullPageUp(final @NotNull Editor editor, int pages) {
final Rectangle visibleArea = getVisibleArea(editor);
final int lineHeight = editor.getLineHeight();
@NotNull final VimEditor editor1 = new IjVimEditor(editor);
final @NotNull VimEditor editor1 = new IjVimEditor(editor);
final int lastVisualLine = EngineEditorHelperKt.getVisualLineCount(editor1) - 1;

int y = visibleArea.y;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ import com.intellij.openapi.editor.ReadOnlyFragmentModificationException
import com.intellij.openapi.editor.VisualPosition
import com.intellij.openapi.editor.actionSystem.EditorActionManager
import com.intellij.openapi.editor.ex.util.EditorUtil
import com.maddyhome.idea.vim.api.EngineEditorHelper
import com.maddyhome.idea.vim.api.EngineEditorHelperBase
import com.maddyhome.idea.vim.api.VimEditor
import com.maddyhome.idea.vim.api.VimRangeMarker
Expand Down Expand Up @@ -42,6 +41,10 @@ internal class IjEditorHelper : EngineEditorHelperBase() {
return EditorHelper.getApproximateScreenWidth(editor.ij)
}

override fun getApproximateOutputPanelWidth(editor: VimEditor): Int {
return EditorHelper.getApproximateOutputPanelWidth(editor.ij)
}

override fun handleWithReadonlyFragmentModificationHandler(editor: VimEditor, exception: Exception) {
return EditorActionManager.getInstance()
.getReadonlyFragmentModificationHandler(editor.ij.document)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
serviceInterface="com.maddyhome.idea.vim.api.VimCommandLineService"/>
<applicationService serviceImplementation="com.maddyhome.idea.vim.ui.ex.IjOutputPanelService"
serviceInterface="com.maddyhome.idea.vim.api.VimOutputPanelService"/>
<applicationService serviceImplementation="com.maddyhome.idea.vim.group.DigraphGroup"
<applicationService serviceImplementation="com.maddyhome.idea.vim.api.VimDigraphGroupBase"
serviceInterface="com.maddyhome.idea.vim.api.VimDigraphGroup"/>
<applicationService serviceImplementation="com.maddyhome.idea.vim.group.HistoryGroup"/>
<applicationService serviceImplementation="com.maddyhome.idea.vim.group.KeyGroup"
Expand Down
2 changes: 2 additions & 0 deletions src/main/resources/messages/IdeaVimBundle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ E20=E20: Mark not set
e_nopresub=E33: No previous substitute regular expression
e_noprev=E34: No previous command
e_noprevre=E35: No previous regular expression
E39=E39: Number expected
e_re_damg=E43: Damaged match string
e_re_corr=E44: Currupted regexp program
E50=E50: Too many \\z(
Expand Down Expand Up @@ -84,6 +85,7 @@ E549=E549: Illegal percentage: {0}
E774=E774: 'operatorfunc' is empty
e841.reserved.name.cannot.be.used.for.user.defined.command=E841: Reserved name, cannot be used for user defined command
E939=E939: Positive count required
E1214=E1214: Digraph must be just two characters: {0}

message.search.hit.bottom=search hit BOTTOM, continuing at TOP
message.search.hit.top=search hit TOP, continuing at BOTTOM
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
/*
* Copyright 2003-2024 The IdeaVim authors
*
* Use of this source code is governed by an MIT-style
* license that can be found in the LICENSE.txt file or at
* https://opensource.org/licenses/MIT.
*/

package org.jetbrains.plugins.ideavim.action.change.insert

import org.jetbrains.plugins.ideavim.VimTestCase
import org.junit.jupiter.api.Test

class InsertCompletedDigraphActionTest : VimTestCase() {
@Test
fun `test insert digraph`() {
doTest(listOf("i", "<C-K>OK", "<Esc>"), "", "✓")
}

@Test
fun `test insert digraph with reversed characters`() {
doTest(listOf("i", "<C-K>KO", "<Esc>"), "", "✓")
}

@Test
fun `test insert same character with different digraphs`() {
doTest(listOf("i", "<C-K>Ct", "<C-K>c|", "<Esc>"), "", "¢¢")
}

@Test
fun `test insert custom digraph`() {
doTest(listOf("i", "<C-K>(0", "<Esc>"), "", "⓪") {
enterCommand("digraph (0 9450")
}
}

@Test
fun `test insert custom digraph with reversed characters`() {
doTest(listOf("i", "<C-K>0(", "<Esc>"), "", "⓪") {
enterCommand("digraph (0 9450")
}
}

@Test
fun `test insert custom digraph overriding existing custom digraph`() {
doTest(listOf("i", "<C-K>(0", "<Esc>"), "", "✓") {
enterCommand("digraph (0 9450")
enterCommand("digraph (0 10003")
}
}

@Test
fun `test insert custom digraph overriding existing default digraph`() {
doTest(listOf("i", "<C-K>OK", "<Esc>"), "", "⓪") {
enterCommand("digraph OK 9450")
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,54 +11,70 @@ package org.jetbrains.plugins.ideavim.ex.implementation.commands
import com.maddyhome.idea.vim.VimPlugin
import org.jetbrains.plugins.ideavim.VimTestCase
import org.junit.jupiter.api.Test
import kotlin.test.assertEquals

class AsciiCommandTest : VimTestCase() {
@Test
fun `test shows ascii value under caret`() {
configureByText("${c}Hello world")
enterCommand("ascii")
kotlin.test.assertEquals("<H> 72, Hex 48, Oct 110", VimPlugin.getMessage())
assertEquals("<H> 72, Hex 48, Oct 110", VimPlugin.getMessage())
}

@Test
fun `test show ascii for space`() {
configureByText("$c ")
enterCommand("ascii")
kotlin.test.assertEquals("< > 32, Hex 20, Oct 040, Digr SP", VimPlugin.getMessage())
assertEquals("< > 32, Hex 20, Oct 040, Digr SP", VimPlugin.getMessage())
}

@Test
fun `test shows unprintable ascii code`() {
configureByText("${c}\u0009")
enterCommand("ascii")
kotlin.test.assertEquals("<^I> 9, Hex 09, Oct 011, Digr HT", VimPlugin.getMessage())
assertEquals("<^I> 9, Hex 09, Oct 011, Digr HT", VimPlugin.getMessage())
}

@Test
fun `test shows unprintable ascii code 2`() {
configureByText("${c}\u007f")
enterCommand("ascii")
kotlin.test.assertEquals("<^?> 127, Hex 7f, Oct 177, Digr DT", VimPlugin.getMessage())
assertEquals("<^?> 127, Hex 7f, Oct 177, Digr DT", VimPlugin.getMessage())
}

@Test
fun `test shows unprintable ascii code 3`() {
configureByText("${c}\u0006")
enterCommand("ascii")
kotlin.test.assertEquals("<^F> 6, Hex 06, Oct 006, Digr AK", VimPlugin.getMessage())
assertEquals("<^F> 6, Hex 06, Oct 006, Digr AK", VimPlugin.getMessage())
}

@Test
fun `test unicode char with 3 hex digits`() {
configureByText("${c}œ")
enterCommand("ascii")
kotlin.test.assertEquals("<œ> 339, Hex 0153, Oct 523, Digr oe", VimPlugin.getMessage())
assertEquals("<œ> 339, Hex 0153, Oct 523, Digr oe", VimPlugin.getMessage())
}

@Test
fun `test unicode char with 4 hex digits`() {
configureByText("✓")
enterCommand("ascii")
kotlin.test.assertEquals("<✓> 10003, Hex 2713, Oct 23423, Digr OK", VimPlugin.getMessage())
assertEquals("<✓> 10003, Hex 2713, Oct 23423, Digr OK", VimPlugin.getMessage())
}

@Test
fun `test shows correct digraph for character that can be created from multiple digraphs`() {
configureByText("¢") // Can be entered with <C-K>Ct and <C-K>c|, should show Ct as the first digraph
enterCommand("ascii")
assertEquals("<¢> 162, Hex a2, Oct 242, Digr Ct", VimPlugin.getMessage())
}

@Test
fun `test shows custom digraph`() {
configureByText("⓪")
enterCommand("digraph (0 9450")
enterCommand("ascii")
assertEquals("<⓪> 9450, Hex 24ea, Oct 22352, Digr (0", VimPlugin.getMessage())
}
}
Loading
Loading