Building a VSCode Extension – Some Tips and Tricks

  • infoFull Post Details
    info_outlineClick for Full Post Details
    Date Posted:
    May. 10, 2019
    Last Updated:
    May. 10, 2019
  • classTags
    classClick for Tags

I’m trying out building a VSCode extension for the first time, and having a lot of fun learning the basics of TypeScript and the VSCode API.

I’m impressed by the level of documentation for the VSCode APIs, but thought I would share some additional tips and tricks I have been picking up.

Watch for Changes in a Specific Document

onDidChangeTextDocument and onDidCloseTextDocument are both excellent event listeners to subscribe to for watching for changes in a document. However, they are “attached” to the workspace, not to specific documents, so if you attach a listener to either, you will actually be getting notified when any document is changed or closed, not just the one you are interested. However, even though vscode.TextDocument is a complex type, using an equality operator works just fine, so the best way to listen for changes on a specific doc is to store a reference to the TextDocument of interest, then check if it matches on each event. Here is a quick sample:

let currOpenEditor = vscode.window.activeTextEditor;
if (currOpenEditor){

	// In this example, we want to start watching the currently open doc
	let currActiveDoc = currOpenEditor.document;

	let onDidChangeDisposable = vscode.workspace.onDidChangeTextDocument((event: vscode.TextDocumentChangeEvent)=>{
		if (event.document === currActiveDoc){
			console.log('Watched doc changed');
		}
		else {
			console.log('Non watched doc changed');
		}
	});
	
	let onDidCloseDisposable = vscode.workspace.onDidCloseTextDocument((closedDoc: vscode.TextDocument)=>{
		if (closedDoc === currActiveDoc){
			console.log('Watched doc was closed');
		}
		else {
			console.log('non watched doc closed');
		}
	});
}

Getting the range of entire document

Right now, it looks like there is no single API call that will return the full range that the text content of a document spans. There are a few different ways you can determine the range:

The popular method – something like:

// where document is of type vscode.TextDocument
let entireDocRange: vscode.Range = new vscode.Range(0,document.lineAt(0).range.start.character,document.lineCount-1,document.lineAt(document.lineCount-1).range.end.character);

Neat method – Create a range that is purposely larger than the actual range of the document (start at 0,0, then go to end of doc + 1 line), then use vscode.TextDocument.validateRange() to shrink the larger range down to the actual text content. Found on StackOverflow, demonstrated below:

let entireDocRange = document.validateRange(new vscode.Range(0,0,document.lineCount,0));

Webview – the built-in web renderer

If you are looking to display simple HTML content to a VSCode user, you can use the built-in webview API to show a rendered webpage in a new tab – no dealing with deploying a local server, Chrome extensions, etc. You can even communicate with the content inside the webview by using the standard postMessage syntax.

Leave a Reply

Your email address will not be published. Required fields are marked *