format
Some checks failed
Testing / Test (push) Has been cancelled

This commit is contained in:
Michael Zhang 2024-12-08 19:43:18 -06:00
parent 223ae3ea9a
commit 391d8a1beb
12 changed files with 465 additions and 278 deletions

3
.vscode/settings.json vendored Normal file
View file

@ -0,0 +1,3 @@
{
"editor.defaultFormatter": "biomejs.biome"
}

30
biome.json Normal file
View file

@ -0,0 +1,30 @@
{
"$schema": "https://biomejs.dev/schemas/1.9.4/schema.json",
"vcs": {
"enabled": false,
"clientKind": "git",
"useIgnoreFile": false
},
"files": {
"ignoreUnknown": false,
"ignore": []
},
"formatter": {
"enabled": true,
"indentStyle": "tab"
},
"organizeImports": {
"enabled": true
},
"linter": {
"enabled": true,
"rules": {
"recommended": true
}
},
"javascript": {
"formatter": {
"quoteStyle": "double"
}
}
}

BIN
bun.lockb Executable file

Binary file not shown.

View file

@ -19,15 +19,11 @@
"main": "./dist/extension", "main": "./dist/extension",
"scripts": { "scripts": {
"build": "npm run lint && webpack --mode production", "build": "npm run lint && webpack --mode production",
"lint": "prettier --check . && eslint src --ext mjs,js,ts", "lint": "npx @biomejs/biome check",
"format": "prettier --write . && eslint src --ext mjs,js,ts --fix" "format": "npx @biomejs/biome format --write"
}, },
"activationEvents": [ "activationEvents": ["*"],
"*" "extensionKind": ["ui"],
],
"extensionKind": [
"ui"
],
"contributes": { "contributes": {
"commands": [ "commands": [
{ {
@ -165,17 +161,8 @@
"bugs": { "bugs": {
"url": "https://github.com/iCrawl/discord-vscode/issues" "url": "https://github.com/iCrawl/discord-vscode/issues"
}, },
"keywords": [ "keywords": ["discord", "vscode", "rich", "presence", "rich presence", "rpc"],
"discord", "categories": ["Other"],
"vscode",
"rich",
"presence",
"rich presence",
"rpc"
],
"categories": [
"Other"
],
"homepage": "https://github.com/iCrawl/discord-vscode#readme", "homepage": "https://github.com/iCrawl/discord-vscode#readme",
"icon": "assets/icon.png", "icon": "assets/icon.png",
"galleryBanner": { "galleryBanner": {
@ -191,6 +178,7 @@
"utf-8-validate": "^5.0.9" "utf-8-validate": "^5.0.9"
}, },
"devDependencies": { "devDependencies": {
"@biomejs/biome": "^1.9.4",
"@types/lodash-es": "^4.17.6", "@types/lodash-es": "^4.17.6",
"@types/node": "^17.0.41", "@types/node": "^17.0.41",
"@types/vscode": "^1.67.0", "@types/vscode": "^1.67.0",

View file

@ -1,5 +1,12 @@
import { basename, parse, sep } from 'path'; import { basename, parse, sep } from "node:path";
import { debug, env, Selection, TextDocument, window, workspace } from 'vscode'; import {
type Selection,
type TextDocument,
debug,
env,
window,
workspace,
} from "vscode";
import { import {
CONFIG_KEYS, CONFIG_KEYS,
@ -13,9 +20,16 @@ import {
UNKNOWN_GIT_REPO_NAME, UNKNOWN_GIT_REPO_NAME,
VSCODE_IMAGE_KEY, VSCODE_IMAGE_KEY,
VSCODE_INSIDERS_IMAGE_KEY, VSCODE_INSIDERS_IMAGE_KEY,
} from './constants'; } from "./constants";
import { log, LogLevel } from './logger'; import { LogLevel, log } from "./logger";
import { getConfig, getGit, resolveFileIcon, toLower, toTitle, toUpper } from './util'; import {
getConfig,
getGit,
resolveFileIcon,
toLower,
toTitle,
toUpper,
} from "./util";
interface ActivityPayload { interface ActivityPayload {
details?: string | undefined; details?: string | undefined;
@ -35,19 +49,32 @@ interface ActivityPayload {
instance?: boolean | undefined; instance?: boolean | undefined;
} }
async function fileDetails(_raw: string, document: TextDocument, selection: Selection) { async function fileDetails(
_raw: string,
document: TextDocument,
selection: Selection,
) {
let raw = _raw.slice(); let raw = _raw.slice();
if (raw.includes(REPLACE_KEYS.TotalLines)) { if (raw.includes(REPLACE_KEYS.TotalLines)) {
raw = raw.replace(REPLACE_KEYS.TotalLines, document.lineCount.toLocaleString()); raw = raw.replace(
REPLACE_KEYS.TotalLines,
document.lineCount.toLocaleString(),
);
} }
if (raw.includes(REPLACE_KEYS.CurrentLine)) { if (raw.includes(REPLACE_KEYS.CurrentLine)) {
raw = raw.replace(REPLACE_KEYS.CurrentLine, (selection.active.line + 1).toLocaleString()); raw = raw.replace(
REPLACE_KEYS.CurrentLine,
(selection.active.line + 1).toLocaleString(),
);
} }
if (raw.includes(REPLACE_KEYS.CurrentColumn)) { if (raw.includes(REPLACE_KEYS.CurrentColumn)) {
raw = raw.replace(REPLACE_KEYS.CurrentColumn, (selection.active.character + 1).toLocaleString()); raw = raw.replace(
REPLACE_KEYS.CurrentColumn,
(selection.active.character + 1).toLocaleString(),
);
} }
if (raw.includes(REPLACE_KEYS.FileSize)) { if (raw.includes(REPLACE_KEYS.FileSize)) {
@ -70,7 +97,9 @@ async function fileDetails(_raw: string, document: TextDocument, selection: Sele
raw = raw.replace( raw = raw.replace(
REPLACE_KEYS.FileSize, REPLACE_KEYS.FileSize,
`${originalSize > 1000 ? size.toFixed(2) : size}${FILE_SIZES[currentDivision]}`, `${originalSize > 1000 ? size.toFixed(2) : size}${
FILE_SIZES[currentDivision]
}`,
); );
} }
@ -80,7 +109,8 @@ async function fileDetails(_raw: string, document: TextDocument, selection: Sele
if (git?.repositories.length) { if (git?.repositories.length) {
raw = raw.replace( raw = raw.replace(
REPLACE_KEYS.GitBranch, REPLACE_KEYS.GitBranch,
git.repositories.find((repo) => repo.ui.selected)?.state.HEAD?.name ?? FAKE_EMPTY, git.repositories.find((repo) => repo.ui.selected)?.state.HEAD?.name ??
FAKE_EMPTY,
); );
} else { } else {
raw = raw.replace(REPLACE_KEYS.GitBranch, UNKNOWN_GIT_BRANCH); raw = raw.replace(REPLACE_KEYS.GitBranch, UNKNOWN_GIT_BRANCH);
@ -93,8 +123,8 @@ async function fileDetails(_raw: string, document: TextDocument, selection: Sele
REPLACE_KEYS.GitRepoName, REPLACE_KEYS.GitRepoName,
git.repositories git.repositories
.find((repo) => repo.ui.selected) .find((repo) => repo.ui.selected)
?.state.remotes[0].fetchUrl?.split('/')[1] ?.state.remotes[0].fetchUrl?.split("/")[1]
.replace('.git', '') ?? FAKE_EMPTY, .replace(".git", "") ?? FAKE_EMPTY,
); );
} else { } else {
raw = raw.replace(REPLACE_KEYS.GitRepoName, UNKNOWN_GIT_REPO_NAME); raw = raw.replace(REPLACE_KEYS.GitRepoName, UNKNOWN_GIT_REPO_NAME);
@ -104,7 +134,11 @@ async function fileDetails(_raw: string, document: TextDocument, selection: Sele
return raw; return raw;
} }
async function details(idling: CONFIG_KEYS, editing: CONFIG_KEYS, debugging: CONFIG_KEYS) { async function details(
idling: CONFIG_KEYS,
editing: CONFIG_KEYS,
debugging: CONFIG_KEYS,
) {
const config = getConfig(); const config = getConfig();
let raw = (config[idling] as string).replace(REPLACE_KEYS.Empty, FAKE_EMPTY); let raw = (config[idling] as string).replace(REPLACE_KEYS.Empty, FAKE_EMPTY);
@ -114,12 +148,18 @@ async function details(idling: CONFIG_KEYS, editing: CONFIG_KEYS, debugging: CON
const split = dir.split(sep); const split = dir.split(sep);
const dirName = split[split.length - 1]; const dirName = split[split.length - 1];
const noWorkspaceFound = config[CONFIG_KEYS.LowerDetailsNoWorkspaceFound].replace(REPLACE_KEYS.Empty, FAKE_EMPTY); const noWorkspaceFound = config[
const workspaceFolder = workspace.getWorkspaceFolder(window.activeTextEditor.document.uri); CONFIG_KEYS.LowerDetailsNoWorkspaceFound
].replace(REPLACE_KEYS.Empty, FAKE_EMPTY);
const workspaceFolder = workspace.getWorkspaceFolder(
window.activeTextEditor.document.uri,
);
const workspaceFolderName = workspaceFolder?.name ?? noWorkspaceFound; const workspaceFolderName = workspaceFolder?.name ?? noWorkspaceFound;
const workspaceName = workspace.name?.replace(REPLACE_KEYS.VSCodeWorkspace, EMPTY) ?? workspaceFolderName; const workspaceName =
workspace.name?.replace(REPLACE_KEYS.VSCodeWorkspace, EMPTY) ??
workspaceFolderName;
const workspaceAndFolder = `${workspaceName}${ const workspaceAndFolder = `${workspaceName}${
workspaceFolderName === FAKE_EMPTY ? '' : ` - ${workspaceFolderName}` workspaceFolderName === FAKE_EMPTY ? "" : ` - ${workspaceFolderName}`
}`; }`;
const fileIcon = resolveFileIcon(window.activeTextEditor.document); const fileIcon = resolveFileIcon(window.activeTextEditor.document);
@ -132,15 +172,27 @@ async function details(idling: CONFIG_KEYS, editing: CONFIG_KEYS, debugging: CON
if (workspaceFolder) { if (workspaceFolder) {
const { name } = workspaceFolder; const { name } = workspaceFolder;
const relativePath = workspace.asRelativePath(window.activeTextEditor.document.fileName).split(sep); const relativePath = workspace
.asRelativePath(window.activeTextEditor.document.fileName)
.split(sep);
relativePath.splice(-1, 1); relativePath.splice(-1, 1);
raw = raw.replace(REPLACE_KEYS.FullDirName, `${name}${sep}${relativePath.join(sep)}`); raw = raw.replace(
REPLACE_KEYS.FullDirName,
`${name}${sep}${relativePath.join(sep)}`,
);
} }
try { try {
raw = await fileDetails(raw, window.activeTextEditor.document, window.activeTextEditor.selection); raw = await fileDetails(
raw,
window.activeTextEditor.document,
window.activeTextEditor.selection,
);
} catch (error) { } catch (error) {
log(LogLevel.Error, `Failed to generate file details: ${error as string}`); log(
LogLevel.Error,
`Failed to generate file details: ${error as string}`,
);
} }
raw = raw raw = raw
.replace(REPLACE_KEYS.FileName, fileName) .replace(REPLACE_KEYS.FileName, fileName)
@ -163,10 +215,13 @@ export async function activity(previous: ActivityPayload = {}) {
const appName = env.appName; const appName = env.appName;
const defaultSmallImageKey = debug.activeDebugSession const defaultSmallImageKey = debug.activeDebugSession
? DEBUG_IMAGE_KEY ? DEBUG_IMAGE_KEY
: appName.includes('Insiders') : appName.includes("Insiders")
? VSCODE_INSIDERS_IMAGE_KEY ? VSCODE_INSIDERS_IMAGE_KEY
: VSCODE_IMAGE_KEY; : VSCODE_IMAGE_KEY;
const defaultSmallImageText = config[CONFIG_KEYS.SmallImage].replace(REPLACE_KEYS.AppName, appName); const defaultSmallImageText = config[CONFIG_KEYS.SmallImage].replace(
REPLACE_KEYS.AppName,
appName,
);
const defaultLargeImageText = config[CONFIG_KEYS.LargeImageIdling]; const defaultLargeImageText = config[CONFIG_KEYS.LargeImageIdling];
const removeDetails = config[CONFIG_KEYS.RemoveDetails]; const removeDetails = config[CONFIG_KEYS.RemoveDetails];
const removeLowerDetails = config[CONFIG_KEYS.RemoveLowerDetails]; const removeLowerDetails = config[CONFIG_KEYS.RemoveLowerDetails];
@ -177,8 +232,14 @@ export async function activity(previous: ActivityPayload = {}) {
let state: ActivityPayload = { let state: ActivityPayload = {
details: removeDetails details: removeDetails
? undefined ? undefined
: await details(CONFIG_KEYS.DetailsIdling, CONFIG_KEYS.DetailsEditing, CONFIG_KEYS.DetailsDebugging), : await details(
startTimestamp: config[CONFIG_KEYS.RemoveTimestamp] ? undefined : previous.startTimestamp ?? Date.now(), CONFIG_KEYS.DetailsIdling,
CONFIG_KEYS.DetailsEditing,
CONFIG_KEYS.DetailsDebugging,
),
startTimestamp: config[CONFIG_KEYS.RemoveTimestamp]
? undefined
: (previous.startTimestamp ?? Date.now()),
largeImageKey: IDLE_IMAGE_KEY, largeImageKey: IDLE_IMAGE_KEY,
largeImageText: defaultLargeImageText, largeImageText: defaultLargeImageText,
smallImageKey: defaultSmallImageKey, smallImageKey: defaultSmallImageKey,
@ -196,18 +257,25 @@ export async function activity(previous: ActivityPayload = {}) {
} }
if (!removeRemoteRepository && git?.repositories.length) { if (!removeRemoteRepository && git?.repositories.length) {
let repo = git.repositories.find((repo) => repo.ui.selected)?.state.remotes[0]?.fetchUrl; let repo = git.repositories.find((repo) => repo.ui.selected)?.state
.remotes[0]?.fetchUrl;
if (repo) { if (repo) {
if (repo.startsWith('git@') || repo.startsWith('ssh://')) { if (repo.startsWith("git@") || repo.startsWith("ssh://")) {
repo = repo.replace('ssh://', '').replace(':', '/').replace('git@', 'https://').replace('.git', ''); repo = repo
.replace("ssh://", "")
.replace(":", "/")
.replace("git@", "https://")
.replace(".git", "");
} else { } else {
repo = repo.replace(/(https:\/\/)([^@]*)@(.*?$)/, '$1$3').replace('.git', ''); repo = repo
.replace(/(https:\/\/)([^@]*)@(.*?$)/, "$1$3")
.replace(".git", "");
} }
state = { state = {
...state, ...state,
buttons: [{ label: 'View Repository', url: repo }], buttons: [{ label: "View Repository", url: repo }],
}; };
} }
} }
@ -224,7 +292,11 @@ export async function activity(previous: ActivityPayload = {}) {
...state, ...state,
details: removeDetails details: removeDetails
? undefined ? undefined
: await details(CONFIG_KEYS.DetailsIdling, CONFIG_KEYS.DetailsEditing, CONFIG_KEYS.DetailsDebugging), : await details(
CONFIG_KEYS.DetailsIdling,
CONFIG_KEYS.DetailsEditing,
CONFIG_KEYS.DetailsDebugging,
),
state: removeLowerDetails state: removeLowerDetails
? undefined ? undefined
: await details( : await details(
@ -248,7 +320,10 @@ export async function activity(previous: ActivityPayload = {}) {
}; };
} }
log(LogLevel.Trace, `VSCode language id: ${window.activeTextEditor.document.languageId}`); log(
LogLevel.Trace,
`VSCode language id: ${window.activeTextEditor.document.languageId}`,
);
} }
return state; return state;

View file

@ -1,61 +1,63 @@
import LANG from './data/languages.json'; import LANG from "./data/languages.json";
export const CLIENT_ID = '383226320970055681' as const; export const CLIENT_ID = "383226320970055681" as const;
export const KNOWN_EXTENSIONS: { [key: string]: { image: string } } = LANG.KNOWN_EXTENSIONS; export const KNOWN_EXTENSIONS: { [key: string]: { image: string } } =
export const KNOWN_LANGUAGES: { language: string; image: string }[] = LANG.KNOWN_LANGUAGES; LANG.KNOWN_EXTENSIONS;
export const KNOWN_LANGUAGES: { language: string; image: string }[] =
LANG.KNOWN_LANGUAGES;
export const EMPTY = '' as const; export const EMPTY = "" as const;
export const FAKE_EMPTY = '\u200b\u200b' as const; export const FAKE_EMPTY = "\u200b\u200b" as const;
export const FILE_SIZES = [' bytes', 'KB', 'MB', 'GB', 'TB'] as const; export const FILE_SIZES = [" bytes", "KB", "MB", "GB", "TB"] as const;
export const IDLE_IMAGE_KEY = 'vscode-big' as const; export const IDLE_IMAGE_KEY = "vscode-big" as const;
export const DEBUG_IMAGE_KEY = 'debug' as const; export const DEBUG_IMAGE_KEY = "debug" as const;
export const VSCODE_IMAGE_KEY = 'vscode' as const; export const VSCODE_IMAGE_KEY = "vscode" as const;
export const VSCODE_INSIDERS_IMAGE_KEY = 'vscode-insiders' as const; export const VSCODE_INSIDERS_IMAGE_KEY = "vscode-insiders" as const;
export const UNKNOWN_GIT_BRANCH = 'Unknown' as const; export const UNKNOWN_GIT_BRANCH = "Unknown" as const;
export const UNKNOWN_GIT_REPO_NAME = 'Unknown' as const; export const UNKNOWN_GIT_REPO_NAME = "Unknown" as const;
export const enum REPLACE_KEYS { export enum REPLACE_KEYS {
Empty = '{empty}', Empty = "{empty}",
FileName = '{file_name}', FileName = "{file_name}",
DirName = '{dir_name}', DirName = "{dir_name}",
FullDirName = '{full_dir_name}', FullDirName = "{full_dir_name}",
Workspace = '{workspace}', Workspace = "{workspace}",
VSCodeWorkspace = '(Workspace)', VSCodeWorkspace = "(Workspace)",
WorkspaceFolder = '{workspace_folder}', WorkspaceFolder = "{workspace_folder}",
WorkspaceAndFolder = '{workspace_and_folder}', WorkspaceAndFolder = "{workspace_and_folder}",
LanguageLowerCase = '{lang}', LanguageLowerCase = "{lang}",
LanguageTitleCase = '{Lang}', LanguageTitleCase = "{Lang}",
LanguageUpperCase = '{LANG}', LanguageUpperCase = "{LANG}",
TotalLines = '{total_lines}', TotalLines = "{total_lines}",
CurrentLine = '{current_line}', CurrentLine = "{current_line}",
CurrentColumn = '{current_column}', CurrentColumn = "{current_column}",
FileSize = '{file_size}', FileSize = "{file_size}",
AppName = '{app_name}', AppName = "{app_name}",
GitRepoName = '{git_repo_name}', GitRepoName = "{git_repo_name}",
GitBranch = '{git_branch}', GitBranch = "{git_branch}",
} }
export const enum CONFIG_KEYS { export enum CONFIG_KEYS {
Enabled = 'enabled', Enabled = "enabled",
DetailsIdling = 'detailsIdling', DetailsIdling = "detailsIdling",
DetailsEditing = 'detailsEditing', DetailsEditing = "detailsEditing",
DetailsDebugging = 'detailsDebugging', DetailsDebugging = "detailsDebugging",
LowerDetailsIdling = 'lowerDetailsIdling', LowerDetailsIdling = "lowerDetailsIdling",
LowerDetailsEditing = 'lowerDetailsEditing', LowerDetailsEditing = "lowerDetailsEditing",
LowerDetailsDebugging = 'lowerDetailsDebugging', LowerDetailsDebugging = "lowerDetailsDebugging",
LowerDetailsNoWorkspaceFound = 'lowerDetailsNoWorkspaceFound', LowerDetailsNoWorkspaceFound = "lowerDetailsNoWorkspaceFound",
LargeImageIdling = 'largeImageIdling', LargeImageIdling = "largeImageIdling",
LargeImage = 'largeImage', LargeImage = "largeImage",
SmallImage = 'smallImage', SmallImage = "smallImage",
SuppressNotifications = 'suppressNotifications', SuppressNotifications = "suppressNotifications",
WorkspaceExcludePatterns = 'workspaceExcludePatterns', WorkspaceExcludePatterns = "workspaceExcludePatterns",
SwapBigAndSmallImage = 'swapBigAndSmallImage', SwapBigAndSmallImage = "swapBigAndSmallImage",
RemoveDetails = 'removeDetails', RemoveDetails = "removeDetails",
RemoveLowerDetails = 'removeLowerDetails', RemoveLowerDetails = "removeLowerDetails",
RemoveTimestamp = 'removeTimestamp', RemoveTimestamp = "removeTimestamp",
RemoveRemoteRepository = 'removeRemoteRepository', RemoveRemoteRepository = "removeRemoteRepository",
IdleTimeout = 'idleTimeout', IdleTimeout = "idleTimeout",
} }

View file

@ -82,11 +82,15 @@
".asmx": { "image": "asp" }, ".asmx": { "image": "asp" },
".aspx": { "image": "asp" }, ".aspx": { "image": "asp" },
".axd": { "image": "asp" }, ".axd": { "image": "asp" },
"/\\.(l?a|[ls]?o|out|s|a51|asm|axf|elf|prx|puff|z80)$/i": { "image": "assembly" }, "/\\.(l?a|[ls]?o|out|s|a51|asm|axf|elf|prx|puff|z80)$/i": {
"image": "assembly"
},
".agc": { "image": "assembly" }, ".agc": { "image": "assembly" },
".ko": { "image": "assembly" }, ".ko": { "image": "assembly" },
".lst": { "image": "assembly" }, ".lst": { "image": "assembly" },
"/\\.((c([+px]{2}?)?-?)?objdump|bsdiff|bin|dat|pak|pdb)$/i": { "image": "assembly" }, "/\\.((c([+px]{2}?)?-?)?objdump|bsdiff|bin|dat|pak|pdb)$/i": {
"image": "assembly"
},
".d-objdump": { "image": "assembly" }, ".d-objdump": { "image": "assembly" },
"/\\.gcode|\\.gco/i": { "image": "assembly" }, "/\\.gcode|\\.gco/i": { "image": "assembly" },
"/\\.rpy[bc]$/i": { "image": "assembly" }, "/\\.rpy[bc]$/i": { "image": "assembly" },
@ -150,7 +154,9 @@
".dm": { "image": "dm" }, ".dm": { "image": "dm" },
".dme": { "image": "dm" }, ".dme": { "image": "dm" },
".dmm": { "image": "dm" }, ".dmm": { "image": "dm" },
"/^(Dockerfile|docker-compose)|\\.docker(file|ignore)$/i": { "image": "docker" }, "/^(Dockerfile|docker-compose)|\\.docker(file|ignore)$/i": {
"image": "docker"
},
"/^docker-sync\\.yml$/i": { "image": "docker" }, "/^docker-sync\\.yml$/i": { "image": "docker" },
".editorconfig": { "image": "editorconfig" }, ".editorconfig": { "image": "editorconfig" },
".ejs": { "image": "ejs" }, ".ejs": { "image": "ejs" },
@ -274,13 +280,19 @@
"/^pkginfo$/": { "image": "manifest" }, "/^pkginfo$/": { "image": "manifest" },
"/^mime\\.types$/i": { "image": "manifest" }, "/^mime\\.types$/i": { "image": "manifest" },
"/^METADATA\\.pb$/": { "image": "manifest" }, "/^METADATA\\.pb$/": { "image": "manifest" },
"/[\\/\\\\](?:magic[\\/\\\\]Magdir|file[\\/\\\\]magic)[\\/\\\\][-.\\w]+$/i": { "image": "manifest" }, "/[\\/\\\\](?:magic[\\/\\\\]Magdir|file[\\/\\\\]magic)[\\/\\\\][-.\\w]+$/i": {
"/(\\\\|\\/)dev[-\\w]+\\1(?:[^\\\\\\/]+\\1)*(?!DESC|NOTES)(?:[A-Z][-A-Z]*)(?:\\.in)?$/": { "image": "manifest" }, "image": "manifest"
},
"/(\\\\|\\/)dev[-\\w]+\\1(?:[^\\\\\\/]+\\1)*(?!DESC|NOTES)(?:[A-Z][-A-Z]*)(?:\\.in)?$/": {
"image": "manifest"
},
"lib/icons/.icondb.js": { "image": "manifest" }, "lib/icons/.icondb.js": { "image": "manifest" },
"/\\.git[\\/\\\\](.*[\\/\\\\])?(HEAD|ORIG_HEAD|packed-refs|logs[\\/\\\\](.+[\\/\\\\])?[^\\/\\\\]+)$/": { "/\\.git[\\/\\\\](.*[\\/\\\\])?(HEAD|ORIG_HEAD|packed-refs|logs[\\/\\\\](.+[\\/\\\\])?[^\\/\\\\]+)$/": {
"image": "manifest" "image": "manifest"
}, },
"/\\.(md|mdown|markdown|mkd|mkdown|mdwn|mkdn|rmd|ron|pmd)$/i": { "image": "markdown" }, "/\\.(md|mdown|markdown|mkd|mkdown|mdwn|mkdn|rmd|ron|pmd)$/i": {
"image": "markdown"
},
".mdx": { "image": "markdownx" }, ".mdx": { "image": "markdownx" },
".marko": { "image": "marko" }, ".marko": { "image": "marko" },
".nim": { "image": "nim" }, ".nim": { "image": "nim" },
@ -329,7 +341,9 @@
".psm1": { "image": "powershell" }, ".psm1": { "image": "powershell" },
".ps1xml": { "image": "powershell" }, ".ps1xml": { "image": "powershell" },
".prettierignore": { "image": "prettier" }, ".prettierignore": { "image": "prettier" },
"/\\.prettier((rc)|(\\.(toml|yml|yaml|json|js))?$){2}/i": { "image": "prettier" }, "/\\.prettier((rc)|(\\.(toml|yml|yaml|json|js))?$){2}/i": {
"image": "prettier"
},
"prettier.config.js": { "image": "prettier" }, "prettier.config.js": { "image": "prettier" },
"prisma.yml": { "image": "prisma" }, "prisma.yml": { "image": "prisma" },
".pde": { "image": "processing" }, ".pde": { "image": "processing" },
@ -359,7 +373,9 @@
"/\\.(r|Rprofile|rsx|rd)$/i": { "image": "r" }, "/\\.(r|Rprofile|rsx|rd)$/i": { "image": "r" },
".rkt": { "image": "racket" }, ".rkt": { "image": "racket" },
"/\\.res?i?$/i": { "image": "reasonml" }, "/\\.res?i?$/i": { "image": "reasonml" },
"/\\.(rb|ru|ruby|erb|gemspec|god|mspec|pluginspec|podspec|rabl|rake|opal)$/i": { "image": "ruby" }, "/\\.(rb|ru|ruby|erb|gemspec|god|mspec|pluginspec|podspec|rabl|rake|opal)$/i": {
"image": "ruby"
},
"/^\\.?(irbrc|gemrc|pryrc|ruby-(gemset|version))$/i": { "image": "ruby" }, "/^\\.?(irbrc|gemrc|pryrc|ruby-(gemset|version))$/i": { "image": "ruby" },
"/^(Appraisals|(Rake|[bB]uild|Cap|Danger|Deliver|Fast|Guard|Jar|Maven|Pod|Puppet|Snap)file(\\.lock)?)$/": { "/^(Appraisals|(Rake|[bB]uild|Cap|Danger|Deliver|Fast|Guard|Jar|Maven|Pod|Puppet|Snap)file(\\.lock)?)$/": {
"image": "ruby" "image": "ruby"
@ -377,13 +393,19 @@
}, },
"/\\.(ksh|mksh|pdksh)$/i": { "image": "shell" }, "/\\.(ksh|mksh|pdksh)$/i": { "image": "shell" },
".sh-session": { "image": "shell" }, ".sh-session": { "image": "shell" },
"/\\.zsh(-theme|_history)?$|^\\.?(antigen|zpreztorc|zlogin|zlogout|zprofile|zshenv|zshrc)$/i": { "image": "shell" }, "/\\.zsh(-theme|_history)?$|^\\.?(antigen|zpreztorc|zlogin|zlogout|zprofile|zshenv|zshrc)$/i": {
"image": "shell"
},
"/\\.fish$|^\\.fishrc$/i": { "image": "shell" }, "/\\.fish$|^\\.fishrc$/i": { "image": "shell" },
"/^\\.?(login|profile)$/": { "image": "shell" }, "/^\\.?(login|profile)$/": { "image": "shell" },
".inputrc": { "image": "shell" }, ".inputrc": { "image": "shell" },
".tmux": { "image": "shell" }, ".tmux": { "image": "shell" },
"/^(configure|config\\.(guess|rpath|status|sub)|depcomp|libtool|compile)$/": { "image": "shell" }, "/^(configure|config\\.(guess|rpath|status|sub)|depcomp|libtool|compile)$/": {
"/^\\/(private\\/)?etc\\/([^\\/]+\\/)*(profile$|nanorc$|rc\\.|csh\\.)/i": { "image": "shell" }, "image": "shell"
},
"/^\\/(private\\/)?etc\\/([^\\/]+\\/)*(profile$|nanorc$|rc\\.|csh\\.)/i": {
"image": "shell"
},
"/^\\.?cshrc$/i": { "image": "shell" }, "/^\\.?cshrc$/i": { "image": "shell" },
".profile": { "image": "shell" }, ".profile": { "image": "shell" },
".tcsh": { "image": "shell" }, ".tcsh": { "image": "shell" },

View file

@ -1,28 +1,40 @@
/* eslint-disable @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access */ /* eslint-disable @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access */
const { Client } = require('discord-rpc'); // eslint-disable-line const { Client } = require("discord-rpc"); // eslint-disable-line
import { commands, ExtensionContext, StatusBarAlignment, StatusBarItem, window, workspace, debug } from 'vscode'; import throttle from "lodash-es/throttle";
import throttle from 'lodash-es/throttle'; import {
type ExtensionContext,
StatusBarAlignment,
type StatusBarItem,
commands,
debug,
window,
workspace,
} from "vscode";
import { activity } from './activity'; import { activity } from "./activity";
import { CLIENT_ID, CONFIG_KEYS } from './constants'; import { CLIENT_ID, CONFIG_KEYS } from "./constants";
import { log, LogLevel } from './logger'; import { LogLevel, log } from "./logger";
import { getConfig, getGit } from './util'; import { getConfig, getGit } from "./util";
const statusBarIcon: StatusBarItem = window.createStatusBarItem(StatusBarAlignment.Left); const statusBarIcon: StatusBarItem = window.createStatusBarItem(
statusBarIcon.text = '$(pulse) Connecting to Discord...'; StatusBarAlignment.Left,
);
statusBarIcon.text = "$(pulse) Connecting to Discord...";
// eslint-disable-next-line // eslint-disable-next-line
let rpc = new Client({ transport: 'ipc' }); let rpc = new Client({ transport: "ipc" });
const config = getConfig(); const config = getConfig();
let state = {}; let state = {};
let idle: NodeJS.Timeout | undefined; let idle: NodeJS.Timeout | undefined;
let listeners: { dispose: () => any }[] = []; let listeners: { dispose: () => void }[] = [];
export function cleanUp() { export function cleanUp() {
// eslint-disable-next-line @typescript-eslint/no-unsafe-return // eslint-disable-next-line @typescript-eslint/no-unsafe-return
listeners.forEach((listener) => listener.dispose()); for (const listener of listeners) {
listener.dispose();
}
listeners = []; listeners = [];
} }
@ -34,50 +46,70 @@ async function sendActivity() {
} }
async function login() { async function login() {
log(LogLevel.Info, 'Creating discord-rpc client'); log(LogLevel.Info, "Creating discord-rpc client");
rpc = new Client({ transport: 'ipc' }); rpc = new Client({ transport: "ipc" });
rpc.on('ready', () => { rpc.on("ready", () => {
log(LogLevel.Info, 'Successfully connected to Discord'); log(LogLevel.Info, "Successfully connected to Discord");
cleanUp(); cleanUp();
statusBarIcon.text = '$(globe) Connected to Discord'; statusBarIcon.text = "$(globe) Connected to Discord";
statusBarIcon.tooltip = 'Connected to Discord'; statusBarIcon.tooltip = "Connected to Discord";
void sendActivity(); void sendActivity();
const onChangeActiveTextEditor = window.onDidChangeActiveTextEditor(() => sendActivity()); const onChangeActiveTextEditor = window.onDidChangeActiveTextEditor(() =>
const onChangeTextDocument = workspace.onDidChangeTextDocument(throttle(() => sendActivity(), 2000)); sendActivity(),
const onStartDebugSession = debug.onDidStartDebugSession(() => sendActivity()); );
const onTerminateDebugSession = debug.onDidTerminateDebugSession(() => sendActivity()); const onChangeTextDocument = workspace.onDidChangeTextDocument(
throttle(() => sendActivity(), 2000),
);
const onStartDebugSession = debug.onDidStartDebugSession(() =>
sendActivity(),
);
const onTerminateDebugSession = debug.onDidTerminateDebugSession(() =>
sendActivity(),
);
listeners.push(onChangeActiveTextEditor, onChangeTextDocument, onStartDebugSession, onTerminateDebugSession); listeners.push(
onChangeActiveTextEditor,
onChangeTextDocument,
onStartDebugSession,
onTerminateDebugSession,
);
}); });
rpc.on('disconnected', () => { rpc.on("disconnected", () => {
cleanUp(); cleanUp();
rpc.destroy(); rpc.destroy();
statusBarIcon.text = '$(pulse) Reconnect to Discord'; statusBarIcon.text = "$(pulse) Reconnect to Discord";
statusBarIcon.command = 'discord.reconnect'; statusBarIcon.command = "discord.reconnect";
}); });
try { try {
await rpc.login({ clientId: CLIENT_ID }); await rpc.login({ clientId: CLIENT_ID });
} catch (error) { } catch (error) {
log(LogLevel.Error, `Encountered following error while trying to login:\n${error as string}`); log(
LogLevel.Error,
`Encountered following error while trying to login:\n${error as string}`,
);
cleanUp(); cleanUp();
rpc.destroy(); rpc.destroy();
if (!config[CONFIG_KEYS.SuppressNotifications]) { if (!config[CONFIG_KEYS.SuppressNotifications]) {
// @ts-expect-error // @ts-expect-error
if (error?.message?.includes('ENOENT')) void window.showErrorMessage('No Discord client detected'); if (error?.message?.includes("ENOENT"))
else void window.showErrorMessage(`Couldn't connect to Discord via RPC: ${error as string}`); void window.showErrorMessage("No Discord client detected");
else
void window.showErrorMessage(
`Couldn't connect to Discord via RPC: ${error as string}`,
);
} }
statusBarIcon.text = '$(pulse) Reconnect to Discord'; statusBarIcon.text = "$(pulse) Reconnect to Discord";
statusBarIcon.command = 'discord.reconnect'; statusBarIcon.command = "discord.reconnect";
} }
} }
export async function activate(context: ExtensionContext) { export async function activate(context: ExtensionContext) {
log(LogLevel.Info, 'Discord Presence activated'); log(LogLevel.Info, "Discord Presence activated");
let isWorkspaceExcluded = false; let isWorkspaceExcluded = false;
for (const pattern of config[CONFIG_KEYS.WorkspaceExcludePatterns]) { for (const pattern of config[CONFIG_KEYS.WorkspaceExcludePatterns]) {
@ -93,52 +125,62 @@ export async function activate(context: ExtensionContext) {
const enable = async (update = true) => { const enable = async (update = true) => {
if (update) { if (update) {
try { try {
await config.update('enabled', true); await config.update("enabled", true);
} catch {} } catch {}
} }
log(LogLevel.Info, 'Enable: Cleaning up old listeners'); log(LogLevel.Info, "Enable: Cleaning up old listeners");
cleanUp(); cleanUp();
statusBarIcon.text = '$(pulse) Connecting to Discord...'; statusBarIcon.text = "$(pulse) Connecting to Discord...";
statusBarIcon.show(); statusBarIcon.show();
log(LogLevel.Info, 'Enable: Attempting to recreate login'); log(LogLevel.Info, "Enable: Attempting to recreate login");
void login(); void login();
}; };
const disable = async (update = true) => { const disable = async (update = true) => {
if (update) { if (update) {
try { try {
await config.update('enabled', false); await config.update("enabled", false);
} catch {} } catch {}
} }
log(LogLevel.Info, 'Disable: Cleaning up old listeners'); log(LogLevel.Info, "Disable: Cleaning up old listeners");
cleanUp(); cleanUp();
void rpc?.destroy(); void rpc?.destroy();
log(LogLevel.Info, 'Disable: Destroyed the rpc instance'); log(LogLevel.Info, "Disable: Destroyed the rpc instance");
statusBarIcon.hide(); statusBarIcon.hide();
}; };
const enabler = commands.registerCommand('discord.enable', async () => { const enabler = commands.registerCommand("discord.enable", async () => {
await disable(); await disable();
await enable(); await enable();
await window.showInformationMessage('Enabled Discord Presence for this workspace'); await window.showInformationMessage(
"Enabled Discord Presence for this workspace",
);
}); });
const disabler = commands.registerCommand('discord.disable', async () => { const disabler = commands.registerCommand("discord.disable", async () => {
await disable(); await disable();
await window.showInformationMessage('Disabled Discord Presence for this workspace'); await window.showInformationMessage(
"Disabled Discord Presence for this workspace",
);
}); });
const reconnecter = commands.registerCommand('discord.reconnect', async () => { const reconnecter = commands.registerCommand(
"discord.reconnect",
async () => {
await disable(false); await disable(false);
await enable(false); await enable(false);
}); },
);
const disconnect = commands.registerCommand('discord.disconnect', async () => { const disconnect = commands.registerCommand(
"discord.disconnect",
async () => {
await disable(false); await disable(false);
statusBarIcon.text = '$(pulse) Reconnect to Discord'; statusBarIcon.text = "$(pulse) Reconnect to Discord";
statusBarIcon.command = 'discord.reconnect'; statusBarIcon.command = "discord.reconnect";
statusBarIcon.show(); statusBarIcon.show();
}); },
);
context.subscriptions.push(enabler, disabler, reconnecter, disconnect); context.subscriptions.push(enabler, disabler, reconnecter, disconnect);

146
src/git.d.ts vendored
View file

@ -12,8 +12,8 @@
* -------------------------------------------------------------------------------------------- * --------------------------------------------------------------------------------------------
*/ */
import { Uri, Event, Disposable, ProviderResult } from 'vscode'; import type { Disposable, Event, ProviderResult, Uri } from "vscode";
export { ProviderResult } from 'vscode'; export { ProviderResult } from "vscode";
export interface Git { export interface Git {
readonly path: string; readonly path: string;
@ -23,15 +23,15 @@ export interface InputBox {
value: string; value: string;
} }
export const enum ForcePushMode { export enum ForcePushMode {
Force, Force = "Force",
ForceWithLease, ForceWithLease = "ForceWithLease",
} }
export const enum RefType { export enum RefType {
Head, Head = "Head",
RemoteHead, RemoteHead = "RemoteHead",
Tag, Tag = "Tag",
} }
export interface Ref { export interface Ref {
@ -75,26 +75,26 @@ export interface Remote {
readonly isReadOnly: boolean; readonly isReadOnly: boolean;
} }
export const enum Status { export enum Status {
INDEX_MODIFIED, INDEX_MODIFIED = "INDEX_MODIFIED",
INDEX_ADDED, INDEX_ADDED = "INDEX_ADDED",
INDEX_DELETED, INDEX_DELETED = "INDEX_DELETED",
INDEX_RENAMED, INDEX_RENAMED = "INDEX_RENAMED",
INDEX_COPIED, INDEX_COPIED = "INDEX_COPIED",
MODIFIED, MODIFIED = "MODIFIED",
DELETED, DELETED = "DELETED",
UNTRACKED, UNTRACKED = "UNTRACKED",
IGNORED, IGNORED = "IGNORED",
INTENT_TO_ADD, INTENT_TO_ADD = "INTENT_TO_ADD",
ADDED_BY_US, ADDED_BY_US = "ADDED_BY_US",
ADDED_BY_THEM, ADDED_BY_THEM = "ADDED_BY_THEM",
DELETED_BY_US, DELETED_BY_US = "DELETED_BY_US",
DELETED_BY_THEM, DELETED_BY_THEM = "DELETED_BY_THEM",
BOTH_ADDED, BOTH_ADDED = "BOTH_ADDED",
BOTH_DELETED, BOTH_DELETED = "BOTH_DELETED",
BOTH_MODIFIED, BOTH_MODIFIED = "BOTH_MODIFIED",
} }
export interface Change { export interface Change {
@ -138,7 +138,7 @@ export interface LogOptions {
} }
export interface CommitOptions { export interface CommitOptions {
all?: boolean | 'tracked'; all?: boolean | "tracked";
amend?: boolean; amend?: boolean;
signoff?: boolean; signoff?: boolean;
signCommit?: boolean; signCommit?: boolean;
@ -173,8 +173,13 @@ export interface Repository {
setConfig(key: string, value: string): Promise<string>; setConfig(key: string, value: string): Promise<string>;
getGlobalConfig(key: string): Promise<string>; getGlobalConfig(key: string): Promise<string>;
getObjectDetails(treeish: string, path: string): Promise<{ mode: string; object: string; size: number }>; getObjectDetails(
detectObjectType(object: string): Promise<{ mimetype: string; encoding?: string }>; treeish: string,
path: string,
): Promise<{ mode: string; object: string; size: number }>;
detectObjectType(
object: string,
): Promise<{ mimetype: string; encoding?: string }>;
buffer(ref: string, path: string): Promise<Buffer>; buffer(ref: string, path: string): Promise<Buffer>;
show(ref: string, path: string): Promise<string>; show(ref: string, path: string): Promise<string>;
getCommit(ref: string): Promise<Commit>; getCommit(ref: string): Promise<Commit>;
@ -215,7 +220,12 @@ export interface Repository {
fetch(options?: FetchOptions): Promise<void>; fetch(options?: FetchOptions): Promise<void>;
fetch(remote?: string, ref?: string, depth?: number): Promise<void>; fetch(remote?: string, ref?: string, depth?: number): Promise<void>;
pull(unshallow?: boolean): Promise<void>; pull(unshallow?: boolean): Promise<void>;
push(remoteName?: string, branchName?: string, setUpstream?: boolean, force?: ForcePushMode): Promise<void>; push(
remoteName?: string,
branchName?: string,
setUpstream?: boolean,
force?: ForcePushMode,
): Promise<void>;
blame(path: string): Promise<string>; blame(path: string): Promise<string>;
log(options?: LogOptions): Promise<Commit[]>; log(options?: LogOptions): Promise<Commit[]>;
@ -256,7 +266,7 @@ export interface PushErrorHandler {
): Promise<boolean>; ): Promise<boolean>;
} }
export type APIState = 'uninitialized' | 'initialized'; export type APIState = "uninitialized" | "initialized";
export interface PublishEvent { export interface PublishEvent {
repository: Repository; repository: Repository;
@ -299,40 +309,40 @@ export interface GitExtension {
getAPI(version: 1): API; getAPI(version: 1): API;
} }
export const enum GitErrorCodes { export enum GitErrorCodes {
BadConfigFile = 'BadConfigFile', BadConfigFile = "BadConfigFile",
AuthenticationFailed = 'AuthenticationFailed', AuthenticationFailed = "AuthenticationFailed",
NoUserNameConfigured = 'NoUserNameConfigured', NoUserNameConfigured = "NoUserNameConfigured",
NoUserEmailConfigured = 'NoUserEmailConfigured', NoUserEmailConfigured = "NoUserEmailConfigured",
NoRemoteRepositorySpecified = 'NoRemoteRepositorySpecified', NoRemoteRepositorySpecified = "NoRemoteRepositorySpecified",
NotAGitRepository = 'NotAGitRepository', NotAGitRepository = "NotAGitRepository",
NotAtRepositoryRoot = 'NotAtRepositoryRoot', NotAtRepositoryRoot = "NotAtRepositoryRoot",
Conflict = 'Conflict', Conflict = "Conflict",
StashConflict = 'StashConflict', StashConflict = "StashConflict",
UnmergedChanges = 'UnmergedChanges', UnmergedChanges = "UnmergedChanges",
PushRejected = 'PushRejected', PushRejected = "PushRejected",
RemoteConnectionError = 'RemoteConnectionError', RemoteConnectionError = "RemoteConnectionError",
DirtyWorkTree = 'DirtyWorkTree', DirtyWorkTree = "DirtyWorkTree",
CantOpenResource = 'CantOpenResource', CantOpenResource = "CantOpenResource",
GitNotFound = 'GitNotFound', GitNotFound = "GitNotFound",
CantCreatePipe = 'CantCreatePipe', CantCreatePipe = "CantCreatePipe",
PermissionDenied = 'PermissionDenied', PermissionDenied = "PermissionDenied",
CantAccessRemote = 'CantAccessRemote', CantAccessRemote = "CantAccessRemote",
RepositoryNotFound = 'RepositoryNotFound', RepositoryNotFound = "RepositoryNotFound",
RepositoryIsLocked = 'RepositoryIsLocked', RepositoryIsLocked = "RepositoryIsLocked",
BranchNotFullyMerged = 'BranchNotFullyMerged', BranchNotFullyMerged = "BranchNotFullyMerged",
NoRemoteReference = 'NoRemoteReference', NoRemoteReference = "NoRemoteReference",
InvalidBranchName = 'InvalidBranchName', InvalidBranchName = "InvalidBranchName",
BranchAlreadyExists = 'BranchAlreadyExists', BranchAlreadyExists = "BranchAlreadyExists",
NoLocalChanges = 'NoLocalChanges', NoLocalChanges = "NoLocalChanges",
NoStashFound = 'NoStashFound', NoStashFound = "NoStashFound",
LocalChangesOverwritten = 'LocalChangesOverwritten', LocalChangesOverwritten = "LocalChangesOverwritten",
NoUpstreamBranch = 'NoUpstreamBranch', NoUpstreamBranch = "NoUpstreamBranch",
IsInSubmodule = 'IsInSubmodule', IsInSubmodule = "IsInSubmodule",
WrongCase = 'WrongCase', WrongCase = "WrongCase",
CantLockRef = 'CantLockRef', CantLockRef = "CantLockRef",
CantRebaseMultipleBranches = 'CantRebaseMultipleBranches', CantRebaseMultipleBranches = "CantRebaseMultipleBranches",
PatchDoesNotApply = 'PatchDoesNotApply', PatchDoesNotApply = "PatchDoesNotApply",
NoPathFound = 'NoPathFound', NoPathFound = "NoPathFound",
UnknownPath = 'UnknownPath', UnknownPath = "UnknownPath",
} }

View file

@ -1,22 +1,24 @@
import { window } from 'vscode'; import dayjs from "dayjs";
import dayjs from 'dayjs'; import { window } from "vscode";
const outputChannel = window.createOutputChannel('Discord Presence'); const outputChannel = window.createOutputChannel("Discord Presence");
export const enum LogLevel { export enum LogLevel {
Trace = 'TRACE', Trace = "TRACE",
Debug = 'DEBUG', Debug = "DEBUG",
Info = 'INFO', Info = "INFO",
Warn = 'WARN', Warn = "WARN",
Error = 'ERROR', Error = "ERROR",
} }
function send(level: string, message: string) { function send(level: string, message: string) {
outputChannel.appendLine(`[${dayjs().format('DD/MM/YYYY HH:mm:ss')} - ${level}] ${message}`); outputChannel.appendLine(
`[${dayjs().format("DD/MM/YYYY HH:mm:ss")} - ${level}] ${message}`,
);
} }
export function log(level: LogLevel, message: string | Error) { export function log(level: LogLevel, message: string | Error) {
if (typeof message === 'string') { if (typeof message === "string") {
send(level, message); send(level, message);
} else if (message instanceof Error) { } else if (message instanceof Error) {
send(level, message.message); send(level, message.message);
@ -24,7 +26,7 @@ export function log(level: LogLevel, message: string | Error) {
if (message.stack) { if (message.stack) {
send(level, message.stack); send(level, message.stack);
} }
} else if (typeof message === 'object') { } else if (typeof message === "object") {
try { try {
const json = JSON.stringify(message, null, 2); const json = JSON.stringify(message, null, 2);
send(level, json); send(level, json);

View file

@ -1,9 +1,14 @@
import { basename } from 'path'; import { basename } from "node:path";
import { TextDocument, workspace, extensions, WorkspaceConfiguration } from 'vscode'; import {
type TextDocument,
type WorkspaceConfiguration,
extensions,
workspace,
} from "vscode";
import { KNOWN_EXTENSIONS, KNOWN_LANGUAGES } from './constants'; import { KNOWN_EXTENSIONS, KNOWN_LANGUAGES } from "./constants";
import type { API, GitExtension } from './git'; import type { API, GitExtension } from "./git";
import { log, LogLevel } from './logger'; import { LogLevel, log } from "./logger";
let git: API | null | undefined; let git: API | null | undefined;
@ -30,14 +35,17 @@ type WorkspaceExtensionConfiguration = WorkspaceConfiguration & {
}; };
export function getConfig() { export function getConfig() {
return workspace.getConfiguration('discord') as WorkspaceExtensionConfiguration; return workspace.getConfiguration(
"discord",
) as WorkspaceExtensionConfiguration;
} }
export const toLower = (str: string) => str.toLocaleLowerCase(); export const toLower = (str: string) => str.toLocaleLowerCase();
export const toUpper = (str: string) => str.toLocaleUpperCase(); export const toUpper = (str: string) => str.toLocaleUpperCase();
export const toTitle = (str: string) => toLower(str).replace(/^\w/, (c) => toUpper(c)); export const toTitle = (str: string) =>
toLower(str).replace(/^\w/, (c) => toUpper(c));
export function resolveFileIcon(document: TextDocument) { export function resolveFileIcon(document: TextDocument) {
const filename = basename(document.fileName); const filename = basename(document.fileName);
@ -54,14 +62,16 @@ export function resolveFileIcon(document: TextDocument) {
const regex = new RegExp(match[1], match[2]); const regex = new RegExp(match[1], match[2]);
return regex.test(filename); return regex.test(filename);
}); });
const findKnownLanguage = KNOWN_LANGUAGES.find((key) => key.language === document.languageId); const findKnownLanguage = KNOWN_LANGUAGES.find(
(key) => key.language === document.languageId,
);
const fileIcon = findKnownExtension const fileIcon = findKnownExtension
? KNOWN_EXTENSIONS[findKnownExtension] ? KNOWN_EXTENSIONS[findKnownExtension]
: findKnownLanguage : findKnownLanguage
? findKnownLanguage.image ? findKnownLanguage.image
: null; : null;
return typeof fileIcon === 'string' ? fileIcon : fileIcon?.image ?? 'text'; return typeof fileIcon === "string" ? fileIcon : (fileIcon?.image ?? "text");
} }
export async function getGit() { export async function getGit() {
@ -70,16 +80,19 @@ export async function getGit() {
} }
try { try {
log(LogLevel.Debug, 'Loading git extension'); log(LogLevel.Debug, "Loading git extension");
const gitExtension = extensions.getExtension<GitExtension>('vscode.git'); const gitExtension = extensions.getExtension<GitExtension>("vscode.git");
if (!gitExtension?.isActive) { if (!gitExtension?.isActive) {
log(LogLevel.Trace, 'Git extension not activated, activating...'); log(LogLevel.Trace, "Git extension not activated, activating...");
await gitExtension?.activate(); await gitExtension?.activate();
} }
git = gitExtension?.exports.getAPI(1); git = gitExtension?.exports.getAPI(1);
} catch (error) { } catch (error) {
git = null; git = null;
log(LogLevel.Error, `Failed to load git extension, is git installed?; ${error as string}`); log(
LogLevel.Error,
`Failed to load git extension, is git installed?; ${error as string}`,
);
} }
return git; return git;

View file

@ -1,25 +1,25 @@
/* eslint-disable @typescript-eslint/no-var-requires */ /* eslint-disable @typescript-eslint/no-var-requires */
/* eslint-disable @typescript-eslint/no-require-imports */ /* eslint-disable @typescript-eslint/no-require-imports */
const { CleanWebpackPlugin } = require('clean-webpack-plugin'); const { CleanWebpackPlugin } = require("clean-webpack-plugin");
const TerserPlugin = require('terser-webpack-plugin'); const TerserPlugin = require("terser-webpack-plugin");
const path = require('path'); const path = require("node:path");
/** @type {import('webpack').Configuration} */ /** @type {import('webpack').Configuration} */
module.exports = { module.exports = {
target: 'node', target: "node",
entry: './src/extension.ts', entry: "./src/extension.ts",
output: { output: {
filename: 'extension.js', filename: "extension.js",
libraryTarget: 'commonjs2', libraryTarget: "commonjs2",
path: path.resolve(process.cwd(), 'dist'), path: path.resolve(process.cwd(), "dist"),
}, },
devtool: 'source-map', devtool: "source-map",
externals: { externals: {
vscode: 'commonjs vscode', vscode: "commonjs vscode",
}, },
resolve: { resolve: {
extensions: ['.ts', '.js', '.json'], extensions: [".ts", ".js", ".json"],
}, },
plugins: [new CleanWebpackPlugin()], plugins: [new CleanWebpackPlugin()],
optimization: { optimization: {
@ -42,7 +42,7 @@ module.exports = {
rules: [ rules: [
{ {
test: /\.ts$/, test: /\.ts$/,
use: 'ts-loader', use: "ts-loader",
exclude: /node_modules/, exclude: /node_modules/,
}, },
], ],