diff --git a/CHANGELOG.md b/CHANGELOG.md index 6f3bf70..bdc970c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,15 @@ +## 1.6.0 +- Auto config for Deno and Node.js + - Toggle between Deno mode and Node.js mode with a one click. + - You can freely combine the runtime (Deno or Node.js), linter (deno_lint or + eslint), and formatter (deno_fmt or prettier). +- fix bug when outline-view result was null (https://github.com/atom-community/atom-languageclient/pull/150) + +## 1.5.0 +- format on save +- format on Format Current File command (or menu > packages > Deno > Format Curent File) +- format on Format All File command (or menu > packages > Deno > Format All File) + ## 1.4.0 - Hotfix because 1.3 is broken - The package size was temporarily bloated. diff --git a/README.md b/README.md index dac2cf3..a89d665 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,11 @@ Translations: # atom-ide-deno +[![CI](https://github.com/ayame113/atom-ide-deno/actions/workflows/CI.yml/badge.svg)](https://github.com/ayame113/atom-ide-deno/actions/workflows/CI.yml) +[![Dependency Status](https://david-dm.org/ayame113/atom-ide-deno.svg)](https://david-dm.org/ayame113/atom-ide-deno) +[![apm](https://img.shields.io/apm/dm/atom-ide-deno.svg)](https://atom.io/packages/atom-ide-deno) +[![apm](https://img.shields.io/apm/v/atom-ide-deno.svg)](https://atom.io/packages/atom-ide-deno) + Javascript and TypeScript language support for Atom-IDE, powered by the deno language server. @@ -49,6 +54,11 @@ are available. The configuration of the settings is similar to [vscode_deno](https://github.com/denoland/vscode_deno). +- Auto config for Deno and Node.js: + - You can freely combine the runtime (Deno or Node.js), linter (deno_lint or + eslint), and formatter (deno_fmt or prettier). Please note that this rewrite + your settings. This is disabled by default. + ![auto config](https://raw.githubusercontent.com/ayame113/atom-ide-deno/main/screenshot/auto_config.png) - lsp flags - Enables language server: Whether to turn on Language Server - Enables code lens implementations: Code lens settings (currently not diff --git a/deno.png b/deno.png deleted file mode 100644 index e540f6e..0000000 Binary files a/deno.png and /dev/null differ diff --git a/lib/auto_config.ts b/lib/auto_config.ts new file mode 100644 index 0000000..784cce1 --- /dev/null +++ b/lib/auto_config.ts @@ -0,0 +1,177 @@ +import { CompositeDisposable, Disposable } from "atom"; +import type { StatusBar, Tile } from "atom/status-bar"; +//https://github.com/atom/atom-select-list/pull/31 +//import {SelectListView} from "atom-select-list"; + +interface SelectListView { + selectItem(item: Record | string): Promise; + confirmSelection(): void; + cancelSelection(): void; +} + +type modes = "deno" | "node"; +let statusBarElement: HTMLAnchorElement; +let statusBarTile: Tile; +const subscriptions = new CompositeDisposable(); +let tooltip: Disposable; + +// consumeStatusBarとactivateの呼ばれる順番が前後する +// statusbarを受け取ってresolveするPromise +// getstatusBar.then(statusBar=>...) +export let consumeStatusBar: (param: StatusBar) => void; +const getStatusBar = new Promise((resolve) => { + consumeStatusBar = resolve; +}); + +export function activate({ grammarScopes }: { grammarScopes: string[] }) { + //下部のステータスバーをクリックして切り替え + statusBarElement = document.createElement("a"); + statusBarElement.classList.add("inline-block"); + if (!atom.config.get("atom-ide-deno.modes.enable")) { + statusBarElement.classList.add("atom-ide-deno-status-bar-disable"); + } + getStatusBar.then((statusBar) => { + statusBarTile = statusBar.addRightTile({ + item: statusBarElement, + priority: 10.5, + }); + }); + subscriptions.add( + atom.config.onDidChange("atom-ide-deno.modes.currentMode", changeMode), + atom.config.onDidChange("atom-ide-deno.modes.DenoMode", changeMode), + atom.config.onDidChange("atom-ide-deno.modes.NodeMode", changeMode), + atom.config.onDidChange("atom-ide-deno.modes.enable", ({ newValue }) => { + statusBarElement.classList[newValue ? "remove" : "add"]( + "atom-ide-deno-status-bar-disable", + ); + changeMode(); + }), + atom.workspace.observeActiveTextEditor((editor: any) => { + //js/tsと設定画面以外ではステータスバーを非表示 + if ( + grammarScopes.includes(editor?.getGrammar?.()?.scopeName) || + atom.workspace.getPaneItems().some((e: any) => + e?.getURI() == "atom://config" + ) + ) { + statusBarElement.classList.remove( + "atom-ide-deno-status-bar-not-in-scope", + ); + } else { + statusBarElement.classList.add("atom-ide-deno-status-bar-not-in-scope"); + } + }), + ); + statusBarElement.addEventListener("click", () => { + atom.config.set( + "atom-ide-deno.modes.currentMode", + atom.config.get("atom-ide-deno.modes.currentMode") == "deno" + ? "node" + : "deno", + ); + }); + // 全てのpackageの初期が終わったらchangeMode + atom.packages.onDidActivateInitialPackages(changeMode); +} + +function changeMode() { + if (!atom.config.get("atom-ide-deno.modes.enable")) { + return; + } + const newMode: modes = atom.config.get("atom-ide-deno.modes.currentMode"); + console.log(`Mode change to ${newMode}`); + if (newMode == "deno") { + statusBarElement.innerText = "Deno"; + statusBarElement.classList.remove("status-bar-icon-node"); + statusBarElement.classList.add("status-bar-icon-deno"); + } else { + statusBarElement.innerText = "Node.js"; + statusBarElement.classList.remove("status-bar-icon-deno"); + statusBarElement.classList.add("status-bar-icon-node"); + } + //設定変更 + //deno lsp: linterOnlyモード+lint:false->なにも行わない + if (newMode == "deno") { + //atom.packages.enablePackage('atom-ide-deno') + atom.config.set("atom-ide-deno.lspFlags.enable", true); + atom.config.set("atom-ide-deno.advanced.linterOnly", false); + atom.packages.disablePackage("atom-ide-javascript"); + atom.packages.disablePackage("atom-typescript"); + atom.packages.disablePackage("javascript-drag-import"); + } else { + //atom.packages.disablePackage('atom-ide-deno') + atom.config.set("atom-ide-deno.lspFlags.enable", true); + atom.config.set("atom-ide-deno.advanced.linterOnly", true); + atom.packages.enablePackage("atom-ide-javascript"); + atom.packages.enablePackage("atom-typescript"); + atom.packages.enablePackage("javascript-drag-import"); + } + const { linter, formatter } = atom.config.get( + `atom-ide-deno.modes.${newMode == "deno" ? "Deno" : "Node"}Mode`, + ); + // linter + (async () => { + // deno lint + const isDenoLintEnable = linter == "deno lint"; + atom.config.set("atom-ide-deno.lspFlags.lint", isDenoLintEnable); + // eslint + const isEslintEnable = linter == "eslint"; + await atom.commands.dispatch( + (atom.workspace as any).getElement(), + isEslintEnable ? "linter:enable-linter" : "linter:disable-linter", + ); + const selectListViewItem = atom.workspace.getModalPanels().filter((v) => + v.isVisible() && v.getItem().constructor.name == "SelectListView" + )[0]?.getItem() as SelectListView; + try { + await selectListViewItem?.selectItem("ESLint"); + selectListViewItem?.confirmSelection(); + } catch (_) { + selectListViewItem.cancelSelection(); + } + try { + await atom.commands.dispatch( + (atom.workspace.getActiveTextEditor() as any).getElement(), + "linter:lint", + ); + } catch (_) { + _; + } + })(); + // formatter + { + //deno fmt + const isDenoFormatEnable = formatter == "deno fmt"; + atom.config.set("atom-ide-deno.format.onSave.enable", isDenoFormatEnable); + // prettier + const isPrettierEnable = formatter == "prettier"; + if (isPrettierEnable) { + atom.packages.enablePackage("prettier-atom"); + } else { + atom.packages.disablePackage("prettier-atom"); + } + } + //tooltip + tooltip?.dispose(); + tooltip = atom.tooltips.add(statusBarElement, { + title: `
+ Enabled:
+ ${ + (newMode == "deno" + ? ["atom-ide-deno"] + : ["atom-ide-javascript", "atom-typescript", "javascript-drag-import"]) + .map((v) => `• ${v}
`).join("") + } + • ${linter}
+ • ${formatter}
+ Click to toggle Deno
and Node.js mode. +
`, + delay: { show: 0, hide: 100 }, + }); +} + +export function deactivate() { + statusBarTile.destroy(); + subscriptions.dispose(); + tooltip.dispose(); +} diff --git a/lib/config.ts b/lib/config.ts index ba85be6..5d1fe86 100644 --- a/lib/config.ts +++ b/lib/config.ts @@ -1,15 +1,15 @@ export interface atomConfig { [key: string]: | configValObj - | configVal + | configVal | configVal - | configVal - | configVal + | configVal + | configVal | configVal - | configValArray + | configValArray | configValArray - | configValArray - | configValArray + | configValArray + | configValArray | configValArray; } @@ -26,6 +26,7 @@ interface configValBase { | "color" | "never"; order: number; + radio?: boolean; } interface configValObj extends configValBase { type: "object"; @@ -34,6 +35,7 @@ interface configValObj extends configValBase { interface configVal extends configValBase { type: TypeName; default: T; + enum?: T[] | enumContent[]; } interface configValArray extends configValBase { type: "array"; @@ -42,40 +44,145 @@ interface configValArray extends configValBase { type: TypeName; }; } -type TypeName = T extends String ? "string" +type TypeName = T extends string ? "string" : T extends Integer ? "integer" - : T extends Number ? "number" - : T extends Boolean ? "boolean" + : T extends number ? "number" + : T extends boolean ? "boolean" : T extends Color ? "color" : "never"; -type Color = String; -type Integer = Number; + +interface enumContent { + value: T; + description?: string; +} +type Color = string; +type Integer = number; export const config: atomConfig = { + modes: { + title: "Auto config for Deno and Node.js", + description: `Toggle between Deno mode and Node.js mode with a one click. + To toggle between modes, click on the part labeled \`Deno\` or \`Node.js\` in the status bar at the bottom.`, + type: "object", + order: 1, + properties: { + enable: { + title: "enables", + description: + "⚠️Please note that enabling this will automatically rewrite your package settings. If you do not want this behavior, disable it.", + type: "boolean", + default: false, + order: 1, + }, + currentMode: { + title: "current mode", + type: "string", + default: "deno", + enum: [ + { + value: "deno", + description: "Deno mode", + }, + { + value: "node", + description: "Node.js mode", + }, + ], + radio: true, + order: 2, + }, + DenoMode: { + title: "Configuration in *Deno* mode", + description: + `You can customize the configuration used when you select Deno mode. + When you select Deno mode, the following settings apply: + • Atom-ide-deno (package for Deno runtime): Enable (and then disable the \`Linter Only\` setting) + • Atom-ide-javascript (package for Node.js runtime): Disable + • Atom-typescript (package for Node.js runtime): Disable + • Javascript-drag-import (package for Node.js runtime): Disable`, + type: "object", + order: 3, + properties: { + linter: { + title: "Linter", + description: + `• \`deno lint\`: Use the built-in linter from the deno language server. Add ESLint to the \`Disabled provider\` setting in the \`Linter\` package. + • \`eslint\`: Remove ESLint from the \`Disabled provider\` setting in the \`Linter\` package. Disable the built-in deno linter. + • \`disable both\`: Disables both \`deno lint\` and \`eslint\`.`, + type: "string", + default: "deno lint", + order: 1, + enum: ["deno lint", "eslint", "disable both"], + }, + formatter: { + title: "Formatter", + description: + `• \`deno fmt\`: Use the built-in deno formatter (deno fmt). If the \`prettier-atom\` package is installed, disable it. + • \`prettier\`: Enable the \`prettier-atom\` package if it is installed. Disables the built-in deno formatter. + • \`disable both\`: Disable both \`deno fmt\` and \`prettier\`.`, + type: "string", + default: "deno fmt", + order: 2, + enum: ["deno fmt", "prettier", "disable both"], + }, + }, + }, + NodeMode: { + title: "Configuration in *Node.js* mode", + description: + `You can customize the configuration used when you select Node.js mode. + When you select Node.js mode, the following settings apply: + • Atom-ide-deno (package for Deno runtime): Enable (and then enable the \`Linter Only\` setting) + • Atom-ide-javascript (package for Node.js runtime): Enable + • Atom-typescript (package for Node.js runtime): Enable + • Javascript-drag-import (package for Node.js runtime): Enable`, + type: "object", + order: 4, + properties: { + linter: { + title: "Linter", + description: `Same as above`, + type: "string", + default: "eslint", + order: 1, + enum: ["deno lint", "eslint", "disable both"], + }, + formatter: { + title: "Formatter", + description: `Same as above`, + type: "string", + default: "prettier", + order: 2, + enum: ["deno fmt", "prettier", "disable both"], + }, + }, + }, + }, + }, lspFlags: { title: "lsp flags", description: "This setting is based on [vscode extention](https://github.com/denoland/vscode_deno)", type: "object", - order: 1, + order: 2, properties: { enable: { title: "Enables language server", type: "boolean", default: true, - order: 2, + order: 1, }, lint: { title: "Enables lint", type: "boolean", default: true, - order: 3, + order: 2, }, unstable: { title: "Enables unstable", type: "boolean", default: false, - order: 4, + order: 3, }, importMap: { title: "Path to import-map", @@ -83,7 +190,7 @@ export const config: atomConfig = { "Relative path from the project root (ex. `./import-map.json`)", type: "string", default: "", - order: 5, + order: 4, }, config: { title: "Path to tsconfig", @@ -91,66 +198,66 @@ export const config: atomConfig = { "Relative path from the project root (ex. `./tsconfig.json`)", type: "string", default: "", - order: 6, + order: 5, }, codeLens: { title: "code lens", type: "object", - order: 7, + order: 6, properties: { implementations: { title: "Enables implementations", type: "boolean", default: true, - order: 8, + order: 1, }, references: { title: "Enables references", type: "boolean", default: true, - order: 9, + order: 2, }, referencesAllFunctions: { title: "Enables references all functions", type: "boolean", default: true, - order: 10, + order: 3, }, }, }, suggest: { title: "suggest", type: "object", - order: 11, + order: 7, properties: { autoImports: { title: "Enables auto imports", type: "boolean", default: true, - order: 12, + order: 1, }, completeFunctionCalls: { title: "Enables complete function calls", type: "boolean", default: true, - order: 13, + order: 2, }, names: { title: "Enables names", type: "boolean", default: true, - order: 14, + order: 3, }, paths: { title: "Enables paths", type: "boolean", default: true, - order: 15, + order: 4, }, imports: { title: "imports", type: "object", - order: 16, + order: 5, properties: { hosts: { title: "List of hosts", @@ -162,7 +269,7 @@ export const config: atomConfig = { "https://x.nest.land/", "https://envoy.now.sh/", ], - order: 17, + order: 1, items: { type: "string", }, @@ -176,47 +283,47 @@ export const config: atomConfig = { format: { title: "Format options", type: "object", - order: 10, + order: 3, properties: { onSave: { title: "Format on save", type: "object", - order: 11, + order: 1, properties: { enable: { title: "enables", type: "boolean", default: true, - order: 11, + order: 1, }, extensions: { title: "File type to enable", type: "object", - order: 12, + order: 2, properties: { "source_js": { title: "JavaScript", type: "boolean", default: true, - order: 13, + order: 1, }, "source_ts": { title: "TypeScript", type: "boolean", default: true, - order: 14, + order: 2, }, "source_gfm": { title: "markdown", type: "boolean", default: true, - order: 15, + order: 3, }, "source_json": { title: "json", type: "boolean", default: true, - order: 16, + order: 4, }, }, }, @@ -225,12 +332,12 @@ export const config: atomConfig = { onCommand: { title: "Format on command", type: "object", - order: 17, + order: 2, properties: { excludDir: { title: "Excluded directories list when command `Format All File`", type: "array", - order: 18, + order: 1, default: ["./node_modules/"], items: { type: "string", @@ -240,12 +347,62 @@ export const config: atomConfig = { }, }, }, + advanced: { + title: "Advanced", + type: "object", + order: 4, + properties: { + linterOnly: { + title: "Linter only", + description: "When enabled, features other than linter are ignored.", + type: "boolean", + default: false, + order: 1, + }, + debugMode: { + title: "debug mode", + description: "Output log to console (ctrl+shift+i)", + type: "boolean", + default: false, + order: 2, + }, + }, + }, path: { title: "Deno path", description: "Path to the deno executable.(ex. `/usr/bin/deno`, `C:\\\\Program Files\\\\deno\\\\deno.exe`)", type: "string", default: "", - order: 19, + order: 5, }, }; + +/* +キーボード入力のプロパティ一覧 +lspの再起動を延期する +returns->[ + ["lspFlags", "importMap"], + ["lspFlags", "config"], + ["lspFlags", "suggest", "imports", "hosts"], + ["format", "onCommand", "excludDir"] + ["path"] +] +*/ +function getKeyboardInputsKeyPath(o: atomConfig) { + const res: string[][] = []; + for (const [k, v] of Object.entries(o)) { + if ( + ["string", "integer", "number", "array"].includes(v.type) && + !("enum" in v) + ) { + res.push([k]); + } else if (v.type === "object") { + const r = getKeyboardInputsKeyPath(v.properties); + res.push(...r.map((v) => [k, ...v])); + } + } + return res; +} + +export const keyboardInputsKeyPath = getKeyboardInputsKeyPath(config); diff --git a/lib/formatter.ts b/lib/formatter.ts index 8d5deb5..9b593a8 100644 --- a/lib/formatter.ts +++ b/lib/formatter.ts @@ -28,17 +28,16 @@ export function formatFile( denoPath: string, options: string[], filePath: string, -): Promise<{ stdout: string; stderr: string }> { +): Promise<{ error: Error | null; stdout: string; stderr: string }> { const commandOption = ["fmt", ...options, filePath]; console.log("env: ", process.env); console.log(denoPath, ...commandOption); return new Promise((resolve) => { cp.execFile(denoPath, commandOption, { env: process.env, - }, (_error, stdout, stderr) => { - console.log(stderr); - console.log(stdout); - resolve({ stdout, stderr }); + }, (error, stdout, stderr) => { + console.log({ error, stdout, stderr }); + resolve({ error, stdout, stderr }); }); }); } diff --git a/lib/linter_only.ts b/lib/linter_only.ts new file mode 100644 index 0000000..e05a6b8 --- /dev/null +++ b/lib/linter_only.ts @@ -0,0 +1,71 @@ +import type { PublishDiagnosticsParams } from "vscode-languageserver-protocol"; + +// 副作用がある +// target: DenoLanguageClientに対してLinterOnlyModeを追加する +export function addLinterOnlyMode(target: any) { + //LinterOnlyの時はLinter以外の情報を返さない + //それぞれの関数で返すべきデフォルト値 + //機能が追加された場合(package.jsonのprovide/consume)はここにデフォルト値を追加 + const functionResults = { + getDatatip: null, + getSuggestions: [], + getDefinition: null, + getOutline: null, + getReferences: null, + getRangeCodeFormat: [], + getFileCodeFormat: [], + getOnTypeCodeFormat: [], + getCodeHighlight: null, + getCodeActions: null, + getRename: null, + }; + //関数を横取りしてLinterOnlyを判定 + for ( + const [functionName, defaultReturnvalue] of Object.entries(functionResults) + ) { + const original = target[functionName]; + target[functionName] = (...args: any[]) => { + //LinterOnlyの時はデフォルト値を返す + if (target._linterOnly) { + return defaultReturnvalue; + } + return original.call(target, ...args); + }; + } + //signatureHelpは横取りできないので、preInitialization内でconnectionの関数を横取り + { + const original = target.preInitialization; + target.preInitialization = (connection: any, ...args: any[]) => { + original.call(target, connection, ...args); + const originalSignatureHelp = connection.signatureHelp; + connection.signatureHelp = (...signatureHelpArgs: any) => { + if (target._linterOnly) { + return null; + } + return originalSignatureHelp.call(connection, ...signatureHelpArgs); + }; + const originalOnPublishDiagnostics = connection.onPublishDiagnostics; + connection.onPublishDiagnostics = ( + callback: Function, + ...args: any[] + ) => { + originalOnPublishDiagnostics.call( + connection, + (result: PublishDiagnosticsParams) => { + if (!target._linterOnly || result == null) { + callback(result); + return; + } + const { diagnostics, ...other } = result; + callback({ + diagnostics: diagnostics.filter((v) => v.source == "deno-lint"), + ...other, + }); + }, + ...args, + ); + }; + }; + } + return target; +} diff --git a/lib/main.ts b/lib/main.ts index e49f6e3..f321c99 100644 --- a/lib/main.ts +++ b/lib/main.ts @@ -1,6 +1,8 @@ -import { config } from "./config"; +import { config, keyboardInputsKeyPath } from "./config"; import type { atomConfig } from "./config"; import * as formatter from "./formatter"; +import { addLinterOnlyMode } from "./linter_only"; +import * as autoConfig from "./auto_config"; import { menu } from "../menus/main.json"; import { @@ -16,6 +18,7 @@ import type { import type { ServerManager } from "atom-languageclient/lib/server-manager"; import type { Point } from "atom"; import { CompositeDisposable, TextEditor } from "atom"; +import type { StatusBar } from "atom/status-bar"; import type { TextDocumentIdentifier } from "vscode-languageserver-protocol"; import cp from "child_process"; import path from "path"; @@ -25,17 +28,18 @@ const getDenoPath = (): string => class DenoLanguageClient extends AutoLanguageClient { config: atomConfig = config; - _isDebug = false; - _isDebugAtConfigFile: boolean = atom.config.get("core.debugLSP"); + _isDebug!: boolean; _emptyConnection!: LanguageClientConnection; - subscriptions?: CompositeDisposable; + subscriptions!: CompositeDisposable; //isDebug=true時に再起動 - get isDebug() { - return this._isDebug; + async setDebugMode(isDebug: boolean) { + this._isDebug = isDebug; + await this.restartAllServers(); } - set isDebug(v) { - this._isDebug = v; - this.restartAllServers(); + debugLog(...msg: any[]) { + if (this._isDebug) { + console.trace(...msg); + } } getGrammarScopes() { return [ @@ -56,6 +60,7 @@ class DenoLanguageClient extends AutoLanguageClient { return "deno-language-server"; } getInitializeParams(...args: [string, LanguageServerProcess]) { + this.debugLog("initializing..."); const initializationOptions = atom.config.get("atom-ide-deno.lspFlags"); //filter empty string initializationOptions.importMap = initializationOptions.importMap || void 0; @@ -71,9 +76,7 @@ class DenoLanguageClient extends AutoLanguageClient { } catch (e) { console.log(e); } - if (this.isDebug) { - console.log(initializationOptions); - } + this.debugLog(initializationOptions); //https://github.com/denoland/deno/pull/8850 //enableフラグが必要 return Object.assign(super.getInitializeParams(...args), { @@ -81,30 +84,32 @@ class DenoLanguageClient extends AutoLanguageClient { }); } activate() { + this.debugLog("activating..."); super.activate(); this.subscriptions = new CompositeDisposable(); onActivate(this); + autoConfig.activate({ grammarScopes: this.getGrammarScopes() }); } async deactivate() { + this.debugLog("deactivating..."); + autoConfig.deactivate(); await super.deactivate(); this.subscriptions?.dispose(); } restartAllServers(...args: []) { - console.log("restart Deno Language server"); + this.debugLog("restart Deno Language server"); atom.notifications.addInfo("restart Deno Language server"); return super.restartAllServers(...args); } getLogger() { return new FilteredLogger( console, - (lebel) => - this._isDebug || this._isDebugAtConfigFile || - ["warn", "error"].includes(lebel), + (lebel) => this._isDebug || ["warn", "error"].includes(lebel), ); } async getDefinition(...args: [TextEditor, Point]) { const res = await super.getDefinition(...args); - if (this.isDebug) console.log(res); + this.debugLog(res); if (res == null) return null; const { definitions, ...others } = res; // `deno:/` から始まるカスタムリクエストは相対パスとして解釈されてしまう @@ -233,26 +238,69 @@ class DenoLanguageClient extends AutoLanguageClient { }); } } + // DenoMode / NodeMode + _linterOnly = false; + setLinterOnlyMode(v: boolean) { + this._linterOnly = v; + } + consumeStatusBar(statusBar: StatusBar) { + autoConfig.consumeStatusBar(statusBar); + } } -export default new DenoLanguageClient(); +export default addLinterOnlyMode(new DenoLanguageClient()); function onActivate(denoLS: DenoLanguageClient) { //config変更時にlspを再起動 - //importMap pathの入力途中でfile not foundエラーが出るため、2秒間間引く + //文字列の入力途中でfile not foundエラーが出るため、2秒間間引く let inputTimeoutId: NodeJS.Timeout; - function restartServer() { + function restartServer( + { oldValue = {}, newValue }: { oldValue?: any; newValue: any }, + keyPathbase: string[], + ) { console.log("atom-ide-deno config change caught"); clearTimeout(inputTimeoutId); - inputTimeoutId = setTimeout((_) => { + let isDefferRestart = false; + //keyboardInputsKeyPathに含まれるキーの値が変更されていれば、実行を延期(間引く) + for (const keyPath of keyboardInputsKeyPath) { + //無関係なkeyPathは無視 + if (!keyPathbase.every((v, i) => keyPath[i] == v)) { + continue; + } + //keyPathbaseを起点としてdiff + let oldV = oldValue; + let newV = newValue; + for (const key of keyPath.slice(keyPathbase.length)) { + oldV = oldV?.[key]; + newV = newV?.[key]; + } + //値は配列か文字列か数値 + isDefferRestart = JSON.stringify(oldV) !== JSON.stringify(newV); + if (isDefferRestart) { + break; + } + } + if (isDefferRestart) { + inputTimeoutId = setTimeout(() => { + denoLS.restartAllServers(); + }, 2000); + } else { denoLS.restartAllServers(); - }, 2000); + } } - denoLS.subscriptions?.add( - atom.config.onDidChange("atom-ide-deno.lspFlags", restartServer), - atom.config.onDidChange("atom-ide-deno.path", restartServer), - atom.config.onDidChange("core.debugLSP", () => { - denoLS._isDebugAtConfigFile = atom.config.get("core.debugLSP"); - denoLS.restartAllServers(); + denoLS.subscriptions.add( + atom.config.onDidChange( + "atom-ide-deno.lspFlags", + (v) => restartServer(v, ["lspFlags"]), + ), + atom.config.onDidChange( + "atom-ide-deno.path", + (v) => restartServer(v, ["path"]), + ), + atom.config.observe("atom-ide-deno.advanced.debugMode", (newValue) => { + denoLS.setDebugMode(newValue); + }), + atom.config.observe("atom-ide-deno.advanced.linterOnly", (newValue) => { + denoLS.setLinterOnlyMode(newValue); }), //virtual documentを表示 atom.workspace.addOpener((filePath) => { @@ -299,7 +347,7 @@ function onActivate(denoLS: DenoLanguageClient) { originalFunctions[funcName] = editor[funcName]; editor[funcName] = (...args: any[]) => calledArgs[funcName]?.push(args); } - (async (_) => { + (async () => { const doc = await denoLS.getDenoVirtualTextDocument({ uri: filePath.replace("deno://", "deno:/"), }); @@ -323,6 +371,7 @@ function onActivate(denoLS: DenoLanguageClient) { return editor; }), //コマンド登録 + //コマンドの内容はmenu/main.jsonで管理 atom.commands.add( "atom-workspace", Object.fromEntries( diff --git a/package-lock.json b/package-lock.json index 195dcab..aa7b9dd 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,9 +13,9 @@ } }, "@types/dompurify": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/@types/dompurify/-/dompurify-2.2.1.tgz", - "integrity": "sha512-3JwbEeRVQ3n6+JgBW/hCdkydRk9/vWT+UEglcXEJqLJEcUganDH37zlfLznxPKTZZfDqA9K229l1qN458ubcOQ==", + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/@types/dompurify/-/dompurify-2.2.2.tgz", + "integrity": "sha512-8nNWfAa8/oZjH3OLY5Wsxu9ueo0NwVUotIi353g0P2+N5BuTLJyAVOnF4xBUY0NyFUGJHY05o1pO2bqLto+lmA==", "requires": { "@types/trusted-types": "*" } @@ -45,9 +45,9 @@ "integrity": "sha512-KfRL3PuHmqQLOG+2tGpRO26Ctg+Cq1E01D2DMriKEATHgWLfeNDmq9e29Q9WIky0dQ3NPkd1mzYH8Lm936Z9qw==" }, "@types/react": { - "version": "17.0.3", - "resolved": "https://registry.npmjs.org/@types/react/-/react-17.0.3.tgz", - "integrity": "sha512-wYOUxIgs2HZZ0ACNiIayItyluADNbONl7kt8lkLjVK8IitMH5QMyAh75Fwhmo37r1m7L2JaFj03sIfxBVDvRAg==", + "version": "17.0.5", + "resolved": "https://registry.npmjs.org/@types/react/-/react-17.0.5.tgz", + "integrity": "sha512-bj4biDB9ZJmGAYTWSKJly6bMr4BLUiBrx9ujiJEoP9XIDY9CTaPGxE5QWN/1WjpPLzYF7/jRNnV2nNxNe970sw==", "requires": { "@types/prop-types": "*", "@types/scheduler": "*", @@ -117,9 +117,9 @@ } }, "atom-languageclient": { - "version": "1.8.2", - "resolved": "https://registry.npmjs.org/atom-languageclient/-/atom-languageclient-1.8.2.tgz", - "integrity": "sha512-sY/NIqhuXx247LMKH8unkJ9Bo1u8e5rjtWsBjnXeP73ntIfxDx2tT3tFSp2Epd1aQiiBAOa1gxE4nx2UIsJhcA==", + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/atom-languageclient/-/atom-languageclient-1.8.3.tgz", + "integrity": "sha512-AVKb8rBOpTNQDrmxLbiQqMktwzGmMiIvsBMDF+Zs4XYoWYoUivYr0YpDfUQ57WsS7nZKwFCAqjrmkRQWTxAfMQ==", "requires": { "@types/rimraf": "^3.0.0", "atom-ide-base": "^2.6.0", @@ -135,6 +135,16 @@ "resolved": "https://registry.npmjs.org/atom-package-deps/-/atom-package-deps-7.2.3.tgz", "integrity": "sha512-Z1FHJS2c2xBN3wQVniG7jXDyE4mUjZlHA0tfIkCND9U/fHaZyBJPno4/jD8PtYUnhlymaHRbCsgxCU3QuKjqfQ==" }, + "atom-select-list": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/atom-select-list/-/atom-select-list-0.8.0.tgz", + "integrity": "sha512-LZBLl2Mn0ov/CfUV+INrfENQVVdfdXvdB4MGvmvM28Rsm/ViVAuVMjNotvZKVCo5Jm53s/Ixd8K1deQV2WHcxA==", + "dev": true, + "requires": { + "etch": "^0.14.0", + "fuzzaldrin": "^2.1.0" + } + }, "atom-ts-transpiler": { "version": "1.5.3", "resolved": "https://registry.npmjs.org/atom-ts-transpiler/-/atom-ts-transpiler-1.5.3.tgz", @@ -187,9 +197,9 @@ } }, "dompurify": { - "version": "2.2.7", - "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-2.2.7.tgz", - "integrity": "sha512-jdtDffdGNY+C76jvodNTu9jt5yYj59vuTUyx+wXdzcSwAGTYZDAQkQ7Iwx9zcGrA4ixC1syU4H3RZROqRxokxg==" + "version": "2.2.8", + "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-2.2.8.tgz", + "integrity": "sha512-9H0UL59EkDLgY3dUFjLV6IEUaHm5qp3mxSqWw7Yyx4Zhk2Jn2cmLe+CNPP3xy13zl8Bqg+0NehQzkdMoVhGRww==" }, "etch": { "version": "0.14.1", @@ -212,6 +222,12 @@ "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" }, + "fuzzaldrin": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fuzzaldrin/-/fuzzaldrin-2.1.0.tgz", + "integrity": "sha1-kCBMPi/appQbso0WZF1BgGOpDps=", + "dev": true + }, "glob": { "version": "7.1.6", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", diff --git a/package.json b/package.json index 57263d1..bf54fc8 100644 --- a/package.json +++ b/package.json @@ -24,13 +24,14 @@ "test": "atom --test spec" }, "dependencies": { - "atom-languageclient": "^1.8.0", + "atom-languageclient": "^1.8.3", "atom-ts-transpiler": "^1.5.3", "typescript": "^4.2.4" }, "devDependencies": { "@types/atom": "1.40.10", "@types/node": "^14.14.37", + "atom-select-list": "^0.8.0", "deno-bin": "github:ayame113/deno-bin", "vscode-languageserver-protocol": "^3.16.0" }, diff --git a/screenshot/auto_config.png b/screenshot/auto_config.png new file mode 100644 index 0000000..c3c797b Binary files /dev/null and b/screenshot/auto_config.png differ diff --git a/styles/deno-png.css b/styles/deno-png.css new file mode 100644 index 0000000..c3187a9 --- /dev/null +++ b/styles/deno-png.css @@ -0,0 +1,6 @@ +:root{ + /*https://github.com/denoland/deno/blob/main/docs/images/deno3.png*/ + /*MIT*/ + --atom-ide-deno-polygon-data-url: url('data:image/svg+xml;charset=utf8,%3Csvg%20version%3D%221.1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20x%3D%220px%22%20y%3D%220px%22%20width%3D%22300%22%20height%3D%22300%22%20viewBox%3D%22-150%20-150%20300%20300%22%3E%20%3Cpath%20d%3D%22M130%2075%20L0%20150%20L-130%2075%20L-130%20-75%20L-0%20-150%20L130%20-75%20z%22%20style%3D%22fill%3Agray%22%3E%3C%2Fpath%3E%3C%2Fsvg%3E'); + --atom-ide-deno-deno-image-data-url: url('data:image/png;base64,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'); +} \ No newline at end of file diff --git a/styles/main.css b/styles/main.css index 1cf647a..95e2ad7 100644 --- a/styles/main.css +++ b/styles/main.css @@ -1,10 +1,31 @@ +@import url('./deno-png.css'); + .icon-deno::before { content: ' ' !important; background-size: 75%; background-repeat: no-repeat; background-position: 50% 0.75em; - /* prettier-ignore */ - background-image: url( - 'data:image/png;base64,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' - ); + background-image: var(--atom-ide-deno-deno-image-data-url); +} +.atom-ide-deno-status-bar-disable, +.atom-ide-deno-status-bar-not-in-scope{ + display: none; +} + +.status-bar-icon-deno::before, +.status-bar-icon-node::before { + content: ""; + background-size: 68%; + background-repeat: no-repeat; + background-position: 50%; + display: inline-block; + width: 2em; + height: 2em; + vertical-align: bottom; +} +.status-bar-icon-deno::before { + background-image: var(--atom-ide-deno-deno-image-data-url); +} +.status-bar-icon-node::before { + background-image: var(--atom-ide-deno-polygon-data-url); }