From df74c35e3e4bf578294a308816d51f88dba8e8aa Mon Sep 17 00:00:00 2001 From: Akash Yadav Date: Sat, 1 Apr 2023 18:31:38 +0530 Subject: [PATCH] feat(editor): add file and workspace based snippet variable resolvers --- .../AbstractSnippetVariableResolver.kt | 30 +++++++++ .../editor/snippets/FileVariableResolver.kt | 61 +++++++++++++++++++ .../snippets/WorkspaceVariableResolver.kt | 48 +++++++++++++++ .../androidide/editor/ui/IDEEditor.java | 23 ++++++- 4 files changed, 160 insertions(+), 2 deletions(-) create mode 100644 editor/src/main/java/com/itsaky/androidide/editor/snippets/AbstractSnippetVariableResolver.kt create mode 100644 editor/src/main/java/com/itsaky/androidide/editor/snippets/FileVariableResolver.kt create mode 100644 editor/src/main/java/com/itsaky/androidide/editor/snippets/WorkspaceVariableResolver.kt diff --git a/editor/src/main/java/com/itsaky/androidide/editor/snippets/AbstractSnippetVariableResolver.kt b/editor/src/main/java/com/itsaky/androidide/editor/snippets/AbstractSnippetVariableResolver.kt new file mode 100644 index 000000000..391d252bc --- /dev/null +++ b/editor/src/main/java/com/itsaky/androidide/editor/snippets/AbstractSnippetVariableResolver.kt @@ -0,0 +1,30 @@ +/* + * This file is part of AndroidIDE. + * + * AndroidIDE is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * AndroidIDE is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with AndroidIDE. If not, see . + */ + +package com.itsaky.androidide.editor.snippets + +import io.github.rosemoe.sora.widget.snippet.variable.ISnippetVariableResolver + +/** + * Base class for snippet variable resolvers. + * + * @author Akash Yadav + */ +interface AbstractSnippetVariableResolver : ISnippetVariableResolver, AutoCloseable { + override fun close() { + } +} diff --git a/editor/src/main/java/com/itsaky/androidide/editor/snippets/FileVariableResolver.kt b/editor/src/main/java/com/itsaky/androidide/editor/snippets/FileVariableResolver.kt new file mode 100644 index 000000000..b70dee2f8 --- /dev/null +++ b/editor/src/main/java/com/itsaky/androidide/editor/snippets/FileVariableResolver.kt @@ -0,0 +1,61 @@ +/* + * This file is part of AndroidIDE. + * + * AndroidIDE is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * AndroidIDE is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with AndroidIDE. If not, see . + */ + +package com.itsaky.androidide.editor.snippets + +import com.itsaky.androidide.editor.ui.IDEEditor +import com.itsaky.androidide.projects.ProjectManager +import io.github.rosemoe.sora.widget.snippet.variable.FileBasedSnippetVariableResolver + +/** + * Resolver for resolving snippet variables related to the file opened in an editor. + * + * @author Akash Yadav + */ +class FileVariableResolver(editor: IDEEditor) : FileBasedSnippetVariableResolver(), AbstractSnippetVariableResolver { + + var editor: IDEEditor? = editor + private set + + companion object { + private const val TM_FILENAME = "TM_FILENAME" + private const val TM_FILENAME_BASE = "TM_FILENAME_BASE" + private const val TM_DIRECTORY = "TM_DIRECTORY" + private const val TM_FILEPATH = "TM_FILEPATH" + private const val RELATIVE_FILEPATH = "RELATIVE_FILEPATH" + } + + override fun resolve(name: String): String { + val file = editor?.file ?: return "" + return when (name) { + TM_FILENAME -> file.name + TM_FILENAME_BASE -> file.nameWithoutExtension + TM_DIRECTORY -> file.parentFile?.absolutePath ?: "" + TM_FILEPATH -> file.absolutePath + RELATIVE_FILEPATH -> file.relativeTo(ProjectManager.getProjectDir()).absolutePath + else -> "" + } + } + + override fun getResolvableNames(): Array { + return arrayOf(TM_FILENAME, TM_FILENAME_BASE, TM_DIRECTORY, TM_FILEPATH, RELATIVE_FILEPATH) + } + + override fun close() { + editor = null + } +} diff --git a/editor/src/main/java/com/itsaky/androidide/editor/snippets/WorkspaceVariableResolver.kt b/editor/src/main/java/com/itsaky/androidide/editor/snippets/WorkspaceVariableResolver.kt new file mode 100644 index 000000000..9b18d37d4 --- /dev/null +++ b/editor/src/main/java/com/itsaky/androidide/editor/snippets/WorkspaceVariableResolver.kt @@ -0,0 +1,48 @@ +/* + * This file is part of AndroidIDE. + * + * AndroidIDE is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * AndroidIDE is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with AndroidIDE. If not, see . + */ + +package com.itsaky.androidide.editor.snippets + +import com.itsaky.androidide.projects.ProjectManager +import io.github.rosemoe.sora.widget.snippet.variable.WorkspaceBasedSnippetVariableResolver + +/** + * Resolver for resolving snippet variables related to the opened workspace folder (project). + * + * @author Akash Yadav + */ +class WorkspaceVariableResolver : + WorkspaceBasedSnippetVariableResolver(), AbstractSnippetVariableResolver { + + companion object { + private const val WORKSPACE_NAME = "WORKSPACE_NAME" + private const val WORKSPACE_FOLDER = "WORKSPACE_FOLDER" + } + + override fun resolve(name: String): String { + val directory = ProjectManager.getProjectDir() + return when (name) { + WORKSPACE_NAME -> directory.name + WORKSPACE_FOLDER -> directory.absolutePath + else -> "" + } + } + + override fun getResolvableNames(): Array { + return arrayOf(WORKSPACE_NAME, WORKSPACE_FOLDER) + } +} diff --git a/editor/src/main/java/com/itsaky/androidide/editor/ui/IDEEditor.java b/editor/src/main/java/com/itsaky/androidide/editor/ui/IDEEditor.java index d21c68292..7da326db0 100644 --- a/editor/src/main/java/com/itsaky/androidide/editor/ui/IDEEditor.java +++ b/editor/src/main/java/com/itsaky/androidide/editor/ui/IDEEditor.java @@ -46,6 +46,9 @@ import com.itsaky.androidide.editor.language.treesitter.TreeSitterLanguage; import com.itsaky.androidide.editor.language.treesitter.TreeSitterLanguageProvider; import com.itsaky.androidide.editor.schemes.IDEColorScheme; import com.itsaky.androidide.editor.schemes.IDEColorSchemeProvider; +import com.itsaky.androidide.editor.snippets.AbstractSnippetVariableResolver; +import com.itsaky.androidide.editor.snippets.FileVariableResolver; +import com.itsaky.androidide.editor.snippets.WorkspaceVariableResolver; import com.itsaky.androidide.eventbus.events.editor.ChangeType; import com.itsaky.androidide.eventbus.events.editor.ColorSchemeInvalidatedEvent; import com.itsaky.androidide.eventbus.events.editor.DocumentChangeEvent; @@ -80,6 +83,7 @@ import io.github.rosemoe.sora.widget.CodeEditor; import io.github.rosemoe.sora.widget.IDEEditorSearcher; import io.github.rosemoe.sora.widget.component.EditorAutoCompletion; import io.github.rosemoe.sora.widget.component.EditorTextActionWindow; +import io.github.rosemoe.sora.widget.snippet.variable.ISnippetVariableResolver; import java.io.File; import java.util.concurrent.CompletableFuture; import kotlin.io.FilesKt; @@ -426,6 +430,8 @@ public class IDEEditor extends CodeEditor implements IEditor, ILspEditor { if (server != null) { this.languageClient = server.getClient(); + getSnippetController().setFileVariableResolver(new FileVariableResolver(this)); + getSnippetController().setWorkspaceVariableResolver(new WorkspaceVariableResolver()); } } @@ -755,8 +761,8 @@ public class IDEEditor extends CodeEditor implements IEditor, ILspEditor { new Position(end.line, end.column, end.index)); final var changedText = event.getChangedText().toString(); - final var changeEvent = new DocumentChangeEvent(file, changedText, getText().toString(), ++fileVersion, type, - changeDelta, changeRange); + final var changeEvent = new DocumentChangeEvent(file, changedText, getText().toString(), + ++fileVersion, type, changeDelta, changeRange); // Notify FileManager first FileManager.INSTANCE.onDocumentContentChange(changeEvent); @@ -819,6 +825,19 @@ public class IDEEditor extends CodeEditor implements IEditor, ILspEditor { public void release() { ensureWindowsDismissed(); super.release(); + ISnippetVariableResolver resolver = getSnippetController().getFileVariableResolver(); + if (resolver instanceof AbstractSnippetVariableResolver) { + ((AbstractSnippetVariableResolver) resolver).close(); + } + + resolver = getSnippetController().getWorkspaceVariableResolver(); + if (resolver instanceof AbstractSnippetVariableResolver) { + ((AbstractSnippetVariableResolver) resolver).close(); + } + + getSnippetController().setFileVariableResolver(null); + getSnippetController().setWorkspaceVariableResolver(null); + if (this.actionsMenu != null) { this.actionsMenu.destroy(); }