Produce new lines of code using the vscode.window.activeTextEditor.edit method in Visual Studio Code

Hey everyone, I'm currently working on a vscode extension that can automatically generate template code based on the language you are using when you click a button. However, there seems to be an issue with the formatting of the generated code as it doesn't appear on new lines even though the coordinates are correct.

import * as vscode from 'vscode';
import "typescript";
import "./constants";

let myStatusBar : vscode.StatusBarItem;

export function activate({ subscriptions }: vscode.ExtensionContext) {
    const codeBoilerplateCommand = 'code-boilerplate.CodeBoilerplate';
    subscriptions.push(vscode.commands.registerCommand(codeBoilerplateCommand, () => {
        // Code generation logic here
    }));

    myStatusBar = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Right, 100);
    myStatusBar.command = codeBoilerplateCommand;
    subscriptions.push(myStatusBar);

    subscriptions.push(vscode.window.onDidChangeActiveTextEditor(updateStatusBarItem));
    subscriptions.push(vscode.window.onDidChangeTextEditorSelection(updateStatusBarItem));
    updateStatusBarItem();
}

function updateStatusBarItem(): void {
    myStatusBar.text = `$(new-file) Hello World!`;
    myStatusBar.show();
}

export function deactivate() {
    myStatusBar.dispose();
}

As an example, if I were to use a C# file, the generated code would look like this:

using System;namespace HelloWorld {class HelloWorld {static void Main(string[] args) {Console.WriteLine("Hello World!");}}}

However, what I actually expect is the code to be formatted with new lines and proper indentation, like so:

using System;

namespace HelloWorld {
    class HelloWorld {
        static void Main(string[] args) {
            Console.WriteLine("Hello World!");
        }
    }
}

Answer №1

After conducting tests on your code, I have confirmed that my previous comment was accurate regarding the insertion of text at line 2 in a document without pre-existing content.

editBuilder.insert(new vscode.Position(2,3), 'someText');

Unfortunately, the editBuilder does not create new lines automatically if they do not exist already. Instead, it simply appends the text to the existing line, typically line 1.

To overcome this limitation, there are two alternative approaches:

  • Preferred method: Construct your string as a string literal.

let insertString;

// Create the C# string
insertString = `using System;

namespace HelloWorld {
  class HelloWorld {
    static void Main(string[] args) {
      Console.WriteLine("Hello World!");
    }
  }
}`;

// Utilize one of these for all instances of insertString
await vscode.window.activeTextEditor.edit(editBuilder => {
    editBuilder.insert(new vscode.Position(0,0), insertString);
});

This approach works smoothly and allows you to verify the correctness of your string's format and indentation easily.


  • Add enough empty lines first before making your edits:
// Convert these into a loop
await vscode.commands.executeCommand('editor.action.insertLineAfter');
await vscode.commands.executeCommand('editor.action.insertLineAfter');
await vscode.commands.executeCommand('editor.action.insertLineAfter');
await vscode.commands.executeCommand('editor.action.insertLineAfter');
await vscode.commands.executeCommand('editor.action.insertLineAfter');
await vscode.commands.executeCommand('editor.action.insertLineAfter');
await vscode.commands.executeCommand('editor.action.insertLineAfter');
await vscode.commands.executeCommand('editor.action.insertLineAfter');

// Adjusted the Position arguments here
// Note that all character Positions are set to 0

await vscode.window.activeTextEditor.edit(editBuilder => {
    editBuilder.insert(new vscode.Position(0,0), 'using System;');
    editBuilder.insert(new vscode.Position(2,0), 'namespace HelloWorld {');
    editBuilder.insert(new vscode.Position(3,0), '\tclass HelloWorld {');
    editBuilder.insert(new vscode.Position(4,0), '\t\tstatic void Main(string[] args) {');
    editBuilder.insert(new vscode.Position(5,0), '\t\t\tConsole.WriteLine("Hello World!");');
    editBuilder.insert(new vscode.Position(6,0), '\t\t}');
    editBuilder.insert(new vscode.Position(7,0), '\t}');
    editBuilder.insert(new vscode.Position(8,0), '}');
});

Note on Positions: It is important to note that attempting to insert text at a specific character position like

editBuilder.insert(new vscode.Position(6,12)...
will not work on an empty line 6 since there is no character 12 on an empty line. For indentation purposes, zeroing out the Position characters and inserting tabs (\t) is recommended. This further underscores why the first method is more efficient.


Both methods are effective, but the first method is cleaner. Here is a demonstration of both methods working consecutively within the same activate function:



Another useful tip is to select all text and then execute the command editor.action.formatSelection after setting the languageId for the file (verify if it has not been set by the user):

const editor = vscode.window.activeTextEditor;
await vscode.languages.setTextDocumentLanguage(editor.document, 'javascript');

// Take note that formatting of the insertString is not attempted here
const insertString = `using System;

    namespace HelloWorld {
    class HelloWorld {
    static void Main(string[] args) {
    Console.WriteLine("Hello World!");
    }
    }
    }`;

await editor.edit(editBuilder => {
    editBuilder.insert(new vscode.Position(10,0), insertString);
});

// Select all text and run formatSelection
await vscode.commands.executeCommand('editor.action.selectAll');
await vscode.commands.executeCommand('editor.action.formatSelection');
await vscode.commands.executeCommand('cancelSelection');

This assumes that the user has a formatter installed for each language.

Demonstration of this formatter:

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

A Unique Identifier in Kotlin

In my typescript class, I have a member that accepts any as the name: interface ControlTagType { type?: String | null; [name: string]: any } class ControlTag { tagSource: String | null = null; tag: ControlTagType | null = null; } expor ...

Setting up Electron to utilize TypeScript's baseUrl can be achieved by following a few simple steps

In TypeScript, there is a compiler option known as baseUrl that allows you to use non-relative paths, like: import Command from "util/Command" as opposed to: import Command from "../../../util/Command" While this works fine during compilation, TypeScri ...

validating if Object may be either 'null' or 'undefined'

In the code snippet below, I am attempting to verify whether hostel.country.address is null: return hostel.country.address && hostel.country.address.internalEmployeeIdentifier !== null || hostel.country.address.exter ...

Unable to place value into an array following the invocation of a function in Angular 9

Within an array I established, I am encountering an undefined value when I use console.log. Take a look at my component.ts below: export class OrderExceptionReportComponent implements OnInit { public sessionData: ExceptionReportSessionData[] = []; n ...

Having difficulty executing the Cypress open command within a Next.js project that uses Typescript

I'm having trouble running cypress open in my Next.js project with Typescript. When I run the command, I encounter the following issues: % npm run cypress:open > [email protected] cypress:open > cypress open DevTools listening on ws: ...

Develop an extensive Typescript and React shared library

Trying to develop a shared React and Typescript library has been quite challenging. Configuring the project workspace to work on both the library and application simultaneously has proven to be more difficult than anticipated. project ├─ app │ ├ ...

Challenges in handling asynchronous data within static JSON objects in Angular2

I have a service set up with some static objects that are being utilized in my UI. fetchRulesVariables() fetchRuleVariables() { let variables = [ { name: 'Credit Funding Type', id: 1, multiple: ...

Matching the appropriate data type for interface attributes

In the process of developing a module (module1), I have defined the following interface type: interface ModuleOneInterface { keyOne: customInterface; keyTwo: customInterface; keyThree: customInterface; } Now, as I work on another module (modul ...

Exploring the process of selecting checkboxes in Angular 6

I'm currently learning Angular 6 and I have a requirement to mark checkboxes based on specific IDs from two arrays: this.skillArray = [ {ID: 1, name: "Diving"}, {ID: 2, name: "Firefighting"}, {ID: 3, name: "Treatment"}, ...

What could be the reason my mat-form-field is not displaying the label?

I'm currently working on a project using Angular Material to build a web page. I am facing an issue with the mat-form-field component as the label is not displaying, and I can't figure out why. Any assistance would be greatly appreciated. Thank y ...

What is the best way to wrap `useFetch` in order to leverage reactivity?

When I wrap useFetch() as a composable to customize the baseURL and automatically set an authentication token, I encounter reactivity issues when calling the composable within a component without using the await keyword. Typically, I would call const { dat ...

What are the benefits of utilizing TypeScript declarations? How can you demonstrate their value with concrete examples?

I'm a bit confused about the use of declaration in TypeScript. It seems like the compiler doesn't compile it into the js file, so what is the purpose and advantage of using declaration? Can someone please explain this to me? ...

Leverage Typescript to convert string literal types to uppercase

type x = 'first' | 'second' I am looking to create a type y that is similar to this: type y = 'FIRST' | 'SECOND' Here is what I attempted: type x = 'first' | 'second' type y = {[key in x]: key[& ...

Creating a function in Typescript to extend a generic builder type with new methods

Looking to address the warnings associated with buildChainableHTML. Check out this TS Playground Link Is there a way to both: a) Address the language server's concerns without resorting to workarounds (such as !,as, ?)? b) Dodge using type HTMLChain ...

How can I use the form's restart() method in React-Final-Form to clear a MUI TextField input and also capture the event at the same time?

When I use form.restart() in my reset button, it resets all fields states and values based on my understanding of the Final-Form. The reset method triggers and clears all fields in the form, and I can capture the event in the autocomplete. However, I am fa ...

Enforce numerical input in input field by implementing a custom validator in Angular 2

After extensive research, I was unable to find a satisfactory solution to my query. Despite browsing through various Stack Overflow questions, none of them had an accepted answer. The desired functionality for the custom validator is to restrict input to ...

Encountering an error in Angular2 and TypeScript: TS2322 error message stating that the type 'Response' cannot be assigned to type 'UserStatus'

Currently, I am facing some challenges while working with Angular2 and TypeScript. Transitioning from AngularJS to Angular2 has proven to be a bit tricky for me. To better understand this new framework, I decided to create an experimental app with the foll ...

Transform object into data transfer object

Looking for the most efficient method to convert a NestJS entity object to a DTO. Assuming the following setup: import { IsString, IsNumber, IsBoolean } from 'class-validator'; import { Exclude } from 'class-transformer'; export clas ...

Establish an enumeration using universally recognized identifiers

I have a JavaScript function that requires a numerical input, as well as some predefined constants at the top level: var FOO = 1; var BAR = 2; The function should only be called using one of these constants. To ensure type safety in TypeScript, I am att ...

Customizable mongoDB database collection

Is there a more efficient way to make calls to different collections based on a function parameter? I'm exploring the possibility and if it's not feasible, I'll handle it case by case. Currently, I have this code and the goal is to have a u ...