Skip to content

Commit

Permalink
Deactivate command (#42)
Browse files Browse the repository at this point in the history
  • Loading branch information
friedbrice authored Mar 11, 2024
1 parent 7807576 commit 458b45e
Show file tree
Hide file tree
Showing 9 changed files with 181 additions and 104 deletions.
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,13 @@ All notable changes to the "alloglot" extension will be documented in this file.
The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/).
This project adhere's to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [unreleased]

- Add `deactivateCommand` to `TConfig` to run on extension `deactivate()`
- Add `verboseOutput` to `TConfig`. Hide some existing output behind said config.
- Minor bugfixes in async processes.
- Minor wording changes in some UI output messages.

## [2.5.1]

- Stream activate command stdout to output channel.
Expand Down
25 changes: 18 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@ Most of the properties are optional, so you can make use of only the features th

```json
{
"alloglot.activationCommand": "ghcid",
"alloglot.activateCommand": "ghcid",
"alloglot.deactivateCommand": "pgrep ghc | xargs kill",
"alloglot.languages": [
{
"languageId": "cabal",
Expand Down Expand Up @@ -102,18 +103,28 @@ This allows use of the features you want without unwanted features getting in yo
/**
* Extension configuration.
*/
export type Config = {
/**
* An array of per-language configurations.
*/
languages: Array<LanguageConfig>

export type TConfig = {
/**
* A shell command to run on activation.
* The command will run asynchronously.
* It will be killed (if it's still running) on deactivation.
*/
activateCommand?: string

/**
* A shell command to run on deactivation.
*/
deactivateCommand?: string

/**
* An array of per-language configurations.
*/
languages?: Array<LanguageConfig>

/**
* If `true`, Alloglot will log more output.
*/
verboseOutput?: boolean
}

/**
Expand Down
16 changes: 13 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,15 +23,15 @@
"commands": [
{
"command": "alloglot.command.restart",
"title": "Restart Alloglot"
"title": "Alloglot: Restart Alloglot"
},
{
"command": "alloglot.command.apisearch",
"title": "Go to API Search"
"title": "Alloglot: Go to API Search"
},
{
"command": "alloglot.command.suggestimports",
"title": "Suggest Imports..."
"title": "Alloglot: Suggest Imports..."
}
],
"menus": {
Expand All @@ -54,6 +54,16 @@
"description": "A shell command to run on activation. The command will run asynchronously. It will be killed (if it's still running) on deactivation.",
"default": null
},
"alloglot.deactivateCommand": {
"type":"string",
"description": "A shell command to run on deactivation.",
"default":null
},
"alloglot.verboseOutput": {
"type":"boolean",
"description": "If `true`, Alloglot will log more output.",
"default":null
},
"alloglot.languages": {
"type": "array",
"description": "An array of language configurations. See README.md for schema.",
Expand Down
9 changes: 4 additions & 5 deletions src/apisearch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -206,20 +206,19 @@ Portions of this software are derived from [vscode-goto-documentation](https://g

import * as vscode from 'vscode'

import { Config, alloglot } from './config'
import { TConfig, alloglot } from './config'

export function makeApiSearch(output: vscode.OutputChannel, config: Config): vscode.Disposable {
export function makeApiSearch(output: vscode.OutputChannel, config: TConfig): vscode.Disposable {
const { languages } = config
if (!languages || languages.length === 0) return vscode.Disposable.from()

output.appendLine(alloglot.ui.creatingApiSearch(languages.map(lang => lang.languageId)))

const langs: Map<string, string> = new Map()
languages.forEach(lang => {
lang.languageId && lang.apiSearchUrl && langs.set(lang.languageId, lang.apiSearchUrl)
})

output.appendLine(alloglot.ui.creatingApiSearch)
config.languages?.forEach(lang => output.appendLine(`\t${lang.languageId}`))

return vscode.commands.registerTextEditorCommand(
alloglot.commands.apiSearch,
editor => {
Expand Down
67 changes: 44 additions & 23 deletions src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,28 @@ import * as vscode from 'vscode'
/**
* Extension configuration.
*/
export type Config = {
export type TConfig = {
/**
* A shell command to run on activation.
* The command will run asynchronously.
* It will be killed (if it's still running) on deactivation.
*/
activateCommand?: string

/**
* A shell command to run on deactivation.
*/
deactivateCommand?: string

/**
* An array of per-language configurations.
*/
languages?: Array<LanguageConfig>

/**
* If `true`, Alloglot will log more output.
*/
verboseOutput?: boolean
}

/**
Expand Down Expand Up @@ -177,10 +187,10 @@ export type AnnotationsMapping = {
}

export namespace Config {
export function make(output: vscode.OutputChannel): Config {
const empty: Config = {}
export function make(output: vscode.OutputChannel): TConfig {
const empty: TConfig = {}

function readFallback(): Config | undefined {
function readFallback(): TConfig | undefined {
const workspaceFolders = vscode.workspace.workspaceFolders?.map(folder => folder.uri)
try {
if (workspaceFolders && workspaceFolders.length > 0) {
Expand All @@ -197,23 +207,27 @@ export namespace Config {
}
}

function readSettings(): Config | undefined {
function readSettings(): TConfig | undefined {
output.appendLine(alloglot.ui.readingWorkspaceSettings)
const workspaceSettings = vscode.workspace.getConfiguration(alloglot.config.root)
const activateCommand = workspaceSettings.get<string>(alloglot.config.activateCommand)
const deactivateCommand = workspaceSettings.get<string>(alloglot.config.deactivateCommand)
const languages = workspaceSettings.get<Array<LanguageConfig>>(alloglot.config.languages)
const settingsExist = !!(activateCommand || languages)
const verboseOutput = workspaceSettings.get<boolean>(alloglot.config.verboseOutput)
const settingsExist = !!(activateCommand || languages || deactivateCommand || verboseOutput)
output.appendLine(alloglot.ui.workspaceConfigExists(settingsExist))
if (settingsExist) return { activateCommand, languages }
if (settingsExist) return { activateCommand, deactivateCommand, languages, verboseOutput }
return undefined
}

return sanitizeConfig(readSettings() || readFallback() || empty)
}

function sanitizeConfig(config: Config): Config {
function sanitizeConfig(config: TConfig): TConfig {
return {
activateCommand: config.activateCommand?.trim(),
deactivateCommand: config.deactivateCommand?.trim(),
verboseOutput: !!config.verboseOutput,
languages: config.languages?.filter(lang => {
// make sure no fields are whitespace-only
// we mutate the original object because typescript doesn't have a `filterMap` function
Expand Down Expand Up @@ -247,48 +261,51 @@ export namespace alloglot {
export const root = 'alloglot' as const

export namespace ui {
export const activateCommandDone = (cmd: string) => `Activation command ${cmd} has completed.`
export const activateCommandDone = (cmd: string) => `Activation command ${cmd} has completed.`
export const addImport = (moduleName: string) => `Add import: ${moduleName}`
export const annotationsStarted = 'Annotations started.'
export const appliedEdit = (success: boolean) => `Applied edit: ${success}`
export const applyingTransformations = (t: any, x: string) => `Applying ${JSON.stringify(t)} to ${x}`
export const commandKilled = (cmd: string) => `Killed \`\`${cmd}''.`
export const commandLogs = (cmd: string, logs: string) => `Logs from \`\`${cmd}'':\n\t${logs}`
export const commandNoOutput = (cmd: string) => `Received no output from \`\`${cmd}''.`
export const commandKilled = (cmd: string) => `Killed ${cmd}.`
export const commandLogs = (cmd: string, logs: string) => `Logs from ${cmd}:\n\t${logs}`
export const commandNoOutput = (cmd: string) => `Received no output from ${cmd}.`
export const couldNotReadFallback = (err: any) => `Could not read fallback configuration: ${err}`
export const creatingApiSearch = 'Creating API search command for languages...'
export const creatingTagsSource = (path: string) => `Creating tags source for ${path}`
export const creatingApiSearch = (langIds: Array<string>) => `Creating API search command for languages: ${langIds}`
export const creatingTagsSource = (path: string) => `Creating tags source for path: ${path}`
export const deactivatingAlloglot = `Deactivating Alloglot...`
export const deactivateCommandDone = (cmd: string) => `Deactivation command has completed: ${cmd}`
export const deactivateCommandFailed = (err: any) => `Deactivation command has completed: ${err}`
export const disposingAlloglot = 'Disposing Alloglot...'
export const errorRunningCommand = (cmd: string, err: any) => `Error running \`\`${cmd}'':\n\t${err}`
export const errorRunningCommand = (cmd: string, err: any) => `Error running ${cmd}:\n\t${err}`
export const fileMatcherResult = (result: any) => `Match: ${result}`
export const findingImportPosition = 'Finding import position...'
export const formatterStarted = 'Formatter started.'
export const foundBlankLine = (line: number) => `Found blank line at line ${line}`
export const foundImportPosition = (line: number) => `Found import at line ${line}`
export const killingCommand = (cmd: string) => `Killing \`\`${cmd}''...`
export const killingCommand = (cmd: string) => `Killing ${cmd}...`
export const languageClientStarted = 'Language client started.'
export const languageClientStopped = 'Language client stopped.'
export const makingImportSuggestion = (tag: any) => `Making import suggestion for ${JSON.stringify(tag)}`
export const makingImportSuggestion = (tag: any) => `Making import suggestion for tag: ${JSON.stringify(tag)}`
export const noBlankLineFound = 'No blank line found. Inserting import at start of file.'
export const noWorkspaceFolders = 'No workspace folders found. Cannot read fallback configuration.'
export const parsedTagLine = (tag: any) => `Parsed tag: ${JSON.stringify(tag)}`
export const parsingTagLine = (line: string) => `Parsing tag line: ${line}`
export const pickedSuggestion = (suggestion: any) => `Picked: ${JSON.stringify(suggestion)}`
export const providingCodeActions = 'Providing code actions...'
export const ranCommand = (cmd: string) => `Ran \`\`${cmd}''.`
export const readingFallbackConfig = (path: string) => `Reading fallback configuration from ${path}`
export const ranCommand = (cmd: string) => `Ran ${cmd}.`
export const readingFallbackConfig = (path: string) => `Reading fallback configuration from path: ${path}`
export const readingWorkspaceSettings = 'Reading configuration from workspace settings'
export const registeredCompletionsProvider = 'Registered completions provider.'
export const registeredDefinitionsProvider = 'Registered definitions provider.'
export const registeredImportsProvider = 'Registered imports provider.'
export const registeringCompletionsProvider = 'Registering completions provider...'
export const registeringDefinitionsProvider = 'Registering definitions provider...'
export const registeringImportsProvider = 'Registering imports provider...'
export const renderedImportLine = (line?: string) => `Rendered import: ${line}`
export const renderedImportLine = (line?: string) => `Rendered import line: ${line}`
export const renderedModuleName = (name?: string) => `Rendered module name: ${name}`
export const renderingImportLine = (tag: any) => `Rendering import line for ${JSON.stringify(tag)}`
export const renderingImportLine = (tag: any) => `Rendering import line for tag: ${JSON.stringify(tag)}`
export const restartingAlloglot = 'Restarting Alloglot...'
export const runningCommand = (cmd: string, cwd?: string) => `Running \`\`${cmd}'' in \`\`${cwd}''...`
export const runningCommand = (cmd: string, cwd?: string) => `Running ${cmd} in ${cwd}...`
export const runningSuggestImports = 'Running suggest imports...'
export const splittingOutputChannel = (name: string) => `Creating new output channel: ${name}`
export const startingAlloglot = 'Starting Alloglot...'
Expand All @@ -299,13 +316,14 @@ export namespace alloglot {
export const stoppingLanguageClient = 'Stopping language client...'
export const tagsStarted = 'Tags started.'
export const transformationResult = (x: string) => `Result: ${x}`
export const usingActivateCommandOutput = (channelId: string) => `Activation command stdout broadcasting to channel ${channelId}`
export const usingActivateCommandOutput = (channelId: string) => `Activation command stdout broadcasting to channel: ${channelId}`
export const usingConfig = (config: any) => `Using configuration:\n${JSON.stringify(config, null, 2)}`
export const usingFileMatcher = (matcher: any) => `File matcher: ${matcher}`
export const workspaceConfigExists = (exists: boolean) => `Configuration exists in settings: ${exists}`
}

export namespace collections {
const root = `${alloglot.root}.collections` as const
export const annotations = `${root}.annotations` as const
}

Expand All @@ -317,6 +335,7 @@ export namespace alloglot {
export const client = 'client' as const
export const tags = 'tags' as const
export const tagsSource = 'tagssource' as const
export const importsProvider = 'importsprovider' as const
}

export namespace commands {
Expand All @@ -331,5 +350,7 @@ export namespace alloglot {
export const fallbackPath = `.vscode/${root}.json` as const
export const languages = 'languages' as const
export const activateCommand = 'activateCommand' as const
export const deactivateCommand = 'deactivateCommand' as const
export const verboseOutput = 'verboseOutput' as const
}
}
Loading

0 comments on commit 458b45e

Please sign in to comment.