VSCode: Extension: folding section based on first blank line found or to the start of the next similar section - visual-studio-code

How can I make a VSCode extension folding strategy based on the first blank line following a starting folding marker?
## Some section --|
Any text... | (this should fold)
...more text. --|
(blank line)
## Another section (next fold...)
I've tried lots of regex in the language-configuration.json.
"folding": {
"markers": {
"start": "^##",
"end": "^\\s*$"
} },
If I change things to test with something other than a blank (or whitespace) line as the end delimiter it works. Can't use the next start marker to mark the end of the last or it includes it in the fold (I tried look ahead regex, but I think the regex are applied line by line and the matches can't span lines?)
It's similar to the folding needed for Markdown which VSCode handles well (don't know if that's using a more complex method like https://code.visualstudio.com/api/references/vscode-api#FoldingRangeProvider).
Maybe something in the fixes for [folding] should not fold white space after function has something to do with it.

What I learned: 1. the begin and end regex are applied line by line. 2. tmLanguage start/end regex will work on blank lines, but currently language-configuration folding doesn't seem to work on blank lines.
And since blank lines are in this case a hack for ending at the next begin section:
To solve the problem of folding a section to the next similar section I used the FoldingRangeProvider.
disposable = vscode.languages.registerFoldingRangeProvider('myExt', {
provideFoldingRanges(document, context, token) {
//console.log('folding range invoked'); // comes here on every character edit
let sectionStart = 0, FR = [], re = /^## /; // regex to detect start of region
for (let i = 0; i < document.lineCount; i++) {
if (re.test(document.lineAt(i).text)) {
if (sectionStart > 0) {
FR.push(new vscode.FoldingRange(sectionStart, i - 1, vscode.FoldingRangeKind.Region));
}
sectionStart = i;
}
}
if (sectionStart > 0) { FR.push(new vscode.FoldingRange(sectionStart, document.lineCount - 1, vscode.FoldingRangeKind.Region)); }
return FR;
}
});
Set "editor.foldingStrategy": "auto". You can make it more sophisticated to preserve white space between sections.

Related

Add different number of spaces to multiple lines so that each line has equal amount of characters

Is there an easy way to add spaces to multiple lines so that each line has equal amount of characters?
Motivation, say I want to add '*' at end of each line
/***************************
* This is line 1. *
* Line2. *
* May be line3. *
* For sure this is line 4. *
****************************/
Without using any custom format program, is there a way in VS code to add different number of spaces just before the last '*' like so:
/***************************
* This is line 1. *
* Line2 *
* May be line3 *
* For sure this is line 4. *
****************************/
select all the * at the lines that are incorrect
add as much spaces as needed to get all *'s beyond the correct position
Esc to get out of multi cursor
Place Multi Cursor on all lines at the position where you want the *'s
press Ctrl+Delete
Esc to get out of multi cursor
You can do this fairly simply with an extension I wrote, Find and Transform, because it allows you to use javascript or the vscode extension api in a replacement. So starting with this text:
/***************************
* This is line 1.
* Line2.
* May be line3.
* For sure this is line 4.
****************************/
you would make this keybinding (in your keybindings.json):
{
"key": "alt+q", // whatever keybinding you want
"command": "findInCurrentFile",
"args": {
"replace": [
"$${",
"const str = `${selectedText}`;", // get the selected text
// since the selected text can contain newlines, surround the variable with backticks
"let lineArray = str.split('\\n');", // newlines must be double-escaped
"let firstLineLength = lineArray[0].length;",
"lineArray = lineArray.map((line, index) => {",
"if (index === 0) return line;",
"else if (line === lineArray.at(lineArray.length-1)) return line;",
"else return `${line.padEnd(firstLineLength-1, ' ')}*`;",
"});",
"return lineArray.join('\\n');",
"}$$"
]
}
}
So the replacement is straightforward javascript which gets the selected text, splits it on the newlines and then uses the length of the first line to pad the other lines with spaces and then adds a * to the end of each line. It does nothing to the first or last line of the selection.
Demo:
You can do multiple selections at a time too.

iText PDFSweep RegexBasedCleanupStrategy not work in some case

I'm trying to use iText PDFSweep RegexBasedCleanupStrategy to redact some words from pdf, however I only want to redact the word but not appear in other word, eg.
I want to redact "al" as single word, but I don't want to redact the "al" in "mineral".
So I add the word boundary("\b") in the Regex as parameter to RegexBasedCleanupStrategy,
new RegexBasedCleanupStrategy("\\bal\\b")
however the pdfAutoSweep.cleanUp not work if the word is at the end of line.
In short
The cause of this issue is that the routine that flattens the extracted text chunks into a single String for applying the regular expression does not insert any indicator for a line break. Thus, in that String the last letter from one line is immediately followed by the first letter of the next which hides the word boundary. One can fix the behavior by adding an appropriate character to the String in case of a line break.
The problematic code
The routine that flattens the extracted text chunks into a single String is CharacterRenderInfo.mapString(List<CharacterRenderInfo>) in the package com.itextpdf.kernel.pdf.canvas.parser.listener. In case of a merely horizontal gap this routine inserts a space character but in case of a vertical offset, i.e. a line break, it adds nothing extra to the StringBuilder in which the String representation is generated:
if (chunk.sameLine(lastChunk)) {
// we only insert a blank space if the trailing character of the previous string wasn't a space, and the leading character of the current string isn't a space
if (chunk.getLocation().isAtWordBoundary(lastChunk.getLocation()) && !chunk.getText().startsWith(" ") && !chunk.getText().endsWith(" ")) {
sb.append(' ');
}
indexMap.put(sb.length(), i);
sb.append(chunk.getText());
} else {
indexMap.put(sb.length(), i);
sb.append(chunk.getText());
}
A possible fix
One can extend the code above to insert a newline character in case of a line break:
if (chunk.sameLine(lastChunk)) {
// we only insert a blank space if the trailing character of the previous string wasn't a space, and the leading character of the current string isn't a space
if (chunk.getLocation().isAtWordBoundary(lastChunk.getLocation()) && !chunk.getText().startsWith(" ") && !chunk.getText().endsWith(" ")) {
sb.append(' ');
}
indexMap.put(sb.length(), i);
sb.append(chunk.getText());
} else {
sb.append('\n');
indexMap.put(sb.length(), i);
sb.append(chunk.getText());
}
This CharacterRenderInfo.mapString method is only called from the RegexBasedLocationExtractionStrategy method getResultantLocations() (package com.itextpdf.kernel.pdf.canvas.parser.listener), and only for the task mentioned, i.e. applying the regular expression in question. Thus, enabling it to properly allow recognition of word boundaries should not break anything but indeed should be considered a fix.
One merely might consider adding a different character for a line break, e.g. a plain space ' ' if one does not want to treat vertical gaps any different than horizontal ones. For a general fix one might, therefore, consider making this character a settable property of the strategy.
Versions
I tested with iText 7.1.4-SNAPSHOT and PDFSweep 2.0.3-SNAPSHOT.

How to stop VS Code forcing me to use braces, otherwise the cursor position goes crazy (PHP, or apply it globally)

VS Code
if (1 == 1) // When I hit enter here, the cursor moves to the next line at pos (0)
|
else
return; // When I hit enter here, cursor moves to next line/ pos 4
| // why is the cursor here? why not pos 0?
Visual Studio (this is what I want to happen)
if (1 == 1) // When I hit enter here, the cursor moves to the next line at
| // pos 1 if I'm working with Tabs or pos 4 for spaces)
This is not a problem in VS Code if you use braces like this:
if (1 == 1){
return;
}
However, I don't like to use braces in those scenarios, and if I don't, VS Code naturally makes me end up writing this code which is also bad
if (1 == 1)
return;
I'm trying to get the same behaviour in VS Code. I can't seen to find a setting for this, or an extension. Please help. If I have to make an extension, or update the VS Code source and build it myself, I'm up for that, just please point me to the right direction. This is annoying.
You can create code snippet. F1 "usn" => choose language >>
"if": {
"prefix": "if",
"body": [
"if ($1)",
"\t$2",
"$3"
]
},
"ifelse": {
"prefix": "ifelse",
"body": [
"if ($1)",
"\t$2",
"else",
"\t$3",
"$4"
]
},
Just in case add this to settings.json ctrl+,:
"editor.snippetSuggestions": "top",

find all lines that begin with `console` in notepad++

How do I find all lines that begin with console in notepad++?
there can be zero to any number of spaces or tabs before the word console
suppose i have a file as follows:
'createdRow': function (row, data, index) {
console.log("data is: "); console.log(data);
fields=Object.keys(data)
console.log("fields is: "); console.log(fields);
noOfFields=fields.length
console.log("noOfFields is: "); console.log(noOfFields);
var highlightVal = 80;
var highlightClassName = 'highlight';
var counterIndexCount = 4;
for (var i=1; i <= counterIndexCount; i++) {
if (parseInt(data['counter'+ i].substring(0,2), 10) >= highlightVal) {
$('td', row).eq(i).addClass(highlightClassName);
} else {
$('td', row).eq(i).removeClass(highlightClassName);
}
}
I thought I might have to do something like \n console using the Extended option in the bottom left of the find search. But could not get it to work.
for my reference:
similar q asked here
Do a regex (regular expression) search for this:
^( |\t)*console
The ^ matches the start of the line; ( |\t)* matches any number of tabs or spaces; and console, of course, matches the text you're looking for.
If you want to match the whole line, add .* at the end:
^( |\t)*console.*
Type Ctrl+H
Then in the search window:
Find what: ^\s*console\b
then click on Find All in Current Document
You'll find the lines in the find result window.
^ : Begining of line
\s* : 0 or more any kind of space character
console : literally 'console'
\b : word boundary to make sure that is not matching 'consolefoobar'

How can I adjust indentation of my c source code in the entire selected block all at once?

I'd like to adjust indentation of my source code correctly at a time after I select some block of it.
Is there any function or key with which I can do it including parenthesis?
Here is original selected block of sample code I'd like to adjust indentation.
while(1)
{
func1();
if( )
{
func2();
}
}
if( x == 0 )
{
aa = 1;
}
This would be the correctly indented code how I just want to adjust.
while(1)
{
func1();
if( )
{
func2();
}
}
if( x == 0 )
{
aa = 1;
}
Select your code and press C-M-\, which should be bound to indent-region:
C-M-\
Indent all the lines in the region, as though you had typed TAB at the beginning of each line (indent-region).
If a numeric argument is supplied, indent every line in the region to that column number.
I'm using evil mode because I like vim editing keymap.
In my case, block auto indentation can be done by equal(=) key after selecting a code block.
It's very convenient to rearrange block of code in a c-default-style.
(1) install evil package
(2) Insert this code into you emacs init file.
; indentation style for c, c++, java
(setq c-default-style "linux"
c-basic-offset 4)
(3) select block using v and direction key
(4) press '='