Community생산성 & 협업github.com

boboyr/TiecodePluginSkills

结绳(Tiecode/结绳 IDE)插件开发完整指南。涵盖插件 API、扩展点、打包、以及各种功能的实现方式。适用于开发、修改、学习或排查结绳插件、.rmx 插件、Tiecode 插件等。

TiecodePluginSkills란 무엇인가요?

이 스킬은 '结绳 IDE (QiStudio, Tiecode)'를 위한 플러그인 개발 완벽 가이드를 제공합니다. 안드로이드 기반 IDE에서 플러그인(.rmx 파일)을 개발하는 데 필요한 모든 핵심 개념과 실전 구현 방법을 다룹니다. 주요 내용으로는 plugin API(com.rapid.api.*), program.json 확장 포인트 시스템, TextMate + LanguageEngine + LSP를 활용한 코드 완성, 파일 트리 커스터마이징(PSObject/ExpansionCase/CreationOption/OpeningOption), 실행 구성(RunConfiguration/TaskRunConfiguration), 프로젝트 템플릿(BaseTemplate), 빌드 태스크(BaseTask/ToolchainService), 도구 체인, 언어 하이라이팅, 메뉴, 설정 페이지 등이 포함됩니다. 이 스킬은 실제 여러 플러그인(Go, Scala, Kotlin, Linux, AAR 등)의 소스 코드를 역컴파일하여 분석한 내용을 바탕으로 하며, Gitee의 공식 저장소와 GitHub의 커뮤니티 예제를 참조합니다. 개발자, IDE 확장 개발자, 고급 사용자 모두가 QiStudio 생태계에서 자신만의 플러그인을 만들거나 기존 플러그인을 학습 및 디버깅하는 데 유용합니다.

지원 대상~Claude Code~Codex CLI✓Cursor
npx skills add boboyr/TiecodePluginSkills

Installed? Explore more 생산성 & 협업 skills: steipete/gemini, steipete/gh-issues, steipete/skill-creator · View all 6 →

즐겨 사용하는 AI에게 물어보기

이 에이전트 스킬이 미리 로드된 새 채팅을 엽니다.

문서

结绳插件开发

「结绳 IDE / QiStudio」(호스트 패키지명 com.tiecode.develop)를 위한 플러그인 개발 문서입니다. 「结绳 Studio」의 공식 명칭은 QiStudio(차세대 개방형 엔지니어링 플랫폼, 모바일 최초 OSGi 표준 구현 앱, 「마이크로 컴포넌트/플러그인」 형태로 엔지니어링 개발 환경 확장)입니다. 내용 출처: studio-api-1.0-preview5.jar(com.rapid.api.*)역컴파일 + go / scala / kotlin / linux / aar / libgdx / 설치 없이 실행 등 10여 개 실제 플러그인의 소스 코드 복원.


공식 자료 및 저장소(중요)

공식 Gitee 저장소

저장소설명
MobileIPE-Plugin-DevManual공식 플러그인 개발 튜토리얼(QiStudio 마이크로 컴포넌트). QiStudio核心体系介绍.md, Rapid框架介绍.md, plugin/扩展点介绍.md, plugin/插件清单配置.md, plugin/注册你的微组件——插件.md 포함
TiecodeCompiler-Public结绳 컴파일러(크로스 플랫폼 버전)산출물 배포 저장소. docs/(컴파일러 사용/문법/패키징/플랫폼 통합 문서), headers/tiec/(C API + C++ 패키징 헤더 파일), prebuilt/(cli + android/windows/linux/ohos/wasm 동적 라이브러리), stdlibs/(안드로이드/CXX/웹 기본 라이브러리) 포함
QiStudio-PluginSamples공식 플러그인 샘플 프로젝트 모음(19+개 예제: 의존성 주입, 편집기 효과/레인보우 브래킷, 플로팅 로그, Html 프로젝트 관리자, 네트워크 요청, 아이콘 확장, Javac9 도구 체인, 언어 하이라이팅, 사용자 정의 테마, Application 생명주기, 프로젝트 컴포넌트, 각종 메뉴, 도구 페이지, 설정 페이지 등)

공식 API jar 파일명은 qistudio-api-<버전>.jar입니다(이 스킬에서 역컴파일한 studio-api-1.0-preview5.jar는 호스트 측 SDK입니다). QQ 교류 그룹: 1016399857.

커뮤니티 참고 구현(GitHub)

이 스킬과 함께 제공되는 실제 플러그인 소스 코드 모음(단일 저장소, 여러 디렉토리, 8개의 완전 컴파일 가능 플러그인 포함):

https://github.com/boboyr/tiecode-plugin

디렉토리플러그인시연 기능
go语言工程插件/go 언어 엔지니어링(콘솔+SDL3)이중 템플릿 + LSP(gopls) 자동 완성 + TextMate 하이라이팅 + 도구 체인 + 실행 구성 + 파일 트리 가상 노드
结绳安卓工程aar构建插件/aar/jar 빌드호스트 컴파일 체인 재사용 + NameGenerator 한글 출력
结绳免安装运行插件/설치 없이 실행기호스트 태스크 재사용 + 플러그인 방식으로 미설치 APK 로딩
libgdx游戏编辑器插件/libgdx 비주얼 에디터디자이너 + 편집기 코드 영역 메뉴 + 새 장면 클래스
scala安卓工程插件/Scala 안드로이드 엔지니어링완전한 sbt 빌드 체인 + 「结绳 플러그인 프로젝트」 템플릿 + 빌드/디버그 플러그인
结绳Linux工程插件/结绳 Linux-SDL3GCC 도구 체인 + SDL3 + 태스크 체인
外部kotlin文件注解插件/외부 Kotlin 파일 어노테이션结绳 컴파일러 API: CompilerPlugin + AnnotationProcessor + Kotlin 자동 완성
BasicLanguages-lang参考/공식 기본 언어csml/json/markdown/xml/properties 언어 하이라이팅 참고

0. 핵심 개념 및 전체 아키텍처

结绳은 모듈식 IDE 호스트이며, 플러그인은 .rmx 파일로 배포됩니다. 하나의 .rmx는 본질적으로 APK입니다: AndroidManifest.xml + classes.dex + META-INF/program.json. 호스트는 manifest의 <application> 또는 4대 컴포넌트가 아닌, program.json의 확장 포인트(extension point) 선언을 통해 플러그인 기능을 발견합니다.

0.1 세 가지 핵심 패키지

패키지역할
com.rapid.api.*플러그인 SDK(本次文档主体). 프로젝트, 언어, 태스크, 구조, 페이지, UI, 네트워크 등
com.rapid.framework.*프레임워크 계층: VFS(가상 파일 시스템), Service/Data/Event Keys, program/plugin 컨테이너
com.tiecode.compiler.*结绳 컴파일러(구문 트리 / 심볼 테이블 / 도구 체인 completer/processor)——호스트 측, 플러그인은 일반적으로 toolchain 하위 패키지만 사용

0.2 확장 포인트(program.json의 extension 배열)

META-INF/program.json의 전체 구조:

{
  "id": "com.goproject.plugin",
  "name": "go语言工程插件",
  "engine": "plugin",
  "description": "...",
  "versionCode": 4,
  "versionName": "1.3",
  "minSupport": 1,
  "vendor": { "name": "boboyr", "email": "", "url": "#" },
  "extension": [
    { "point": "application", "class": "com.goproject.plugin.MyApplication" },
    { "point": "project.manager", "class": "com.goproject.plugin.project.GoProjectManager" },
    { "point": "project.language", "class": "com.goproject.plugin.lang.GoLanguageFactory",
      "scope": { "unit": "project", "identifiers": "sample.go" } },
    { "point": "domain.menu", "class": "com.goproject.plugin.Gomodmenu" }
  ]
}

minSupport 필드 설명(호스트 최소 지원 버전)

minSupport는 정수로, 플러그인이 요구하는 호스트 结绳의 최소 버전을 나타냅니다. 버전에 따라 값이 다릅니다:

结绳 버전minSupport설명
结绳 4.614.6 플러그인은 "minSupport": 1로 작성
结绳 4.724.7 플러그인은 "minSupport": 2로 작성

즉, 4.6용 플러그인 개발 시 minSupport는 1을 입력하고, 4.7로 업그레이드하거나 4.7 대상 플러그인은 2를 입력합니다. 값과 호스트 버전 간의 구체적인 바인딩 규칙은 공식 기준을 따르며, 개발 시 대상 호스트 버전에 맞춰 작성하면 됩니다.

확인된 확장 포인트全集(point 필드):

확장 포인트클래스 구현/상속역할출처 플러그인
applicationAndroidPlugin플러그인 진입점, onInit/activate/onUninstallgo/scala/aar/설치 없음
project.managerProjectManager(주로 CodeProjectManager 사용)프로젝트 유형 등록go/scala/linux
project.languageLanguageFactory언어 등록(하이라이팅 + 연관 파일 확장자), scope 가능go/scala
project.language.engineLanguageEngine언어 엔진 등록(자동 완성/진단 등 provider 컨테이너)结绳 콘솔 플러그인
project.toolchainTool 하위 클래스(예: SunJdk8Compiler)컴파일 도구 체인 등록JavaCompiler8
project.componentComponentIntegrator/ComponentFactory프로젝트 열 때 컴포넌트 마운트(실행 구성/최초 팝업/hook)linux/kotlin/aar/설치 없음
project.file.creationOptionPSObjectCreationOption파일 트리 「새 파일」 메뉴 항목kotlin/libgdx
project.file.openWithEditorPSObjectOpeningOption파일 「열기 방식」kotlin
project.event.fileUiProjectFileUiEvent파일 트리 UI 이벤트(아이콘 바인딩 등)kotlin
domain.menuBaseDomainMenuAction/메뉴 action최상위 메뉴 항목go
domain.menu.editor.code편집기 코드 영역 메뉴libgdx
platform.settingsBuilderSettingsBuilder설정 페이지에 하위 페이지 추가scala 안드로이드
project.file.creationOption———

참고: scope.identifiers는 언어/컴포넌트를 특정 프로젝트 typeId(예: sample.go)로 제한하는 데 사용됩니다. 일부 확장 포인트의 class는 None(플레이스홀더)일 수 있습니다.


1. 플러그인 진입점: application 확장 포인트

import com.rapid.framework.program.android.app.AndroidPlugin;
import com.rapid.framework.program.android.DvmPluginDescriptor;
import com.rapid.api.Platform;
import com.rapid.api.framework.project.toolchain.ToolchainService;
import com.rapid.api.framework.project.ProjectServiceKeys;

public class MyApplication extends AndroidPlugin {
    @Override
    public void onInit(DvmPluginDescriptor descriptor) {
        // 사용자 정의 컴파일 도구 체인 등록(예: go 컴파일러)
        ToolchainService service = Platform.getService(ProjectServiceKeys.TOOLCHAIN);
        service.setTool(GoCompileApiKeys.Gocompile, new BaseGoCompiler());
    }
    @Override
    public void activate() {
        // 플러그인이 활성화될 때 한 번 실행(주로 hook, 리스너, 컴파일 플러그인 장착)
    }
    @Override
    public void onUninstall() {
        // 제거 정리: 자신이 실행한 하위 프로세스 종료(예: gopls), LSP 연결 해제
    }
}

핵심 API(com.rapid.api.Platform):

  • Platform.getService(Key<T>) —— 호스트 서비스 가져오기(예: ProjectServiceKeys.TOOLCHAIN)
  • Platform.getProject() —— 현재 열려 있는 프로젝트 객체
  • Platform.getApplicationContext() —— 호스트 Context

2. 프로젝트 유형: project.manager 확장 포인트

플러그인은 ProjectManager를 통해 하나의 「프로젝트 유형」(예: go语言工程, 结绳安卓工程)을 등록합니다.

2.1 관리자 뼈대

public class GoProjectManager extends CodeProjectManager<GoProject> {
    public final static String TYPE = "go语言工程";       // 표시 이름
    public final static String IDENTIFIER = "sample.go"; // typeId, project.json에 저장됨

    public GoProjectManager() {
        super();
        this.fileManager = new GoFileManager();   // 선택 사항: 사용자 정의 파일 관리자(아이콘 바인딩 등)

        // ① 파일 열기 방식(확장자별)
        fileManager.addPSObjectOpeningOption(DefaultOpeningOption.INSTANCE, ".go", ".mod");
        // ② 파일 트리 노드 확장 방식(가상 「외부 라이브러리」 노드)
        fileManager.addPSObjectExpansionCase(new ExternalLibrariesExpansionCase(), MARKER);
        // ③ 새 파일 메뉴 항목
        fileManager.addPSObjectCreationOption(new GoFileCreationOption());
        // ④ 언어 엔진 및 언어 팩토리
        languageManager.registerEngine("go", GoLanguageEngine.getInstance());
        languageManager.registerLanguageFactory(new GoLanguageFactory());
        languageManager.registerOperatorProvider(GoLanguage.ID, new GoOperatorProvider());
        // ⑤ 프로젝트 생성 템플릿
        addTemplate(new GoConsoleTemplate());
        addTemplate(new GoSdl3Template());
    }

    @Override public String getIdentifier() { return IDENTIFIER; }

    @Override public TypeDescription getTypeDescription() {
        Drawable d = ContextUtils.getDrawable(AndroidPlugins.getContext(this), R.drawable.golang);
        return new TypeDescription(TYPE, TypeDescription.APPLICATION, d);
    }

    @Override public GoProject newProject() { return new GoProject(); }

    @Override public boolean isProjectDir(File file) { return false; }
}

ProjectManager 인터페이스 메서드(javap 출처):

String getIdentifier();
TypeDescription getTypeDescription();      // 이름 + 유형 + 아이콘
List<Template<T>> getTemplates();
void addTemplate(Template<T>);
ProjectFileManager<T> getFileManager();
T newProject();
void load(T, LoadingPresentation);
boolean isProjectDir(File);                // 특정 디렉토리가 해당 유형의 프로젝트인지 판단
String backup(T); void delete(T);

TypeDescription의 유형 상수: APPLICATION / CONSOLE / LIBRARY.


3. 프로젝트 객체 및 파이프라인 조립: CodeProject.prepare()

프로젝트 유형은 Project 하위 클래스에 해당합니다. prepare()는 프로젝트를 열 때 호스트에 의해 호출되며, 이 시점에 템플릿 파일이 이미 생성되어 있으므로 디렉토리 내용을 기반으로 태스크 체인, 실행 구성, 컴포넌트를 조립할 수 있습니다.

public class GoProject extends CodeProject {
    @Override
    public void prepare() {
        if (GoProjectKind.isSdl3(getProjectDir())) {
            Task buildLibmain = new BuildLibmainTask();
            Task publishLib = new PublishLibTask();
            addTask(buildLibmain);
            addTask(publishLib);
            publishLib.dependsOn(buildLibmain);      // 태스크 의존성
            addRunConfiguration(new GoSdl3RunConfiguration());
        } else {
            addTask(new CompilerGoTask());
            addTask(new RunGoTask());
            addRunConfiguration(new GoStartRunConfig());
            addRunConfiguration(new ElfRunConfig());
        }
    }
    @Override public ProjectVariant getVariant() { return ProjectVariant.DEBUG; }
}

CodeProject(BaseProject 확장)핵심 메서드:

void prepare();
TaskContainer getTasks();  TaskExecutor getTaskExecutor();
void addTask(Task);  void setTasks(Iterable<Task>);
void addRunConfiguration(RunConfiguration);   // CodeProject 고유
ProjectVariant getVariant();  void setVariant(ProjectVariant);
Logger getLogger();  void setLogger(Logger);
String getName();
File getProjectDir();  File getChildFile(String);   // 프로젝트 상대 경로를 File로 변환
void recycle();

ProjectVariant 값: DEBUG / RELEASE / UNDEFINED.

팁(go 플러그인 출처): prepare()에서 프로젝트에 마커 파일(예: External Libraries)을 추가로 작성하면, 이미 존재하는 기존 프로젝트에 한 번에 기능을 추가할 수 있어 프로젝트를 다시 생성할 필요가 없습니다.


4. 프로젝트 템플릿: BaseTemplate

템플릿은 「새 프로젝트」 대화상자에서 어떤 옵션을 선택할 수 있는지, 생성 시 어떤 파일을 작성할지 결정합니다.

public class GoConsoleTemplate extends BaseTemplate<GoProject> {
    @Override public String getName() { return "콘솔 프로젝트"; }
    @Override public Drawable getPicture() { return null; }        // 템플릿 미리보기 이미지, null 가능
    @Override public String getDefaultProjectName() { return "내 go 콘솔 프로젝트"; }
    @Override public Form getForm() { return new Form(); }         // 입력 항목 추가 가능

    @Override public void create(GoProject project, Form form,
                                 Project.OnProjectCreateListener listener) {
        try {
            File file = project.getChildFile("src/main.go");
            String html = AssetUtils.readAsset(AndroidPlugins.getContext(this), "sample/main.go");
            html = html.replace("${project_name}", project.getName());
            FileUtils.writeFile(html, file);                        // 프로젝트 디렉토리에 쓰기
            FileUtils.writeFile("module main\ngo 1.26.0", project.getChildFile("src/go.mod"));
            listener.onSuccess();                                    // 성공 콜백
        } catch (IOException e) {
            listener.onFail("기본 파일 쓰기 실패");                      // 실패 콜백
        }
    }
}

Template<T> 인터페이스 메서드:

String getName();
Drawable getPicture();
String getDefaultProjectName();
Form getForm();          // com.rapid.framework.data.form.Form, addInput(new FormInput(...)) 가능
void create(T, Form, OnProjectCreateListener);   // OnProjectCreateListener.onSuccess()/onFail(msg)

템플릿 리소스 포함: 템플릿 파일을 app/src/main/assets/<name>에 넣고, AssetUtils.readAsset / AssetUtils.unZipAssetsFolder(context, zipName, destDir)을 사용하여 읽고 압축을 풉니다. (SDL3 프로젝트 템플릿은 asset의 gosdl3_template.zip 전체를 프로젝트 디렉토리에 압축 해제하는 방식 사용)


5. 컴파일 태스크 및 도구 체인: BaseTask + ToolchainService

5.1 태스크 BaseTask

public class CompilerGoTask extends BaseTask {
    @Override public void execute() throws TaskInterruptError {
        File output = new File(Platform.getProject().getProjectDir() + "/output");
        if (!output.exists()) output.mkdirs();
        GoCompile a = Platform.getService(ProjectServiceKeys.TOOLCHAIN)
                             .getTool(GoCompileApiKeys.Gocompile);
        if (!a.isInstalled(ctx)) { logger.info("도구 체인 설치 중..."); a.install(ctx); }
        GoCompileParams p = new GoCompileParams();
        p.inputFiles = FileUtils.getGofile(srcDir);
        p.outputPath = output.getPath();
        p.options = new String[]{"build", "-o"};
        a.compile(p, new CompileOnExecutionCallback());
    }

    // 반드시 재정의: 기본 BaseTask.prepare는 UnsupportedOperationException을 던짐;
    // 또한 logger/variant 필드를 여기서 할당하지 않으면 execute()에서 logger.info 호출 시 NPE 발생.
    @Override public void prepare(Project project, ProjectVariant variant, Logger logger) {
        this.logger = logger;
        this.variant = variant;
        Os.setenv("GOROOT", goRoot, false);   // 환경 변수 설정(android.system.Os)
    }

    @Override public String getId() { return "compileWithGo"; }   // 실행 구성 getTaskId()에서 참조 용도
    @Override public String getName() { return "대상 플랫폼으로 컴파일"; }
}

Task 인터페이스(javap 출처):

String getId();  String getName();
void prepare(Project, ProjectVariant, Logger);      // 기본 예외 발생하므로 반드시 재정의
void execute() throws TaskInterruptError;
TaskState getState();
void interrupt();
void dependsOn(Task...);  void dependsOn(List<Task>);
Task getDependencyTask(String);  Task getDependencyTaskByName(String);
String getIntermediatePath();  String getIntermediatePath(String);
String getOutputPath();  String getOutputPath(String);
File getGeneratedDir();

주의사항 (go 플러그인 주석 원문): 태스크에서 logger를 할당하지 않으면, execute()에서 logger.info 사용 시 NPE로 직접 실패하여 도구 체인 설치가 절대 실행되지 않습니다.

5.2 도구 체인 Tool + Installable

public interface Tool { /* ANDROID_SDK/AAPT/AAPT2/D8/R8/DX/PROGUARD/
                         MANIFEST_MERGER/APK_SIGNER/JAVA_SDK/JAVA_COMPILER 등 Key 내장 */ }
public interface Installable {
    boolean isInstalled(Context);
    void install(Context) throws IOException;
}
  • 사용자 정의 도구 체인은 application.onInit()에서 ToolchainService.setTool(customKey, impl)로 등록합니다.
  • 내장 Android 도구 체인 Key는 모두 Tool 인터페이스에 있습니다(직접 Platform.getService(TOOLCHAIN).getTool(Tool.AAPT2) 등으로 사용 가능).
  • 호스트 컴파일 체인 재사용(aar 플러그인 / 설치 없이 실행 플러그인 방식): 자체 컴파일러를 패키징하지 않고, getDependencyTaskByName("compileWithTiecodec") 등으로 호스트 태스크를 가져와 의존성을 걸거나, getTaskId()를 직접 재사용합니다.

6. 실행 구성: RunConfiguration / TaskRunConfiguration

프로젝트의 「실행」 메뉴에 실행 가능한 항목을 추가합니다. 가장 일반적인 것은 TaskRunConfiguration: 태스크 id를 지정하고, 태스크 실행 성공 시 onResult 콜백을 호출합니다.

public class GoStartRunConfig extends TaskRunConfiguration {
    public Project getProject() { return Platform.getProject(); }
    public String getTaskId() { return "RunWithGo"; }          // 연결된 태스크 id
    public ProjectVariant getVariant() { return ProjectVariant.DEBUG; }
    public Icon getIcon() { return GoIcons.RUN; }
    public String getDisplayName() { return "Go 프로그램 실행"; }

    @Override
    public void result(RunConfiguration.Result result) {
        if (result.isSuccess()) {
            logger.info("실행 성공: " + result.getMessage());
        } else {
            logger.error("실행 실패: " + result.getMessage());
        }
    }
    @Override
    public void onResult(RunConfiguration.Result result) { result(result); }
}

7. 언어 엔진: LanguageEngine + LanguageFactory

LanguageEngine은 언어와 관련된 모든 Provider를 담는 컨테이너입니다. project.language.engine 확장 포인트를 통해 등록하거나, ProjectFileManager에서 registerEngine을 통해 등록합니다.

주요 Provider 인터페이스:

  • DocumentProvider: 문서 포맷(주석/들여쓰기/괄호 매칭 등)
  • CompletionProvider: 코드 자동 완성(TextMate/LSP/Keyword 등 여러 출처 지원)
  • DiagnosticProvider: 구문 검사 및 진단
  • HoverProvider: 마우스 호버 시 정보 표시
  • NavigationProvider: 정의로 이동 / 참조 찾기
  • SignatureProvider: 메서드 시그니처 힌트

LanguageFactory는 언어의 기본 정보(id, 표시 이름, 파일 확장자)와 LanguageEngine을 연결합니다.


8. 파일 트리 사용자 정의: PSObject 계열

8.1 가상 노드:

PSObjectExpansionCase는 가상 노드(예: 「외부 라이브러리」 폴더)를 동적으로 표시하는 데 사용됩니다.

public class ExternalLibrariesExpansionCase extends PSObjectExpansionCase {
    @Override
    public boolean isExpansionCase(Object marker) {
        return MARKER.equals(marker);  // ProjectFileManager.addPSObjectExpansionCase에서 전달한 marker
    }
    @Override
    public List<PSObject> computeChildren(PSObject parent) {
        List<PSObject> children = new ArrayList<>();
        children.add(new ExternalLibraryNode("go 표준 라이브러리", "/usr/local/go/src"));
        return children;
    }
}

8.2 새 파일 생성:

PSObjectCreationOption은 파일 트리 우클릭 메뉴의 「새 파일」 항목을 정의합니다.

public class GoFileCreationOption extends PSObjectCreationOption {
    @Override public String getName() { return "Go 파일"; }
    @Override public Drawable getIcon() { return GoIcons.FILE; }
    @Override public boolean isAvailable(PSObject parent) { return true; }
    @Override
    public void onCreate(PSObject parent, String name, Consumer<String> onFinish) {
        // 파일 생성 로직
        String content = "package main\n\nfunc main() {\n\tprintln(\"Hello, Go!\")\n}\n";
        // 파일 시스템에 쓰기
        onFinish.accept(name + ".go");  // 생성 완료 콜백
    }
}

8.3 파일 열기 방식:

PSObjectOpeningOption은 특정 파일에 대한 사용자 정의 열기 방식을 등록합니다.


9. 메뉴: BaseDomainMenuAction

domain.menu 확장 포인트를 사용하여 IDE 상단 메뉴에 새 항목을 추가하거나 드롭다운 메뉴를 확장합니다.

public class GomodMenu extends BaseDomainMenuAction {
    @Override public String getText() { return "Go 모듈"; }
    @Override public Drawable getIcon() { return GoIcons.MODULE; }
    @Override
    public void actionPerformed(ActionEvent e) {
        // 메뉴 클릭 처리
        Platform.getProject().getTasks().executeTask("goModTidy", new TaskCallback() {
            @Override public void onSuccess() { /* 성공 처리 */ }
            @Override public void onFailure(String msg) { /* 실패 처리 */ }
        });
    }
}

또한 domain.menu.editor.code 확장 포인트를 사용하여 코드 편집기 영역에 우클릭 메뉴를 추가할 수 있습니다(libgdx 플러그인 참조).


10. 설정 페이지: SettingsBuilder

platform.settingsBuilder 확장 포인트를 사용하여 플러그인 고유의 설정 페이지를 추가합니다.

public class GoSettingsBuilder implements SettingsBuilder {
    @Override public String getTitle() { return "Go"; }
    @Override public Drawable getIcon() { return GoIcons.SETTINGS; }
    @Override
    public SettingsPage build() {
        // Android 표준 PreferenceScreen 또는 사용자 정의 레이아웃 반환
        return new GoSettingsPage();
    }
}

11. 결绳 컴파일러 API: CompilerPlugin + AnnotationProcessor

외부 Kotlin 파일 플러그인은 결绳 컴파일러 플러그인 시스템을 시연합니다:

  • CompilerPlugin: 컴파일러 수명주기(컴파일 전/후 처리)에 연결
  • AnnotationProcessor: 컴파일 중 어노테이션을 처리하여 추가 코드 생성
  • 결绳 코드 완성 엔진과 결합하여 Kotlin에 대한 자동 완성 제공

상세 내용은 externalKotlinFileAnnotationPlugin/ 소스 코드 참조.


12. .rmx 패키징 및 배포

.rmx는 다음을 포함하는 Android APK입니다:

  • AndroidManifest.xml(플러그인 메타데이터)
  • classes.dex(컴파일된 Java/Kotlin 코드)
  • META-INF/program.json(확장 포인트 선언, 필수)

패키징 단계:

  1. Android Studio 또는 Gradle을 사용하여 APK 빌드
  2. 서명된 APK의 확장자를 .rmx로 변경
  3. 사용자가结绳 IDE에서 직접 열거나 설치

13. 추가 팁 및 주의사항

  1. 로거 NPE 문제: BaseTask.prepare()에서 this.logger를 반드시 할당하십시오.
  2. 환경 변수: 안드로이드 환경에서 android.system.Os.setenv()를 사용하여 PATH 및 GOROOT 등을 설정하십시오.
  3. 리소스 관리: AssetUtils.readAsset() 및 AssetUtils.unZipAssetsFolder()를 사용하여 플러그인 asset에서 템플릿 파일을 읽고 압축 해제하십시오.
  4. 호환성: program.json의 minSupport 버전을 확인하여 플러그인이 올바른结绳 버전을 대상으로 하는지 확인하십시오.
  5. 디버깅: 결绳의 로컬 로그 도구를 사용하여 System.out.println() 출력, logcat 또는 특수하게 연결된 플러그인 로그를 확인하십시오.

이 스킬은 계속 업데이트됩니다. 모든 내용은 Gitee의 공식 문서와 GitHub의 커뮤니티 예제를 참조합니다. 질문이나 기여는 GitHub 저장소를 통해 Issue를 제출해 주십시오.

관련 스킬