Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
78 commits
Select commit Hold shift + click to select a range
1b50291
fix(deps): update dependency org.robolectric:robolectric to v4.16.1
renovate[bot] Jan 21, 2026
cbbe95f
Merge pull request #794 from Rosemoe/renovate/org.robolectric-robolec…
Rosemoe Jan 28, 2026
6f67c6f
Update DefaultCompletionLayout.java
nullij Feb 3, 2026
0535af5
Merge pull request #800 from nullij/patch-1
Rosemoe Feb 4, 2026
b3a8b17
refact(editor): expose `variableResolver` for custom variable resolve…
Rosemoe Feb 6, 2026
533c6dc
chore(editor): refer to inlay hint type names in inlay hint renderers
Rosemoe Feb 6, 2026
0eff59f
fix(editor): add max text length for accessibility node info
Rosemoe Feb 8, 2026
27a6cc4
build(app): migrate signing config to environment variables
Rosemoe Feb 8, 2026
d0e0916
build(app): move signing config vars to job-level env
Rosemoe Feb 8, 2026
9f20f82
docs(textmate): update README.md for TextMate
Rosemoe Feb 8, 2026
efbacac
fix(editor): `SymbolInputView` always overrides the background define…
Rosemoe Feb 8, 2026
099b8be
refact(app): migrate to Material 3
Rosemoe Feb 8, 2026
56e7166
fix(editor): non-null param is declared nullable in `SpanExternalRend…
Rosemoe Feb 9, 2026
77c8ab7
fix(editor): text style in line info panel can be affected by content…
Rosemoe Feb 9, 2026
795f2f0
fix(app): inconsistent inlay hint position in demo
Rosemoe Feb 9, 2026
1bf3548
docs: update screenshots in project README
Rosemoe Feb 9, 2026
b6f8384
fix: fix `ConcurrentModificationException` and expose language server…
KonerDev Feb 10, 2026
db7d487
feat: improve LSP server lifecycle and error handling
KonerDev Feb 11, 2026
7cfa568
chore(deps): update plugin publish to v0.36.0
renovate[bot] Feb 12, 2026
89799c0
chore(deps): update gradle/actions action to v5
renovate[bot] Feb 12, 2026
16c99d0
chore(deps): update agp to v9.0.1
renovate[bot] Feb 13, 2026
87fa0f3
fix(editor-lsp): improve editor lifecycle
KonerDev Feb 18, 2026
76b9f73
refactor(editor-lsp): move exception handling to separate method
KonerDev Feb 19, 2026
700c744
fix: stopping server does no longer disconnect all servers
KonerDev Feb 19, 2026
c5b7349
fix(deps): update dependency org.jruby.jcodings:jcodings to v1.0.64
renovate[bot] Feb 20, 2026
f361f25
Merge pull request #804 from KonerDev/fix/concurrent-exception
Rosemoe Feb 20, 2026
f4111ff
Merge pull request #807 from Rosemoe/renovate/org.jruby.jcodings-jcod…
Rosemoe Feb 20, 2026
2093386
fix: fix unnecessary stop of language server wrapper by tracking conn…
KonerDev Feb 20, 2026
46a9bd5
Merge pull request #808 from KonerDev/fix/unnecessary-stop
Rosemoe Feb 21, 2026
99624d5
feat: add disable-feature option to server definition (Closes #802)
KonerDev Feb 21, 2026
084af3c
fix: fix hover window not showing (Closes #796)
KonerDev Feb 21, 2026
004e85b
fix(deps): update dependency org.jruby.joni:joni to v2.2.7
renovate[bot] Feb 25, 2026
fe24675
Merge pull request #809 from KonerDev/feat/disable-ls-features
Rosemoe Feb 25, 2026
42a4175
Merge pull request #810 from Rosemoe/renovate/org.jruby.joni-joni-2.x
Rosemoe Feb 25, 2026
9242793
Merge pull request #805 from Rosemoe/renovate/agp
Rosemoe Feb 25, 2026
07b035a
fix: possible null reference in `EditorRenderer#applySelectedTextRange`
Rosemoe Feb 25, 2026
cd9a784
Merge remote-tracking branch 'origin/main'
Rosemoe Feb 25, 2026
813bac9
Merge pull request #791 from Rosemoe/renovate/com.vanniktech.maven.pu…
Rosemoe Feb 25, 2026
f55af1c
feat(deps): update Kotlin to v2.3.10
Rosemoe Feb 25, 2026
f07397e
fix(deps): update dependency org.eclipse.lsp4j:org.eclipse.lsp4j to v1
renovate[bot] Feb 27, 2026
09bec91
fix(editor): fix `IndexOutOfBoundsException` on completion
KonerDev Feb 28, 2026
30c1ddc
Merge pull request #812 from KonerDev/fix/oob-completion
Rosemoe Mar 1, 2026
be49c69
fix(editor): leading whitespace is sometimes wrongly hidden
Rosemoe Mar 3, 2026
5d49f36
refact(editor): store text in byte array instead of char array to cut…
Rosemoe Mar 3, 2026
59717e6
Merge remote-tracking branch 'origin/main'
Rosemoe Mar 3, 2026
ca60f69
test(editor): add test for `ContentLine`
Rosemoe Mar 3, 2026
10370f8
perf(editor): avoid copying when create `String` in Latin1 implementa…
Rosemoe Mar 3, 2026
36306af
feat(editor): add experimental shallow copying in `AsyncIncrementalAn…
Rosemoe Mar 3, 2026
d9e5ba5
fix(editor): missing support for multiline code block with more than …
Rosemoe Mar 3, 2026
6f97f74
feat(app): add sample for paged editing for long files
Rosemoe Mar 4, 2026
c28ca33
Merge pull request #753 from Rosemoe/renovate/gradle-actions-5.x
Rosemoe Mar 5, 2026
7ccb3f6
docs: fix license badge
Rosemoe Mar 5, 2026
4216bd9
Merge remote-tracking branch 'origin/main'
Rosemoe Mar 5, 2026
22c6a82
fix(lsp): app crash when `textDocument/inlayHint` or `textDocument/do…
Rosemoe Mar 5, 2026
fdb0a2a
feat(lsp): partially support API changes in LSP4J v1.0 (LSP v3.18.0)
Rosemoe Mar 5, 2026
acdc2fd
fix(ci): `branches-ignore` field for renovate is wrong
Rosemoe Mar 5, 2026
2d06427
chore(deps): update actions/upload-artifact action to v7
renovate[bot] Mar 5, 2026
439456f
Merge pull request #803 from Rosemoe/renovate/major-lsp4j
Rosemoe Mar 5, 2026
aa3b884
Merge pull request #811 from Rosemoe/renovate/major-github-artifact-a…
Rosemoe Mar 5, 2026
298544e
feat(editor): add option to ensure search occurrence is visible
KonerDev Mar 7, 2026
9443e01
fix: only use SpanFactory.obtain when underline is needed in TextMate…
META-Xiao Mar 13, 2026
d349902
test: add unit tests for span selection logic in TextMateAnalyzer
META-Xiao Mar 13, 2026
cbe3d28
fix(monarch): underline color leads to failure in analyzer (similar i…
Rosemoe Mar 13, 2026
c31940f
Merge pull request #820 from META-Xiao/fix/textmate-span-underline-op…
Rosemoe Mar 13, 2026
f21898e
Merge remote-tracking branch 'origin/main'
Rosemoe Mar 13, 2026
9f6ad9f
feat(editor): add experimental minimap, disabled by default (#766)
Rosemoe Mar 14, 2026
0bb17e4
Merge pull request #816 from KonerDev/feat/searcher-occurence
Rosemoe Mar 14, 2026
20a7b8d
chore(minimap): add doc comment for `MinimapCharRenderer` and replace…
Rosemoe Mar 14, 2026
32b6e2f
docs(editor): add some clarifications in `Language` doc comments
Rosemoe Mar 14, 2026
b10bd9a
chore(langs): make exception message more detail
Rosemoe Mar 15, 2026
b9bd53d
fix(editor): empty spans in `Styles` may lead to NPE
Rosemoe Mar 15, 2026
7cdb8b0
fix(editor): render nodes of sticky lines are abandoned, leading to u…
Rosemoe Mar 15, 2026
6bcea90
feat(editor): send partial spans as the analysis goes
Rosemoe Mar 15, 2026
b39ad1b
fix(textmate): underline without explicit color leads failure in Text…
Rosemoe Mar 16, 2026
76695be
refact(editor): move minimap config fields to data class
Rosemoe Mar 16, 2026
0fdd4a8
chore: bump version to 0.24.5
Rosemoe Mar 16, 2026
1528e5b
fix(publishing): migrate to new variant ctor API
Rosemoe Mar 16, 2026
d6176a0
chore: update with upstream changes
KonerDev Mar 21, 2026
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
4 changes: 2 additions & 2 deletions build-logic/convention/src/main/kotlin/Versions.kt
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@
@SuppressWarnings("unused")
object Versions {
// Project versions
private const val version = "0.24.4"
const val versionCode = 93
private const val version = "0.24.5"
const val versionCode = 94

val appVersionName by lazy {
if (CI.isCiBuild) {
Expand Down
6 changes: 4 additions & 2 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,9 @@
import com.android.build.api.dsl.ApplicationExtension
import com.android.build.api.dsl.CommonExtension
import com.vanniktech.maven.publish.AndroidSingleVariantLibrary
import com.vanniktech.maven.publish.JavadocJar
import com.vanniktech.maven.publish.MavenPublishBaseExtension
import com.vanniktech.maven.publish.SourcesJar
import org.jetbrains.kotlin.gradle.dsl.JvmTarget
import org.jetbrains.kotlin.gradle.dsl.KotlinAndroidExtension

Expand Down Expand Up @@ -100,8 +102,8 @@ subprojects {
configure(
AndroidSingleVariantLibrary(
variant = "release",
sourcesJar = true,
publishJavadocJar = false
sourcesJar = SourcesJar.Sources(),
javadocJar = JavadocJar.None()
)
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,13 +42,12 @@
/**
* Language for editor
* <p>
* A Language helps editor to highlight text and provide auto-completion.
* A Language instance helps editor to highlight text and provide auto-completion.
* Implement this interface when you want to add new language support for editor.
* <p>
* <strong>NOTE:</strong> A language must not be single instance.
* One language instance should always serve for only one editor.
* It means that you should not give one language object to other editor instances
* after it has been applied to one editor.
* It means that you should not pass a language object to multiple editor instances.
*
* @author Rosemoe
*/
Expand Down Expand Up @@ -80,7 +79,7 @@ public interface Language {

/**
* Get {@link AnalyzeManager} of the language.
* This is called from time to time by the editor. Cache your instance please.
* The result instance is expected to be the same in language lifecycle.
*/
@NonNull
AnalyzeManager getAnalyzeManager();
Expand All @@ -96,6 +95,7 @@ public interface Language {

/**
* Request to auto-complete the code at the given {@code position}.
* Note that if you did not correctly set the spans for the text, the auto-completion will not be triggered.
* This is called in a worker thread other than UI thread.
*
* @param content Read-only reference of content
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,8 @@ public abstract class AsyncIncrementalAnalyzeManager<S, T> extends BaseAnalyzeMa

private static boolean useShallowCopyByDefault = false;

private static boolean updateStylesDuringAnalysis = true;

/**
* Use shallow copy for initial text copying. Memory usage will be much lower than full copy at the beginning.
* <p>
Expand All @@ -88,6 +90,18 @@ public static boolean isUseShallowCopyByDefault() {
return useShallowCopyByDefault;
}

/**
* Update styles during initial styles analysis. This is useful for long files to show analyzed
* lines quickly, instead of showing the result after initial analysis.
*/
public static void setUpdateStylesDuringAnalysis(boolean sendStylesAsAnalysis) {
AsyncIncrementalAnalyzeManager.updateStylesDuringAnalysis = sendStylesAsAnalysis;
}

public static boolean isUpdateStylesDuringAnalysis() {
return updateStylesDuringAnalysis;
}

public AsyncIncrementalAnalyzeManager() {
this(isUseShallowCopyByDefault());
}
Expand Down Expand Up @@ -487,6 +501,11 @@ private void initialize() {
states.add(result.clearSpans());
onAddState(result.state);
mdf.addLineAt(i, spans);
if (isUpdateStylesDuringAnalysis() && i > 0 && i % 1000 == 0 && !abort) {
var tmpStyles = new Styles();
tmpStyles.spans = styles.spans;
sendNewStyles(tmpStyles);
}
}
styles.blocks = computeBlocks(shadowed, delegate);
styles.setSuppressSwitch(delegate.suppressSwitch);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,8 @@ public void setSuppressSwitch(int suppressSwitch) {
* Adjust styles on insert.
*/
public void adjustOnInsert(@NonNull CharPosition start, @NonNull CharPosition end) {
spans.adjustOnInsert(start, end);
if (spans != null)
spans.adjustOnInsert(start, end);
var delta = end.line - start.line;
if (delta == 0) {
return;
Expand All @@ -157,7 +158,8 @@ public void adjustOnInsert(@NonNull CharPosition start, @NonNull CharPosition en
* Adjust styles on delete.
*/
public void adjustOnDelete(@NonNull CharPosition start, @NonNull CharPosition end) {
spans.adjustOnDelete(start, end);
if (spans != null)
spans.adjustOnDelete(start, end);
var delta = start.line - end.line;
if (delta == 0) {
return;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@

import io.github.rosemoe.sora.annotations.Experimental;
import io.github.rosemoe.sora.annotations.InvalidateRequired;
import io.github.rosemoe.sora.widget.minimap.MinimapConfig;

/**
* Direct-access properties.
Expand Down Expand Up @@ -568,4 +569,19 @@ public class DirectAccessProps implements Serializable {
*/
public boolean selectCompletionItemOnEnterForSoftKbd = true;

/**
* Show minimap for content
*/
@Experimental
@InvalidateRequired
public boolean showMinimap = false;

/**
* Minimap config
*/
@Experimental
@InvalidateRequired
@NonNull
public MinimapConfig minimapConfig = MinimapConfig.Companion.getDefaultConfig();

}
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@
import io.github.rosemoe.sora.util.TemporaryCharBuffer;
import io.github.rosemoe.sora.widget.layout.Row;
import io.github.rosemoe.sora.widget.layout.RowIterator;
import io.github.rosemoe.sora.widget.minimap.MinimapRenderer;
import io.github.rosemoe.sora.widget.rendering.RenderingConstants;
import io.github.rosemoe.sora.widget.rendering.TextAdvancesCache;
import io.github.rosemoe.sora.widget.schemes.EditorColorScheme;
Expand Down Expand Up @@ -144,6 +145,7 @@ public class EditorRenderer {
protected Content content;
private volatile boolean renderingFlag;
protected boolean forcedRecreateLayout;
private final MinimapRenderer minimapRenderer;

public EditorRenderer(@NonNull CodeEditor editor) {
this.editor = editor;
Expand Down Expand Up @@ -172,6 +174,7 @@ public EditorRenderer(@NonNull CodeEditor editor) {
lineBreakGraph = editor.getContext().getDrawable(R.drawable.line_break);
softwrapLeftGraph = editor.getContext().getDrawable(R.drawable.softwrap_left);
softwrapRightGraph = editor.getContext().getDrawable(R.drawable.softwrap_right);
minimapRenderer = new MinimapRenderer(editor);

onEditorFullTextUpdate();
}
Expand Down Expand Up @@ -509,7 +512,7 @@ public void drawView(Canvas canvas) {
canvas.save();
float stuckLineBottom = getStuckLineBottom(stuckLines);
canvas.clipRect(0, stuckLineBottom, editor.getWidth(), editor.getHeight());
drawRows(canvas, textOffset, postDrawLineNumbers, postDrawCursor, postDrawCurrentLines, firstLn);
drawRows(canvas, textOffset, postDrawLineNumbers, postDrawCursor, postDrawCurrentLines, firstLn, stuckLines);
patchHighlightedDelimiters(canvas, textOffset);
drawDiagnosticIndicators(canvas, offsetX);
canvas.restore();
Expand Down Expand Up @@ -629,7 +632,7 @@ public void drawView(Canvas canvas) {
}

drawStuckLineNumbers(canvas, stuckLines, offsetX, lineNumberWidth, editor.getColorScheme().getColor(EditorColorScheme.LINE_NUMBER));
drawScrollBars(canvas);
drawScrollBarsAndMinimap(canvas);
drawEdgeEffect(canvas);

releasePreloadedData();
Expand Down Expand Up @@ -1140,7 +1143,9 @@ public TextRowParams createTextRowParams() {
* @param postDrawLineNumbers Line numbers to be drawn later
* @param postDrawCursor Cursors to be drawn later
*/
protected void drawRows(Canvas canvas, float offset, LongArrayList postDrawLineNumbers, List<DrawCursorTask> postDrawCursor, MutableIntList postDrawCurrentLines, MutableInt requiredFirstLn) {
protected void drawRows(Canvas canvas, float offset, LongArrayList postDrawLineNumbers,
List<DrawCursorTask> postDrawCursor, MutableIntList postDrawCurrentLines,
MutableInt requiredFirstLn, List<CodeBlock> stuckLines) {
int firstVis = editor.getFirstVisibleRow();
RowIterator rowIterator = editor.getLayout().obtainRowIterator(firstVis, preloadedLines);
Spans spans = editor.getStyles() == null ? null : editor.getStyles().spans;
Expand All @@ -1165,7 +1170,7 @@ protected void drawRows(Canvas canvas, float offset, LongArrayList postDrawLineN
circleRadius = Math.min(editor.getRowHeight(), spaceWidth) * RenderingConstants.NON_PRINTABLE_CIRCLE_RADIUS_FACTOR;
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q && !editor.isWordwrap() && canvas.isHardwareAccelerated() && editor.isHardwareAcceleratedDrawAllowed()) {
editor.getRenderContext().getRenderNodeHolder().keepCurrentInDisplay(firstVis, editor.getLastVisibleRow());
editor.getRenderContext().getRenderNodeHolder().keepCurrentInDisplay(firstVis, editor.getLastVisibleRow(), stuckLines);
}
float offset2 = editor.getOffsetX() - editor.measureTextRegionOffset();

Expand Down Expand Up @@ -2041,18 +2046,17 @@ protected void drawSideBlockLine(Canvas canvas) {
*
* @param canvas The canvas to draw
*/
protected void drawScrollBars(Canvas canvas) {
protected void drawScrollBarsAndMinimap(Canvas canvas) {
var minimapWidth = minimapRenderer.onDrawToCanvas(canvas, editor.getWidth(), displayTimestamp);
verticalScrollBarRect.setEmpty();
horizontalScrollBarRect.setEmpty();
if (!editor.getEventHandler().shouldDrawScrollBarForTouch() && !(editor.isInMouseMode() && editor.getProps().mouseModeAlwaysShowScrollbars)) {
return;
}
boolean shouldShowScrollbars = editor.getEventHandler().shouldDrawScrollBarForTouch() || (editor.isInMouseMode() && editor.getProps().mouseModeAlwaysShowScrollbars);
var percentage = editor.getEventHandler().getScrollBarFadeOutPercentageForTouch();
if (editor.isInMouseMode() && editor.getProps().mouseModeAlwaysShowScrollbars) {
if (shouldShowScrollbars && editor.isInMouseMode() && editor.getProps().mouseModeAlwaysShowScrollbars) {
percentage = 0f;
}
var size = editor.getDpUnit() * RenderingConstants.SCROLLBAR_WIDTH_DIP;
if (editor.isHorizontalScrollBarEnabled() && !editor.isWordwrap() && editor.getScrollMaxX() > editor.getWidth() * 3 / 4) {
if (shouldShowScrollbars && editor.isHorizontalScrollBarEnabled() && !editor.isWordwrap() && editor.getScrollMaxX() > editor.getWidth() * 3 / 4) {
canvas.save();
canvas.translate(0f, size * percentage);

Expand All @@ -2061,7 +2065,8 @@ protected void drawScrollBars(Canvas canvas) {

canvas.restore();
}
if (editor.isVerticalScrollBarEnabled() && editor.getScrollMaxY() > editor.getHeight() / 2) {
boolean shouldShowVerticalScrollbar = shouldShowScrollbars && !editor.getProps().showMinimap;
if (shouldShowVerticalScrollbar && editor.isVerticalScrollBarEnabled() && editor.getScrollMaxY() > editor.getHeight() / 2) {
canvas.save();
canvas.translate(size * percentage, 0f);

Expand All @@ -2070,6 +2075,14 @@ protected void drawScrollBars(Canvas canvas) {

canvas.restore();
}

if (minimapWidth != 0) {
getVerticalScrollBarRect(tmpRect, minimapWidth);
verticalScrollBarRect.set(tmpRect);
if (editor.getEventHandler().holdVerticalScrollBar()) {
drawLineInfoPanel(canvas, tmpRect.top, tmpRect.height(), minimapWidth + 5 * editor.getDpUnit());
}
}
}

/**
Expand All @@ -2092,27 +2105,33 @@ protected void drawScrollBarTrackVertical(Canvas canvas) {
}
}

private void getVerticalScrollBarRect(RectF rect, float width) {
int height = editor.getHeight();
float all = editor.getScrollMaxY() + height;
float length = Math.max(height / all * height, editor.getDpUnit() * RenderingConstants.SCROLLBAR_LENGTH_MIN_DIP);
float topY = editor.getOffsetY() * 1.0f / editor.getScrollMaxY() * (height - length);
rect.right = editor.getWidth();
rect.left = editor.getWidth() - width;
rect.top = topY;
rect.bottom = topY + length;
}

/**
* Draw vertical scroll bar
*
* @param canvas Canvas to draw
*/
protected void drawScrollBarVertical(Canvas canvas) {
int height = editor.getHeight();
float all = editor.getScrollMaxY() + height;
float length = Math.max(height / all * height, editor.getDpUnit() * RenderingConstants.SCROLLBAR_LENGTH_MIN_DIP);
float topY = editor.getOffsetY() * 1.0f / editor.getScrollMaxY() * (height - length);
getVerticalScrollBarRect(tmpRect, editor.getDpUnit() * RenderingConstants.SCROLLBAR_WIDTH_DIP);
verticalScrollBarRect.set(tmpRect);
if (editor.getEventHandler().holdVerticalScrollBar()) {
drawLineInfoPanel(canvas, topY, length);
drawLineInfoPanel(canvas, tmpRect.top, tmpRect.height(), 30 * editor.getDpUnit());
}
tmpRect.right = editor.getWidth();
tmpRect.left = editor.getWidth() - editor.getDpUnit() * RenderingConstants.SCROLLBAR_WIDTH_DIP;
tmpRect.top = topY;
tmpRect.bottom = topY + length;
verticalScrollBarRect.set(tmpRect);
if (verticalScrollbarThumbDrawable != null) {
verticalScrollbarThumbDrawable.setState(editor.getEventHandler().holdVerticalScrollBar() ? PRESSED_DRAWABLE_STATE : DEFAULT_DRAWABLE_STATE);
verticalScrollbarThumbDrawable.setBounds((int) tmpRect.left, (int) tmpRect.top, (int) tmpRect.right, (int) tmpRect.bottom);
verticalScrollbarThumbDrawable.setBounds((int) verticalScrollBarRect.left,
(int) verticalScrollBarRect.top, (int) verticalScrollBarRect.right,
(int) verticalScrollBarRect.bottom);
verticalScrollbarThumbDrawable.draw(canvas);
} else {
drawColor(canvas, editor.getColorScheme().getColor(editor.getEventHandler().holdVerticalScrollBar() ? EditorColorScheme.SCROLL_BAR_THUMB_PRESSED : EditorColorScheme.SCROLL_BAR_THUMB), tmpRect);
Expand All @@ -2126,7 +2145,7 @@ protected void drawScrollBarVertical(Canvas canvas) {
* @param topY The y at the top of the vertical scrollbar
* @param length The length of vertical scrollbar
*/
protected void drawLineInfoPanel(Canvas canvas, float topY, float length) {
protected void drawLineInfoPanel(Canvas canvas, float topY, float length, float rightMargin) {
if (!editor.isDisplayLnPanel()) {
return;
}
Expand Down Expand Up @@ -2173,8 +2192,8 @@ protected void drawLineInfoPanel(Canvas canvas, float topY, float length) {
drawColorRound(canvas, editor.getColorScheme().getColor(EditorColorScheme.LINE_NUMBER_PANEL), tmpRect);
} else {
float[] radii = null;
tmpRect.right = editor.getWidth() - 30 * editor.getDpUnit();
tmpRect.left = editor.getWidth() - 30 * editor.getDpUnit() - expand * 2 - textWidth;
tmpRect.right = editor.getWidth() - rightMargin;
tmpRect.left = tmpRect.right - expand * 2 - textWidth;
if (position == LineInfoPanelPosition.TOP) {
tmpRect.top = topY;
tmpRect.bottom = topY + editor.getRowHeight() + 2 * expand;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ public class EditorSearcher {
*/
protected LongArrayList lastResults;
private boolean cyclicJumping = true;
private boolean ensureOccurrenceVisible = false;

EditorSearcher(@NonNull CodeEditor editor) {
this.editor = editor;
Expand Down Expand Up @@ -104,6 +105,23 @@ public boolean isCyclicJumping() {
return cyclicJumping;
}

/**
* Set whether the editor should automatically scroll to the nearest occurrence
* when executing a search.
*
* @see #isEnsureOccurrenceVisible()
*/
public void setEnsureOccurrenceVisible(boolean ensureOccurrenceVisible) {
this.ensureOccurrenceVisible = ensureOccurrenceVisible;
}

/**
* @see #setEnsureOccurrenceVisible(boolean)
*/
public boolean isEnsureOccurrenceVisible() {
return ensureOccurrenceVisible;
}

/**
* Set the options when replacing text
*/
Expand Down Expand Up @@ -611,6 +629,19 @@ public void run() {
editor.invalidate();
editor.dispatchEvent(new PublishSearchResultEvent(editor));
currentThread = null;
if (ensureOccurrenceVisible && results.size() > 0) {
var right = editor.getCursor().getRight();
var index = results.lowerBoundByFirst(right);

if (index >= results.size()) {
index = results.size() - 1;
}

var match = results.get(index);
var start = IntPair.getFirst(match);
var startPos = editor.getText().getIndexer().getCharPosition(start);
editor.ensurePositionVisible(startPos.line, startPos.column);
}
}
});
}
Expand Down
Loading
Loading