5

I am creating a vscode extension that does some custom auto-completing of files paths.

I want to take what the user has typed, and if that value resolves to a folder in the workspace, I want to list all the files in that folder for auto-complete.

For example, given:

  • a workspace located at: /home/me/my-vs-project
  • with files:
    • /home/me/my-vs-project/assets/dog.png
    • /home/me/my-vs-project/assets/cat.jpeg

If I type in 'assets' or './assets' into vscode, the extension should be able to provide me an autocomplete list of:

  • './assets/dog.png'
  • './assets/cat.png'

Here's a snippet of the code that doesn't work (returns 0 results)..

let inputAsWorkspaceRelativeFolder = getInput(document, position); // for example, would return: '/home/me/my-vs-project/assets' for input of './assets'

let glob = inputAsWorkspaceRelativeFolder + '/*';

vscode.workspace.findFiles(glob, null, 100).then((uris: vscode.Uri[] ) => {         
   uris.forEach((uri: vscode.Uri) => {              
         console.log(uri);
   });
}); 

For some reason, the above code is returning 0 uris though. Thoughts on how I have to format the glob to make this happen? and/or if there is a better approach?

empire29
  • 3,729
  • 6
  • 45
  • 71
  • 1
    Since you are working using Node you can just choose from any of these answers - https://stackoverflow.com/questions/2727167/how-do-you-get-a-list-of-the-names-of-all-files-present-in-a-directory-in-node-j – Mauricio Gracia Gutierrez Feb 14 '21 at 20:37

2 Answers2

0

I think you wronged the glob. I found this intresting wiki about Glob pattern composition.

        let inputAsWorkspaceRelativeFolder = 'asset'; // for example, would return: '/home/me/my-vs-project/assets' for input of './assets'

        //https://github.com/ev3dev/vscode-ev3dev-browser/wiki/Glob-Patterns
        let glob = '**/'+inputAsWorkspaceRelativeFolder+'/*.*';//or +'/{*.png,*.jpeg}';

Or you can use the node built-in fs


import * as fs from 'fs';
        fs.readdir(inputAsWorkspaceRelativeFolder, (err, files: string[]) => {
            files.forEach((file: path) => {
                const uri = vscode.Uri.file(file);
                console.log(uri);
            });
        });

More simple, if you want to get all the files in the asset folder and don't want to filter for extension.

Denis.net
  • 55
  • 9
  • Hi! In your vs Glob example, wouldn't that find all files in ANY folder named 'asset' in the workspace? I want to have a glob that will only find files that are direct children of the folder. – empire29 Jun 30 '19 at 16:40
  • Yes, I think you just missed the extension glob part. Ie : in ` let glob = inputAsWorkspaceRelativeFolder + '/*';` the ending '/*' should be '/*.*' or better '/*.png,jpeg,jpg,gif}' – Denis.net Jun 30 '19 at 21:25
  • 1
    Looking at the deprecated `vscode.workspace.rootPath` : When there is just one folder open, that folder is taken as the workspace root, but when you have more folders/workspaces loaded you can only search using relative pattern, because you have no more a root path available. – Denis.net Jul 01 '19 at 07:01
0

I was able to do this using vscode.RelativePattern -- I'm sure I could've done it using generic GlobPatterns but im still not clear what the findFiles(..) consider the 'root' when matching files; RelativePattern is explicitly relative to the workspace root.

let workspaceFolder: vscode.WorkspaceFolder | undefined = vscode.workspace.getWorkspaceFolder(document.uri);

        if (!workspaceFolder || document.isUntitled) {
            return undefined;
        }

        // Workspace folder: /home/me/my-project
        let workspaceFolderPath: string = workspaceFolder.uri.path;

        let relativeSearchFolderPrefix = path.normalize(path.dirname(document.uri.path) + '/' + searchText);
        relativeSearchFolderPrefix = path.relative(workspaceFolderPath, relativeSearchFolderPrefix);

            let relativePattern: vscode.RelativePattern = new vscode.RelativePattern(
                workspaceFolderPath,
                relativeSearchFolderPrefix + '/**/*.{png,jpeg,jpg,gif}');

return vscode.workspace.findFiles(globPattern, null, 50).then((uris: vscode.Uri[] ) => {            
            let relativePaths: string[] = [];

            uris.forEach((uri: vscode.Uri) => {             
                relativePaths.push(path.relative(current, uri.path));
            });

            // trivial custom function that turns an array of strings into CompletionItems
            return getCompletionItems(relativePaths, vscode.CompletionItemKind.File);
        }); 
empire29
  • 3,729
  • 6
  • 45
  • 71