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')
|
|
|
|
|
2022-02-18 10:16:48 +08:00
|
|
|
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)
|
2022-02-22 18:31:12 +08:00
|
|
|
return list.filter(it => !it.startsWith('.')).map(it => resolve(dir, it))
|
2022-02-16 19:20:15 +08:00
|
|
|
} catch (err) {
|
|
|
|
return []
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-02-17 12:26:37 +08:00
|
|
|
function getPrefixTxt(line, idx) {
|
|
|
|
var txt = line.slice(0, idx)
|
2023-02-14 22:50:08 +08:00
|
|
|
var n =
|
|
|
|
txt.lastIndexOf('"') > -1 ? txt.lastIndexOf('"') : txt.lastIndexOf("'")
|
2022-02-22 18:31:12 +08:00
|
|
|
var r
|
|
|
|
|
|
|
|
txt = txt.slice(n + 1)
|
|
|
|
if (txt) {
|
|
|
|
// 判断匹配前缀是否被包含在引号中
|
|
|
|
r = new RegExp(`(['"])${txt}\\1`)
|
|
|
|
|
|
|
|
if (r.test(line)) {
|
|
|
|
return txt
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return ''
|
2022-02-17 12:26:37 +08:00
|
|
|
}
|
|
|
|
|
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-03-10 09:27:20 +08:00
|
|
|
workspace: resolve('./'),
|
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-22 18:31:12 +08:00
|
|
|
var inputTxtTrim = inputTxt.trim()
|
|
|
|
|
|
|
|
// console.log('原始inputTxt >>>> ', inputTxt)
|
|
|
|
|
|
|
|
/**
|
|
|
|
* 过滤掉 以下几种情况
|
|
|
|
* @1 在注释后面的
|
|
|
|
* @2 当前光标在行末的
|
|
|
|
* @3 匹配前缀在行首的
|
|
|
|
*/
|
|
|
|
if (
|
|
|
|
inputTxtTrim.startsWith('// ') ||
|
|
|
|
inputTxtTrim.startsWith('/* ') ||
|
|
|
|
inputTxtTrim.startsWith('# ') ||
|
|
|
|
inputTxtTrim.startsWith('./') ||
|
|
|
|
inputTxtTrim.startsWith('../') ||
|
|
|
|
inputTxtTrim.startsWith('/') ||
|
|
|
|
inputTxtTrim.length === pos.character
|
|
|
|
) {
|
|
|
|
return
|
|
|
|
}
|
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-03-17 14:51:42 +08:00
|
|
|
// console.log('修正后的inputTxt: ', inputTxt, currDirFixed)
|
2022-02-22 18:31:12 +08:00
|
|
|
|
2022-02-17 12:26:37 +08:00
|
|
|
if (!inputTxt) {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2022-02-18 10:16:48 +08:00
|
|
|
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))
|
2022-03-17 14:51:42 +08:00
|
|
|
} else if (inputTxt.startsWith('~')) {
|
|
|
|
currDirFixed = inputTxt.replace(/^~/, process.env.HOME)
|
|
|
|
list.push(...ls(currDirFixed))
|
2022-02-17 12:26:37 +08:00
|
|
|
}
|
|
|
|
// 其他的
|
|
|
|
else {
|
|
|
|
currDirFixed = join(options.workspace, inputTxt)
|
|
|
|
list.push(...ls(currDirFixed))
|
|
|
|
}
|
2022-02-16 19:20:15 +08:00
|
|
|
}
|
|
|
|
|
2022-03-10 09:27:20 +08:00
|
|
|
// console.log('currDirFixed: ', options, currDirFixed, list)
|
|
|
|
|
2022-02-18 10:16:48 +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-22 18:31:12 +08:00
|
|
|
if (list.length) {
|
|
|
|
list.unshift(item('', FILE, pos))
|
|
|
|
return Promise.resolve(list)
|
|
|
|
}
|
2022-02-16 19:20:15 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function __init__() {
|
|
|
|
let folders = vsc.workspace.workspaceFolders
|
|
|
|
|
2022-03-17 14:51:42 +08:00
|
|
|
// console.log(folders)
|
|
|
|
|
2022-02-16 19:20:15 +08:00
|
|
|
if (folders && folders.length) {
|
2022-03-11 18:09:06 +08:00
|
|
|
options.workspace = folders[0].uri.fsPath
|
2022-02-16 19:20:15 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
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项目
|
2022-02-18 10:16:48 +08:00
|
|
|
if (isfile(join(options.workspace, 'package.json'))) {
|
|
|
|
let conf = require(join(options.workspace, 'package.json'))
|
2023-02-14 22:50:08 +08:00
|
|
|
if (
|
|
|
|
(conf.dependencies && conf.dependencies.vue) ||
|
|
|
|
(conf.devDependencies && conf.devDependencies['@bytedo/vue-live'])
|
|
|
|
) {
|
2022-02-18 10:16:48 +08:00
|
|
|
let extendWorkspace = join(options.workspace, 'src/')
|
|
|
|
if (isdir(extendWorkspace)) {
|
|
|
|
options.extendWorkspace = extendWorkspace
|
|
|
|
}
|
2022-02-16 19:20:15 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-03-17 14:51:42 +08:00
|
|
|
exports.activate = function (ctx) {
|
2022-02-16 19:20:15 +08:00
|
|
|
__init__()
|
|
|
|
|
|
|
|
let ap = new AutoPath()
|
2023-02-14 22:50:08 +08:00
|
|
|
let auto = vsc.languages.registerCompletionItemProvider(
|
|
|
|
'*',
|
|
|
|
ap,
|
|
|
|
'"',
|
|
|
|
"'",
|
|
|
|
'/'
|
|
|
|
)
|
2022-02-16 19:20:15 +08:00
|
|
|
|
|
|
|
ctx.subscriptions.push(auto)
|
|
|
|
}
|
|
|
|
|
2022-03-17 14:51:42 +08:00
|
|
|
exports.deactivate = function () {}
|