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:

https://i.sstatic.net/IIHFG.gif



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:

https://i.sstatic.net/6ko4t.gif

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

Struggling to solve a never-ending loop problem in a messaging application

I am currently in the process of developing a chat application. During the initialization of the chat page, I am checking for messages and storing them in an array. ngOnInit() { this.messageService.getMessages().doc(`${this.sortItineraries[0] + ...

Angular 8 throws a TS2339 error, yet the code is functioning perfectly and delivering the desired output

Upon compiling my code, I encountered the following error: ERROR in src/app/home/home.component.ts:13:37 - error TS2339: Property 'name' does not exist on type 'string | Type'. Property 'name' does not exist on type &ap ...

Maintaining checkbox selection while switching pages in Angular

When I try to edit the settings for accepting payments in all currencies under the "Pricing" component, the checkbox is unchecked every time I return to the "General" section. How can I prevent this from happening and keep the checkbox checked? Refer to ...

What could be the reason for encountering a Typescript ts(2345) error while trying to pass a mocked constant to .mockResolvedValue()?

Within my test.tsx file, I have the following code snippet: test('Photos will load', async () => { const mockCuratedPhotos = jest.spyOn(endpoints, 'getCuratedPhotos'); mockCuratedPhotos.mockResolvedValue(mockPhotos); awa ...

Conceal or remove disabled years in Angular Material datepicker

I previously disabled years prior to 2018, but now I would like to hide or delete them. The year selection range currently starts from 1998, but it should begin at 2018 instead. Is there a way to display only 3-4 years instead of the current 24-year rang ...

How to assign attributes to all child elements in Angular?

I have a unique component in Angular that I utilize throughout my app. It's a button component which I use by calling <app-delete-btn></app-delete-btn> wherever needed. I tried to set the tabindex="1" attribute for my component ...

Utilizing a configuration file with Vue's `use` method

Within my index.ts file, I am setting up the configuration for the Google reCAPTCHA component using a specific sitekey: Vue.use(VueReCaptcha, { siteKey: 'my_redacted_sitekey' }); This setup occurs prior to the initialization of the new Vue({ ...

Ignoring setTimeout() function within forEach() in Angular leads to issues

I am currently working on the frontend development of a Web Application using Angular. My task involves saving data from an array into a database by making repeated API calls until all the array data is processed. I implemented the use of setTimeout() in ...

The movement of particles in tsparticles experiences interruptions when built in React, causing defects in their motion or noticeable stutter and lag

The performance is flawless in development mode with npm run start, but once deployed and running the production build (npm run build), there seems to be a disturbance in particle movement or a drastic decrease in speed. Despite experimenting with all ava ...

Controlling the visibility of components or elements in Angular through input modifications

Is there a more efficient way to handle button disabling and enabling based on email validation in Angular? I already have form controls set up, but want to make the process cleaner. The goal is to disable the "Get Started" button by default if the email a ...

How can I implement a redirect back to the previous query page post-authentication in Next.js 13?

To enhance security, whenever a user tries to access a protected route, I plan to automatically redirect them to the login page. Once they successfully log in, they will be redirected back to the original protected route they were trying to access. When w ...

Tips for updating state in React TypeScript 2.0?

Working with a small component built using React and TypeScript has presented a unique challenge. interface Props { } interface State { isOpen: boolean; } class App extends React.Component<Props, State> { constructor(props: Props) { super ...

Retrieve the total number of hours within a designated time frame that falls within a different time frame

Having a difficult time with this, let me present you with a scenario: A waiter at a restaurant earns $15/hour, but between 9:00 PM and 2:30 AM, he gets paid an additional $3/hour. I have the 'start' and 'end' of the shift as Date obje ...

Substitute terms in a sentence according to the guidelines

Looking to transform strings based on specific rules? "Hello {{firstName}}, this is {{senderName}}." Consider the following rules: rules = { firstName: "Alex", senderName: "Tracy" } The expected output would be: "Hello Alex, this is Tracy." If yo ...

Leveraging the Recyclability Aspect of a ReactJS Modal

Looking for a way to make a modal dynamic without duplicating too much code. Any suggestions on how to achieve this? I've managed to separate the state from the layout using render props. interface State { open: boolean; } interface InjectedMod ...

Utilizing the 'create' function in sqlite each time I need to run a query

I've been diving into SQLite within the Ionic framework and have pieced together some code based on examples I've encountered. import { Component } from '@angular/core'; import { IonicPage, NavController, NavParams } from 'ionic-a ...

Simultaneously accessing multiple APIs

I am currently facing an issue with calling two API requests sequentially, which is causing unnecessary delays. Can someone please advise me on how to call both APIs simultaneously in order to save time? this.data = await this.processService.workflowAPI1(& ...

Can a string array be transformed into a union type of string literals?

Can we transform this code snippet into something like the following? const array = ['a', 'b', 'c']; // this will change dynamically, may sometimes be ['a', 'e', 'f'] const readonlyArray = arr ...

Updates to TypeScript 2.3.1 creating disruptions in SystemJS plunk

Check out this official Angular + TypeScript plunk using SystemJS 0.19.31, now updated to TypeScript 2.3.0. However, changing the SystemJS configuration in the same plunk to TypeScript 2.3.1 or 2.3.2 'typescript': 'npm:<a href="/cdn-cgi ...

Converting JavaScript object data to x-www-form-urlencoded: A step-by-step guide

I am trying to convert a JavaScript object into x-www-form-urlencoded. Is there a way to achieve this using Angular 2? export class Compentency { competencies : number[]; } postData() { let array = [1, 2, 3]; this.comp.competencies ...