Skip to content

Commit

Permalink
refactor(vscode): add reactive config.
Browse files Browse the repository at this point in the history
  • Loading branch information
chizukicn committed Jul 4, 2023
1 parent 9f1e1ee commit 7da8fdc
Show file tree
Hide file tree
Showing 3 changed files with 134 additions and 68 deletions.
51 changes: 21 additions & 30 deletions packages/vscode/src/annotation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,42 +5,31 @@ import { INCLUDE_COMMENT_IDE, getMatchedPositionsFromCode, isCssId } from './int
import { log } from './log'
import { getColorString, getPrettiedMarkdown, isSubdir, throttle } from './utils'
import type { ContextLoader } from './contextLoader'
import { useConfiguration } from './configuration'

export async function registerAnnotations(
cwd: string,
contextLoader: ContextLoader,
status: StatusBarItem,
ext: ExtensionContext,
) {
let underline = workspace.getConfiguration().get('unocss.underline', true)
let colorPreview = workspace.getConfiguration().get('unocss.colorPreview', true)

let rootFontSize = workspace.getConfiguration().get('unocss.rootFontSize', 16)
let enableRemToPxPreview = workspace.getConfiguration().get('unocss.preview.remToPx', false)
const { configuration, watchChanged } = useConfiguration({
ext,
scope: 'unocss',
initialValue: {
underline: true,
colorPreview: true,
rootFontSize: 16,
enableRemToPxPreview: false,
},
alias: {
enableRemToPxPreview: 'preview.remToPx',
},
})

ext.subscriptions.push(workspace.onDidChangeConfiguration((event) => {
if (event.affectsConfiguration('unocss.underline')) {
underline = workspace.getConfiguration().get('unocss.underline', true)
updateAnnotation()
}
if (event.affectsConfiguration('unocss.colorPreview')) {
colorPreview = workspace.getConfiguration().get('unocss.colorPreview', true)
updateAnnotation()
}
if (event.affectsConfiguration('unocss.preview.remToPx')) {
enableRemToPxPreview = workspace.getConfiguration().get('unocss.preview.remToPx', false)
updateAnnotation()
}
if (enableRemToPxPreview) {
if (event.affectsConfiguration('unocss.rootFontSize')) {
rootFontSize = workspace.getConfiguration().get('unocss.rootFontSize', 16)
updateAnnotation()
}
}
else {
rootFontSize = -1
}
}))
watchChanged(['underline', 'colorPreview', 'enableRemToPxPreview', 'rootFontSize'], () => {
updateAnnotation()
})

workspace.onDidSaveTextDocument(async (doc) => {
const id = doc.uri.fsPath
Expand Down Expand Up @@ -121,14 +110,16 @@ export async function registerAnnotations(

const colorRanges: DecorationOptions[] = []

const rootFontSize = configuration.enableRemToPxPreview ? configuration.rootFontSize : -1

const ranges: DecorationOptions[] = (
await Promise.all(
(await getMatchedPositionsFromCode(ctx.uno, code))
.map(async (i): Promise<DecorationOptions> => {
try {
const md = await getPrettiedMarkdown(ctx!.uno, i[2], rootFontSize)

if (colorPreview) {
if (configuration.colorPreview) {
const color = getColorString(md)
if (color && !colorRanges.find(r => r.range.start.isEqual(doc.positionAt(i[0])))) {
colorRanges.push({
Expand All @@ -155,7 +146,7 @@ export async function registerAnnotations(

editor.setDecorations(colorDecoration, colorRanges)

if (underline) {
if (configuration.underline) {
editor.setDecorations(NoneDecoration, [])
editor.setDecorations(UnderlineDecoration, ranges)
}
Expand Down
72 changes: 34 additions & 38 deletions packages/vscode/src/autocomplete.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { getCSS, getColorString, getPrettiedCSS, getPrettiedMarkdown, isSubdir }
import { log } from './log'
import type { ContextLoader } from './contextLoader'
import { isCssId } from './integration'
import { useConfiguration } from './configuration'

const defaultLanguageIds = [
'erb',
Expand Down Expand Up @@ -59,21 +60,30 @@ export async function registerAutoComplete(
autoCompletes.delete(ctx)
})

let matchType = workspace.getConfiguration().get<AutoCompleteMatchType>('unocss.autocomplete.matchType', 'prefix')

let maxItems = workspace.getConfiguration().get('unocss.autocomplete.maxItems', 1000)

let rootFontSize = workspace.getConfiguration().get('unocss.rootFontSize', 16)

let enableRemToPxPreview = workspace.getConfiguration().get('unocss.preview.remToPx', false)
const { configuration, watchChanged } = useConfiguration({
ext,
scope: 'unocss',
initialValue: {
languagesIds: <string[]>[],
matchType: <AutoCompleteMatchType>'prefix',
maxItems: 1000,
rootFontSize: 16,
enableRemToPxPreview: false,
},
alias: {
enableRemToPxPreview: 'preview.remToPx',
matchType: 'autocomplete.matchType',
maxItems: 'autocomplete.maxItems',
},
})

function getAutocomplete(ctx: UnocssPluginContext) {
const cached = autoCompletes.get(ctx)
if (cached)
return cached

const autocomplete = createAutocomplete(ctx.uno, {
matchType,
matchType: configuration.matchType,
})

autoCompletes.set(ctx, autocomplete)
Expand Down Expand Up @@ -128,7 +138,7 @@ export async function registerAutoComplete(

const completionItems: UnoCompletionItem[] = []

const suggestions = result.suggestions.slice(0, maxItems)
const suggestions = result.suggestions.slice(0, configuration.maxItems)

for (const [value, label] of suggestions) {
const css = await getCSS(ctx!.uno, value)
Expand Down Expand Up @@ -157,6 +167,7 @@ export async function registerAutoComplete(
},

async resolveCompletionItem(item) {
const rootFontSize = configuration.rootFontSize ? configuration.rootFontSize : -1
if (item.kind === CompletionItemKind.Color)
item.detail = await (await getPrettiedCSS(item.uno, item.value, rootFontSize)).prettified
else
Expand All @@ -182,35 +193,20 @@ export async function registerAutoComplete(
return completeUnregister
}

ext.subscriptions.push(workspace.onDidChangeConfiguration(async (event) => {
if (event.affectsConfiguration('unocss.languageIds')) {
ext.subscriptions.push(
registerProvider(),
)
}
if (event.affectsConfiguration('unocss.autocomplete.matchType')) {
autoCompletes.clear()
matchType = workspace.getConfiguration().get<AutoCompleteMatchType>('unocss.autocomplete.matchType', 'prefix')
}
if (event.affectsConfiguration('unocss.autocomplete.maxItems')) {
autoCompletes.clear()
maxItems = workspace.getConfiguration().get<number>('unocss.autocomplete.maxItems', 1000)
}

if (event.affectsConfiguration('unocss.preview.remToPx')) {
autoCompletes.clear()
enableRemToPxPreview = workspace.getConfiguration().get('unocss.preview.remToPx', false)
}
if (enableRemToPxPreview) {
if (event.affectsConfiguration('unocss.rootFontSize')) {
autoCompletes.clear()
rootFontSize = workspace.getConfiguration().get('unocss.rootFontSize', 16)
}
}
else {
rootFontSize = -1
}
}))
watchChanged(['languagesIds'], () => {
ext.subscriptions.push(
registerProvider(),
)
})

watchChanged([
'matchType',
'maxItems',
'rootFontSize',
'enableRemToPxPreview',
], () => {
autoCompletes.clear()
})

ext.subscriptions.push(
registerProvider(),
Expand Down
79 changes: 79 additions & 0 deletions packages/vscode/src/configuration.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
import { toArray } from '@unocss/core'
import type { ExtensionContext } from 'vscode'
import { workspace } from 'vscode'
import { createNanoEvents } from '../../core/src/utils/events'

export interface UseConfigurationOptions<Init> {
ext?: ExtensionContext
scope?: string
initialValue: Init
alias?: Partial<Record<keyof Init, string>>
}

export type ConfigurationListenerMap<Init> = Map<keyof Init, WatchConfigurationHandler<Init, keyof Init>>

export type WatchConfigurationHandler<Init, K extends keyof Init> = (value: Init[K]) => void

export function useConfiguration<Init extends Record<string, unknown>>(options: UseConfigurationOptions<Init>) {
const { initialValue, alias, scope, ext } = options
const configuration = {} as Init

const getConfigurationKey = (key: keyof Init) => {
key = alias?.[key] ?? key
return [scope, key].filter(Boolean).join('.')
}

const reload = () => {
const _config = workspace.getConfiguration()
for (const key in initialValue) {
const configurationKey = getConfigurationKey(key)
configuration[key] = _config.get(configurationKey, initialValue[key])
}
}

const reset = () => {
const _config = workspace.getConfiguration()
for (const key in initialValue) {
configuration[key] = initialValue[key]
const configurationKey = getConfigurationKey(key)
_config.update(configurationKey, initialValue[key], true)
}
}

reload()

const emitter = createNanoEvents()

const watchChanged = <K extends keyof Init>(key: K | K[], fn: WatchConfigurationHandler<Init, K>) => {
const keys = toArray(key)
const unsubscribes = keys.map(key => emitter.on(`update:${String(key)}`, fn))
return () => unsubscribes.forEach(fn => fn())
}

const disposable = workspace.onDidChangeConfiguration((e) => {
const _config = workspace.getConfiguration()
const changedKeys = new Set<keyof Init>()

for (const key in initialValue) {
const configurationKey = getConfigurationKey(key)
if (e.affectsConfiguration(configurationKey)) {
const value = _config.get(configurationKey, initialValue[key])
configuration[key as keyof Init] = value as Init[keyof Init]
changedKeys.add(key)
}
}
for (const key of changedKeys)
emitter.emit(`update:${String(key)}`, configuration[key])
})

if (ext)
ext.subscriptions.push(disposable)

return {
configuration,
watchChanged,
disposable,
reload,
reset,
}
}

0 comments on commit 7da8fdc

Please sign in to comment.