Skip to content

Commit

Permalink
feat: document provider
Browse files Browse the repository at this point in the history
  • Loading branch information
antfu committed Dec 18, 2019
1 parent 7612964 commit e0b6ceb
Show file tree
Hide file tree
Showing 11 changed files with 128 additions and 91 deletions.
20 changes: 15 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,20 +18,30 @@
<a href="https://github.com/antfu/wenyan-lang-vscode" target="__blank"><img alt="GitHub stars" src="https://img.shields.io/github/stars/antfu/wenyan-lang-vscode?style=social"></a>
</p>

<p align="center">且未備,請見諒</p>

![](https://github.com/antfu/wenyan-lang-vscode/raw/master/screenshots/demo-highlight.png)

## Snippets
### Compile & Execute

Direct view the compiled Javascript or Execute it. (The [compiler](https://github.com/LingDong-/wenyan-lang/tree/master/build) is shipped with this extension, no installation required!)

![](https://github.com/antfu/wenyan-lang-vscode/raw/master/screenshots/demo-execute.png)


You can write 文言 very quick by snippets:
### Snippets

You can write Wenyan quickly by using snippets:

![](https://github.com/antfu/wenyan-lang-vscode/raw/master/screenshots/demo-snippets.gif)

Punctuation replacements are also avaliable (You will get the result immediately, the delay is added for demostraction purpose)

### Punctuations Replacement

Punctuations will be automatically replaced to fit the language.

![](https://github.com/antfu/wenyan-lang-vscode/raw/master/screenshots/demo-punctuations.gif)

*You will get the result immediately, the delay is added for demostraction purpose*


## ToDo

Expand Down
Binary file added screenshots/demo-execute.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
19 changes: 0 additions & 19 deletions src/commands/compile.ts

This file was deleted.

20 changes: 0 additions & 20 deletions src/commands/execute.ts

This file was deleted.

30 changes: 24 additions & 6 deletions src/commands/index.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,31 @@
import { commands } from 'vscode'
import path from 'path'
import { commands, window, Uri, workspace, ViewColumn } from 'vscode'
import { CommandKeys, LANG_ID, DOC_SCHEMA } from '../meta'
import { ExtensionModule } from '../module'
import { execute } from './execute'
import { CommandKeys } from './keys'
import { compile } from './compile'
import { documentProvider } from '../editor/documentProvider'

const m: ExtensionModule = () => {
return [
commands.registerCommand(CommandKeys.execute, execute),
commands.registerCommand(CommandKeys.compile, compile),
commands.registerCommand(CommandKeys.execute, async () => {
const document = window.activeTextEditor?.document
if (document?.languageId === LANG_ID) {
const { name } = path.parse(document.uri.fsPath)
const filename = `${name}(Output)`
const uri = Uri.parse(`${DOC_SCHEMA}:${filename}?action=execute&filepath=${encodeURIComponent(document.uri.fsPath)}`)
documentProvider.onDidChangeEmitter.fire(uri)
window.showTextDocument(await workspace.openTextDocument(uri), { preview: false, viewColumn: ViewColumn.Beside })
}
}),
commands.registerCommand(CommandKeys.compile, async () => {
const document = window.activeTextEditor?.document
if (document?.languageId === LANG_ID) {
const { name } = path.parse(document.uri.fsPath)
const filename = `${name}(Compiled).js`
const uri = Uri.parse(`${DOC_SCHEMA}:${filename}?action=compile&filepath=${encodeURIComponent(document.uri.fsPath)}`)
documentProvider.onDidChangeEmitter.fire(uri)
window.showTextDocument(await workspace.openTextDocument(uri), { preview: false, viewColumn: ViewColumn.Beside })
}
}),
]
}

Expand Down
10 changes: 0 additions & 10 deletions src/commands/output.ts

This file was deleted.

47 changes: 47 additions & 0 deletions src/editor/documentProvider.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import { TextDocumentContentProvider, Uri, workspace, EventEmitter } from 'vscode'
import prettier from 'prettier/standalone'
import parserBabel from 'prettier/parser-babylon'
import { parseQuery } from '../utils'
import { DOC_SCHEMA } from '../meta'
import { ExtensionModule } from '../module'
import { Exec } from '../exec'

async function getCompiledResult (filepath: string) {
const result = await Exec(filepath) || ''

return prettier.format(result, { semi: false, parser: 'babel', plugins: [parserBabel] })
}

async function getExecResult (filepath: string) {
const result = await Exec(filepath, { exec: true }) || ''

// remove first line or compiled code
return result.split('\n').slice(1).join('\n')
}

class DocumentProvider implements TextDocumentContentProvider {
onDidChangeEmitter = new EventEmitter<Uri>()
onDidChange = this.onDidChangeEmitter.event

async provideTextDocumentContent (uri: Uri) {
const query = parseQuery(uri.query)
const filepath = query.filepath
const action = query.action

if (!filepath || !action)
return ''

if (action === 'execute')
return await getExecResult(filepath)
if (action === 'compile')
return await getCompiledResult(filepath)
}
}

export const documentProvider = new DocumentProvider()

const m: ExtensionModule = () => {
return workspace.registerTextDocumentContentProvider(DOC_SCHEMA, documentProvider)
}

export default m
60 changes: 29 additions & 31 deletions src/editor/dynamicSnippets.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { window, Disposable, workspace, TextDocumentChangeEvent, Range, Position, Selection } from 'vscode'
import { window, workspace, TextDocumentChangeEvent, Range, Position, Selection } from 'vscode'
import { ExtensionModule } from '../module'
import DynamicSnippets from '../../snippets/dynamic.json'
import { LANG_ID } from '../meta'

const BODY_PARAMETER_REGEX = /\$\d+/g

Expand All @@ -22,46 +23,43 @@ function parseBody (body: string[]) {
return { parsed, shiftBack }
}

const dynamicSnippets: ExtensionModule = (ctx) => {
function update (e: TextDocumentChangeEvent) {
const editor = window.activeTextEditor
function onTextChanged (e: TextDocumentChangeEvent) {
const editor = window.activeTextEditor

const document = editor?.document
if (!editor || !document || document !== e.document)
return
const document = editor?.document
if (!editor || !document || document !== e.document)
return

if (document.languageId !== 'wenyan')
return
if (document.languageId !== LANG_ID)
return

if (!e.contentChanges[0])
return
if (!e.contentChanges[0])
return

const selection = editor.selection
const currentPosition = selection.start.translate(0, 1)
const selection = editor.selection
const currentPosition = selection.start.translate(0, 1)

const text = editor.document.getText(new Range(new Position(0, 0), currentPosition))
const text = editor.document.getText(new Range(new Position(0, 0), currentPosition))

for (const define of Object.values(DynamicSnippets)) {
for (const prefix of define.prefix) {
if (text.endsWith(prefix)) {
const range = new Range(currentPosition.translate(0, -prefix.length), currentPosition)
const { parsed, shiftBack } = parseBody(define.body)
for (const define of Object.values(DynamicSnippets)) {
for (const prefix of define.prefix) {
if (text.endsWith(prefix)) {
const range = new Range(currentPosition.translate(0, -prefix.length), currentPosition)
const { parsed, shiftBack } = parseBody(define.body)

editor.edit((editBuilder) => {
editBuilder.replace(range, parsed)
}).then(() => {
editor.selection = moveSelection(editor.selection, -shiftBack)
})
return
}
editor.edit((editBuilder) => {
editBuilder.replace(range, parsed)
}).then(() => {
editor.selection = moveSelection(editor.selection, -shiftBack)
})
return
}
}
}
}

const disposables: Disposable[] = []
disposables.push(workspace.onDidChangeTextDocument(e => update(e)))

return disposables
const m: ExtensionModule = () => {
return workspace.onDidChangeTextDocument(e => onTextChanged(e))
}

export default dynamicSnippets
export default m
2 changes: 2 additions & 0 deletions src/extension.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { ExtensionContext } from 'vscode'
import dynamicSnippets from './editor/dynamicSnippets'
import documentProvider from './editor/documentProvider'
import commands from './commands'
import { setCTX } from './ctx'

Expand All @@ -8,6 +9,7 @@ export function activate (ctx: ExtensionContext) {

const modules = [
dynamicSnippets,
documentProvider,
commands,
]

Expand Down
2 changes: 2 additions & 0 deletions src/commands/keys.ts → src/meta.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
export const DOC_SCHEMA = 'wenyan'
export const LANG_ID = 'wenyan'

export enum CommandKeys {
execute = 'extension.wenyan-lang.execute',
Expand Down
9 changes: 9 additions & 0 deletions src/utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
export function parseQuery (queryString: string) {
const query: Record<string, string> = {}
const pairs = (queryString[0] === '?' ? queryString.substr(1) : queryString).split('&')
for (let i = 0; i < pairs.length; i++) {
const pair = pairs[i].split('=')
query[decodeURIComponent(pair[0])] = decodeURIComponent(pair[1] || '')
}
return query
}

0 comments on commit e0b6ceb

Please sign in to comment.