[ Web Proxy ]
URL:
Viewing: https://raw.githubusercontent.com/VSpaceCode/VSpaceCode/master/src/pathCommands.ts [Back]  [Original]

import path, { PlatformPath } from "path";
import { env, TextEditor, Uri, window, workspace } from "vscode";
import { CharCode } from "./charCode";
import { defaultStatusBarTimeout } from "./constants";
import { UriScheme } from "./uriScheme";

export function copyWrapper(fn: (activeEditor: TextEditor) => string) {
    return async () => {
        const activeEditor = window.activeTextEditor;
        if (activeEditor) {
            const fsPath = fn(activeEditor);
            await env.clipboard.writeText(fsPath);
            window.setStatusBarMessage(fsPath, defaultStatusBarTimeout);
            return fsPath;
        }
        return undefined;
    };
}

export function getPath(activeEditor: TextEditor) {
    return _getPath(activeEditor, false).fsPath;
}

export function getPathWithLine(activeEditor: TextEditor) {
    const active = _getPath(activeEditor, false);
    return `${active.fsPath}:${active.line}`;
}

export function getPathWithLineColumn(activeEditor: TextEditor) {
    const active = _getPath(activeEditor, false);
    return `${active.fsPath}:${active.line}:${active.col}`;
}

export function getDirectoryPath(activeEditor: TextEditor) {
    const active = _getPath(activeEditor, false);
    return dirname(active.fsPath, active.path);
}

export function getRelativePath(activeEditor: TextEditor) {
    return _getPath(activeEditor, true).fsPath;
}

export function getRelativePathWithLine(activeEditor: TextEditor) {
    const active = _getPath(activeEditor, true);
    return `${active.fsPath}:${active.line}`;
}

export function getRelativePathWithLineColumn(activeEditor: TextEditor) {
    const active = _getPath(activeEditor, true);
    return `${active.fsPath}:${active.line}:${active.col}`;
}

export function getRelativeDirectoryPath(activeEditor: TextEditor) {
    const active = _getPath(activeEditor, true);
    return dirname(active.fsPath, active.path);
}

export function getFilename(activeEditor: TextEditor) {
    const active = _getPath(activeEditor, true);
    return basename(active.fsPath, true, active.path);
}

export function getFilenameBase(activeEditor: TextEditor) {
    const active = _getPath(activeEditor, true);
    return basename(active.fsPath, false, active.path);
}

function _getPath(activeEditor: TextEditor, relative: boolean) {
    const uri = activeEditor.document.uri;
    let fsPath = relative ? relativePathToWorkspace(uri) : uriToFsPath(uri);

    const platformPath = getPlatformPath(uri);
    if (platformPath === path.win32) {
        // Replace all / to \
        fsPath = fsPath.replace(/\//g, "\\");
    }

    const activePos = activeEditor.selection.active;
    const line = activePos.line;
    const col = activePos.character;
    return { fsPath, path: platformPath, line, col };
}

function hasDriveLetter(fsPath: string, offset = 0): boolean {
    if (fsPath.length >= 2 + offset) {
        // Checks C:\Users
        //        ^^
        const char0 = fsPath.charCodeAt(0 + offset);
        const char1 = fsPath.charCodeAt(1 + offset);
        return (
            char1 === CharCode.Colon &&
            ((char0 >= CharCode.A && char0 = CharCode.a && char0 = 3) {
        // Checks \\localhost\shares\ddd
        //        ^^^
        return (
            isPathSeparator(fsPath.charCodeAt(0)) &&
            isPathSeparator(fsPath.charCodeAt(1)) &&
            !isPathSeparator(fsPath.charCodeAt(2))
        );
    }
    return false;
}

/**
 * Compute the closest relative path of the input uri to the workspace folder(s).
 *
 * When there are no workspace folders or when the path
 * is not contained in them, the input is returned.
 *
 * This similar to the `workspace.asRelativePath` that the relative path is always
 * going to use `/`. However, one difference is if we need to return input path,
 * it will always be `/` (won't normalized to `\` if the host is on Windows).
 * So we can handle the case if we are remoting into a Windows machine from *nix.
 */
function relativePathToWorkspace(uri: Uri) {
    const folder = workspace.getWorkspaceFolder(uri);
    return folder
        ? relativePath(folder.uri, uri) ?? uriToFsPath(uri)
        : uriToFsPath(uri);
}

function dirname(fsPath: string, path: PlatformPath) {
    return path.dirname(fsPath) + path.sep;
}

function basename(fsPath: string, withExt: boolean, path: PlatformPath) {
    return withExt
        ? path.basename(fsPath)
        : path.basename(fsPath, path.extname(fsPath));
}

/**
 * Get the platform path base on the uri.
 *
 * This is similar with the assumption in `uriToFsPath`. If the path has drive letter
 * or is an UNC path, assumed the uri to be a Windows path.
 */
function getPlatformPath(uri: Uri) {
    const fsPath = uriToFsPath(uri);
    return hasDriveLetter(fsPath) || isUNC(fsPath) ? path.win32 : path.posix;
}

/**
 * Compute `fsPath` with slash normalized to `/` for the given uri.
 *
 * This is what vscode uses internally to compute uri.fsPath; however,
 * backslash conversion for Windows host is removed, and drive letter is always normalized to uppercase.
 *
 * The problems with the internal `uri.fsPath`:
 *  - Windows machine remoting into a linux will return a `\` as separator
 *  - *nix machine remoting into a windows will return `/` as separator
 *
 * Modified from https://github.com/microsoft/vscode/blob/f74e473238aca7b79c08be761d99a0232838ca4c/src/vs/base/common/uri.ts#L579-L604
 */
function uriToFsPath(uri: Uri): string {
    let value: string;
    if (uri.authority && uri.path.length > 1 && uri.scheme === "file") {
        // unc path: file://shares/c$/far/boo
        value = `//${uri.authority}${uri.path}`;
    } else if (
        // e.g. local file and vscode-remote file
        uri.path.charCodeAt(0) === CharCode.Slash &&
        hasDriveLetter(uri.path, 1)
    ) {
        // windows drive letter: file:///c:/far/boo
        // Normalized drive letter -> C:/far/boo
        value = uri.path[1].toUpperCase() + uri.path.substr(2);
    } else {
        // other path
        value = uri.path;
    }
    return value;
}

function equalsIgnoreCase(a1: string, a2: string) {
    return a1.length === a1.length && a1.toLowerCase() === a2.toLowerCase();
}

function isEqualAuthority(a1: string, a2: string) {
    return a1 === a2 || equalsIgnoreCase(a1, a2);
}

/**
 * Compute the relative path of two uris.
 *
 * This differs from the vscode version is that this doesn't normalize slash for Windows; therefore,
 * we can use posix path to compute relative instead of host machine specific path.
 *
 * Modified from https://github.com/microsoft/vscode/blob/f74e473238aca7b79c08be761d99a0232838ca4c/src/vs/base/common/resources.ts#L228-L249
 */
function relativePath(
    from: Uri,
    to: Uri,
    ignorePathCasing = false
): string | undefined {
    if (
        from.scheme !== to.scheme ||
        !isEqualAuthority(from.authority, to.authority)
    ) {
        return undefined;
    }
    if (from.scheme === UriScheme.File) {
        return path.posix.relative(uriToFsPath(from), uriToFsPath(to));
    }
    let fromPath = from.path || "/";
    const toPath = to.path || "/";
    if (ignorePathCasing) {
        // make casing of fromPath match toPath
        let i = 0;
        for (
            const len = Math.min(fromPath.length, toPath.length);
            i < len;
            i++
        ) {
            if (fromPath.charCodeAt(i) !== toPath.charCodeAt(i)) {
                if (
                    fromPath.charAt(i).toLowerCase() !==
                    toPath.charAt(i).toLowerCase()
                ) {
                    break;
                }
            }
        }
        fromPath = toPath.substr(0, i) + fromPath.substr(i);
    }
    return path.posix.relative(fromPath, toPath);
}

Web Proxy Viewer  |  New URL  |  Original Page