Check value of last line selected - vscode-api - visual-studio-code

I'm trying to figure out how to see if the active editor's last line that's selected contains any characters/text excluding spaces. The purpose of this is to identify if there are any text highlighted and if not then to go back up a number in the editor and not include that line.
I know that you can do this
const editor = vscode.window.activeTextEditor
const lastLineSelected = editor.selection.end
in order to get the last line number, but how can I evaluate the text that's highlighted in that line?

If I understand correctly, you want to get the text of the last line of a selection which may be multi-line. The below does that, with a check in case the only selected line is partially selected.
const editor = vscode.window.activeTextEditor;
const selection = editor.selection;
if (selection && !selection?.isEmpty) {
// is more than one line selected, if so use 0 as the start of the selection on the last line
// otherwise use the actual first character selected on that line
const firstSelectedCharacterOnLastLine = (selection.start.line < selection.end.line) ? 0 : selection.start.character;
// make a Range to use with getText(<some Range>)
const lastLineOfSelectionRange = new vscode.Range(selection.end.line, firstSelectedCharacterOnLastLine, selection.end.line, selection.end.character);
const text = editor.document.getText(lastLineOfSelectionRange);
// do your testing on the text using javascript String methods
// like text.search(/[^\s]/) search for any non-whitespace character
}

Related

How to show complete header label name in Select Columns header menu dialog(Column Chooser),when header column labels contain new line character?

I've header menu configuration added in my nat table as follows,where I've included "Select Columns" menu as well:
// Popup menu
this.natTable.addConfiguration(new HeaderMenuConfiguration(this.natTable) {
#Override
protected PopupMenuBuilder createColumnHeaderMenu(NatTable natTable) {
return super.createColumnHeaderMenu(natTable) .withColumnChooserMenuItem(); }
});
// Column chooser
DisplayColumnChooserCommandHandler columnChooserCommandHandler = new DisplayColumnChooserCommandHandler( bodyLayer.getSelectionLayer(), bodyLayer.getColumnHideShowLayer(), columnHeaderLayer.getColumnHeaderLayer(), columnHeaderLayer.getColumnHeaderDataLayer(), columnHeaderLayer.getColumnGroupHeaderLayer(), columnGroupModel);
//If header name consists of multiple words then I've used ("\n") as a separator between words in
//the header column name ,so that some space could be saved
// In that case on opening "Select Columns" context menu dialog only first word of column is visible
Can it be fixed by replacing all "\n" and white space character by single white space(" ") character in
In org.eclipse.nebula.widgets.nattable.columnChooser.gui.ColumnChooserDialog
//code to replace extra white spaces or new line character from column label with single space so that //header name is completely visible in populate tree method
treeItem.setText(columnEntry.getLabel());
In that case can fix be provided to replace extra space with single space in column header name or is there any other alternative to fix it?
Image with header names having multiple words For eg:"Issue Date",if header name is dispalyed as "Issue\nDate",only Issue is visible in "Select Columns" context menu dialog
IIRC you add the line breaks to save some space. They are not needed for any semantical reason. I would suggest to configure the TextPainter that renders the column header cell content to wrap automatically if not enough space is available. This could look like this for example:
configRegistry.registerConfigAttribute(
CellConfigAttributes.CELL_PAINTER,
new BeveledBorderDecorator(new TextPainter(true, false, false, true)),
DisplayMode.NORMAL,
GridRegion.COLUMN_HEADER);

VSCode: How can I determine the cursor's column position within an editor?

I'm looking for a simple method to determine the column position of a VSCode editor's text insertion cursor/caret, either prior to selecting an area of text to copy or immediately the mouse is used to start the selection. The column number would then be stored in the clipboard before performing further clipboard manipulation.
I have tried searching for AutoHotkey methods to achieve this, but the only solution I'm able to find involves using ImageSearch, which is not suitable for my purpose.
Edit: I found this API reference, could I possibly use this to determine the cursor position preferably using windows cmd/powershell?
You can make a vscode extension and bind the command to a keyboard shortcut.
How to get line and column(character) of cursor:
const activeEditor = vscode.window.activeTextEditor
if (activeEditor) {
console.log(activeEditor.selection.active.line)
console.log(activeEditor.selection.active.character) //column
}
api: https://code.visualstudio.com/api/references/vscode-api#details-159
activeEditor.selection gives you an object with 4 objects
start:Object
line:4
character:8
end:Object
line:6
character:8
active:Object
line:4
character:8
anchor:Object
line:6
character:8
activeEditor.selection.active is your cursor.
activeEditor.selection.anchor is
The position at which the selection starts. This position might be before or after active.
anchor-active may be reversed, but start-end will always be up-down.
note: I found the api AFTER I found out how to get current line from here:
VScode API why can't I get the current line?
EDIT: for columnNum (see Eric's comment):
const activeEditor = vscode.window.activeTextEditor
if (activeEditor) {
const lineOffset = activeEditor.selection.active.line
const charOffset = activeEditor.selection.active.character
console.log(`line: ${lineOffset + 1}`)
console.log(`character: ${charOffset + 1}`)
console.log(`column: ${getColumn(activeEditor.document.lineAt(lineOffset).text,charOffset) + 1}`) //column
function getColumn(str, sumCharacter) {
const arr = [...str]
let whichCharacter = 0
for (let whichColumn = 0; whichColumn < arr.length; whichColumn++) {
if (whichCharacter===sumCharacter) {
return whichColumn
}
whichCharacter+=arr[whichColumn].length
}
return arr.length
}
}

I am trying to make some interesting changes to the editing area of vscode. I want to know whether the API supports the following two features?

First, does the vscode editor area support the insertion of some lines, only for display purposes, and does not affect the properties of the editing area itself, such as the line number unchanged. I know that Gitlens can display the relevant information of the author after a certain line, now I want to insert these non-editable information into separate lines.
Second, in the editor area where the breakpoint is marked during debugging (that is, to the left of the line number), can a new column be added to show some messages corresponding to the line? Or can I just modify the line number, add some characters to the left of it?
I have been searching for several days, and I have not found such an interface to call.
Thanks.
The first feature you can have by implementing the CodeLens provider in your codebase. Here is a sample:
export class MyCodeLensProvider implements CodeLensProvider {
async provideCodeLenses(document: TextDocument): Promise<CodeLens[]> {
let location = new Range(0, 0, 0, 0)
let codeLens = new CodeLens(location, {
command: 'say.testCmd',
title: 'Insert console here',
})
return [codeLens];
}
}
Regarding the second feature, you can have icons before the line number by setting gutterIcon, here is a little snippet that I have extracted from my codebase, hope this will give you hint; how to achieve what you were looking:
const todoStyle = {
text: "TODO:",
color: '#fff',
backgroundColor: '#ffbd2a',
overviewRulerColor: 'rgba(255,0,42,0.8)',
dark: {
gutterIconPath: path.join(__filename, '..', '..', 'src', 'resources', 'dark', 'todo.png')
}
}
const fontColorDecorator = vscode.window.createTextEditorDecorationType(style.todoStyle);
/* Ranges */
let ranges: vscode.Range[] = [];
const startPos = new vscode.Position(lineNumber, characterPosition);
const endPos = new vscode.Position(lineNumber, characterPosition);
let singleRange: vscode.Range = new vscode.Range(startPos, endPos);
ranges.push(singleRange);
activeEditor.setDecorations(fontColorDecorator, ranges);
Note: Make sure to adjust the path and set proper ranges. For simplicity, I am only pushing one position in the range array. If you want to have effects on multiple lines then add more ranges accordingly.

Set selection to a string in codemirror

I'm trying to set a text selection in CodeMirror based on a predefined string, similar to a find without prompt (i.e. http://perso.jojaba.fr/codemirror-test/codemirror/demo/search-element.html) except not marking the value, but actually putting a selection on the range (which might be multi line, depending on the predefined string). I can't seem to figure out how to set a selection in this way. Any idea.
well, as it turns out the findNext() offered by searchwithoutdialog.js actually does what I need. effectively it's:
instance.on("change", function (cm, change) {
// other code snipped! //
var str = "my replacement";
var token = cm.getTokenAt(change.from, false);
cm.replaceRange(str, { ch: token.start, line: line }, { ch: token.end, line: line });
CodeMirror.commands.findNext(cm, str);
}

Inserting a new text at given cursor position

I am working on customizing the codemirror for my new language mode. As part of this new mode implementation, I am writing a new tool bar where user can select some text and say insert. This command should insert the text where user was typing just before clicking on tool bar.
I could not find any API level support to do so. If there is any other way can someone help me out on this?
Basically get the current cursor positio- line number and position at which cursor is currently present. May be a Position object
API for inserting a text, something like insertText("Text", PositionObject)
Here's how I did it:
function insertTextAtCursor(editor, text) {
var doc = editor.getDoc();
var cursor = doc.getCursor();
doc.replaceRange(text, cursor);
}
How about replaceSelection (http://codemirror.net/doc/manual.html#replaceSelection)?
doc.replaceSelection(replacement: string, ?select: string)
Replace the selection(s) with the given string. By default, the new selection ends up after the inserted text. The optional select argument can be used to change this—passing "around" will cause the new text to be selected, passing "start" will collapse the selection to the start of the inserted text.
To add the new line at the end -
function updateCodeMirror(data){
var cm = $('.CodeMirror')[0].CodeMirror;
var doc = cm.getDoc();
var cursor = doc.getCursor(); // gets the line number in the cursor position
var line = doc.getLine(cursor.line); // get the line contents
var pos = { // create a new object to avoid mutation of the original selection
line: cursor.line,
ch: line.length - 1 // set the character position to the end of the line
}
doc.replaceRange('\n'+data+'\n', pos); // adds a new line
}
Call function
updateCodeMirror("This is new line");
Improved function that, if selection present, replaces the text, if not, inserts in current cursor position
function insertString(editor,str){
var selection = editor.getSelection();
if(selection.length>0){
editor.replaceSelection(str);
}
else{
var doc = editor.getDoc();
var cursor = doc.getCursor();
var pos = {
line: cursor.line,
ch: cursor.ch
}
doc.replaceRange(str, pos);
}
}
You want to use the replaceRange function. Even though the name says "replace", it also serves as "insert" depending on the arguments. From the documentation at the time I write this:
Replace the part of the document between from and to with the given
string. from and to must be {line, ch} objects. to can be left off to
simply insert the string at position from. When origin is given, it
will be passed on to "change" events, and its first letter will be
used to determine whether this change can be merged with previous
history events, in the way described for selection origins.
Final function to insert text at current cursor position in a performant way.
Hope it helps.
function insertStringInTemplate(str)
{
var doc = editor_template.getDoc();
var cursor = doc.getCursor();
var pos = {
line: cursor.line,
ch: cursor.ch
}
doc.replaceRange(str, pos);
}
This function is used to insert to the specified position and move the cursor to the end of the inserted text.
function insertToCodeMirror(text) {
const doc = codeMirrorInstance.getDoc();
const cursor = codeMirrorInstance.getCursor();
doc.replaceRange(text, cursor);
codeMirrorInstance.focus();
setTimeout(() => {
cursor.ch += text.length;
codeMirrorInstance.setCursor(cursor);
}, 0);
}