auto-path/index.js

159 lines
3.7 KiB
JavaScript
Raw Normal View History

2022-02-16 19:20:15 +08:00
/**
*
* @author yutent<yutent.io@gmail.com>
* @date 2018/11/01 09:37:55
*/
const vsc = require('vscode')
const { resolve, dirname, join } = require('path')
const fs = require('fs')
const FILE = vsc.CompletionItemKind.File
2022-02-16 19:20:15 +08:00
const FOLDER = vsc.CompletionItemKind.Folder
/**
* [isdir 判断目标是否为目录]
*/
function isdir(path) {
try {
return fs.statSync(path).isDirectory()
} catch (err) {
return false
}
}
function isfile(path) {
try {
return fs.statSync(path).isFile()
} catch (err) {
return false
}
}
/**
* 列出目录
*/
function ls(dir) {
try {
var list = fs.readdirSync(dir)
return list.map(it => resolve(dir, it))
} catch (err) {
return []
}
}
2022-02-17 12:26:37 +08:00
function getPrefixTxt(line, idx) {
var txt = line.slice(0, idx)
var n = txt.lastIndexOf('"') > -1 ? txt.lastIndexOf('"') : txt.lastIndexOf("'")
return txt.slice(n + 1)
}
2022-02-17 14:53:09 +08:00
function item(text, type, p) {
var _ = new vsc.CompletionItem(text, type)
_.range = new vsc.Range(p, p)
return _
}
2022-02-16 19:20:15 +08:00
let options = {
isMiniApp: false, // 是否小程序
2022-02-17 12:26:37 +08:00
extendWorkspace: null // 额外的项目目录, 一般是 vue项目中的 src目录
2022-02-16 19:20:15 +08:00
}
class AutoPath {
provideCompletionItems(doc, pos) {
var currDir = dirname(doc.fileName)
2022-02-17 12:26:37 +08:00
var inputTxt = doc.lineAt(pos).text // 获取光标所在的整行代码
2022-02-16 19:20:15 +08:00
var list = []
2022-02-17 12:26:37 +08:00
var currDirFixed = ''
2022-02-16 19:20:15 +08:00
2022-02-17 12:26:37 +08:00
inputTxt = getPrefixTxt(inputTxt, pos.character)
2022-02-16 19:20:15 +08:00
currDirFixed = join(currDir, inputTxt)
2022-02-17 12:26:37 +08:00
if (!inputTxt) {
return
}
if (inputTxt.startsWith('./') || inputTxt.startsWith('../')) {
2022-02-16 19:20:15 +08:00
list.push(...ls(currDirFixed))
} else {
2022-02-17 12:26:37 +08:00
// 小程序
if (options.isMiniApp) {
2022-02-17 13:25:27 +08:00
let conf = require(join(options.workspace, 'app.json'))
list = conf.pages.map(it => `/${it}`)
if (conf.subPackages && conf.subPackages.length) {
for (let it of conf.subPackages) {
list.push(...it.pages.map(p => '/' + it.root + p))
}
}
2022-02-17 12:26:37 +08:00
currDirFixed = inputTxt
2022-02-17 13:25:27 +08:00
list = list.filter(it => it.startsWith(inputTxt))
2022-02-17 12:26:37 +08:00
}
// vue项目
else if (inputTxt.startsWith('@/') && options.extendWorkspace) {
currDirFixed = join(options.extendWorkspace, inputTxt.slice(2))
list.push(...ls(currDirFixed))
}
// 其他的
else {
currDirFixed = join(options.workspace, inputTxt)
list.push(...ls(currDirFixed))
}
2022-02-16 19:20:15 +08:00
}
list = list
.filter(it => it !== doc.fileName)
.map(k => {
let t = options.isMiniApp ? FILE : isdir(k) ? FOLDER : FILE
k = k.slice(currDirFixed.length)
return item(k, t, pos)
})
2022-02-17 14:53:09 +08:00
list.unshift(item('', FILE, pos))
2022-02-16 19:20:15 +08:00
return Promise.resolve(list)
}
}
function __init__() {
let folders = vsc.workspace.workspaceFolders
if (folders && folders.length) {
options.workspace = folders[0].uri.path
}
if (options.workspace) {
2022-02-17 13:25:27 +08:00
// 判断是否是小程序
if (isfile(join(options.workspace, 'app.json'))) {
let conf = require(join(options.workspace, 'app.json'))
if (conf.pages && conf.pages.length) {
options.isMiniApp = true
return
2022-02-17 12:26:37 +08:00
}
2022-02-17 13:25:27 +08:00
}
// 简单判断是否是vue项目
if (isfile(join(options.workspace, 'package.json'))) {
let conf = require(join(options.workspace, 'package.json'))
if (conf.dependencies.vue) {
let extendWorkspace = join(options.workspace, 'src/')
if (isdir(extendWorkspace)) {
options.extendWorkspace = extendWorkspace
}
2022-02-16 19:20:15 +08:00
}
}
}
}
exports.activate = function(ctx) {
__init__()
let ap = new AutoPath()
let auto = vsc.languages.registerCompletionItemProvider('*', ap, '"', "'", '/')
ctx.subscriptions.push(auto)
}
2022-02-17 12:26:37 +08:00
exports.deactivate = function() {}