When folding a line in VS Code is it possible to override the indentation and choose which lines are included in that fold? - visual-studio-code

Is it possible to customize the way code folding works in Visual Studio Code?
I use a common pattern of defining regions of code across a variety of different document types.
So, for XML I wrap sections of text with <!-- #region --> and <!-- #endregion -->
For c#, I use #region to #endregion,
For TypeScript/Javascript, I use /* #region */ and /* #endregion */.
In full Visual Studio (not VS Code), I have a custom extension which snoops for the pattern across document types, and creates folds based on that, allowing me to create neat, custom document outlines. I'd like to use the same pattern in Visual Studio Code. Is it possible to create a custom VS Code extension which detects these comment patterns, and somehow tags folds based on the patterns?

FoldingRangeProvider can be used if you are looking to contribute custom folding logic in an extension.
Be sure to set your VS Code version in engines in package.json to 1.23, the version that introduced this.
Here's how you'd use one.
export function activate(context: ExtensionContext) {
languages.registerFoldingRangeProvider({ scheme: 'file', language: 'markdown' }, new MyFoldingRangeProvider());
}
class MyFoldingRangeProvider implements FoldingRangeProvider {
provideFoldingRanges(document: TextDocument, context: FoldingContext, token: CancellationToken): FoldingRange[] {
return detectRanges().map(({ lineStart, lineEnd }) => new FoldingRange(lineStart, lineEnd));
}
}

On August 6th 2022 the feature "Fold Selection" was added to "V.S. Code" as part of the sem-minor v1.70.0 release. This new feature gives users complete control over line folds, by total I mean, when & where. Fold Selection allows you to fold whatever code you want, wherever you want.
Below is a GIF image that was appended to the official v1.70.0 release notes
I copy & pasted this image because..,
A. The image shows how the new feature works, and...
B. because it shows that the feature works much like line folding does in IDEs — i.e. VS-22, Intelli-J, CLion, etc...
V.S. Code is actually the first editor I ever used, and I stuck with it for the last 5 years, but one thing I noticed on day 1 of test driving V.S. Code was that it did not have this feature.
Using the new Fold Selection Feature
You can use the feature via the quick input, just type "Fold Selection" until the option pops up for you to select, however, I perfer customizing a keybinding for it.
Here is the default configuration for fold selection in the default keyboard shortcuts JSON document:
{
"key": "ctrl+k ctrl+,",
"command": "editor.createFoldingRangeFromSelection",
"when": "editorTextFocus && foldingEnabled"
}
How to configure the above snippet is beyond the scope of this post, but I suggest keeping the when statement as it is configured above (which is the default).
You can use the keybinding shown in the JSON snippet w/o any configuration, which would be:
CTRL + K CTRL+,
...however, vscode has to attach most all commands to some keyboard shortcut. Most people cannot remember all of the commands and shortcuts, so for features you use often, it makes since to attach it to more practicle option, I like to use something like
CTRL + SHIFT + SPACE SPACE
Its almost like quickly pressing space twice.
Anyways, this is a far better option than what was available before, cheers!
CLICK HERE TO READ THE OFFICIAL RELEASE NOTES

There are three ways to achieve customized folding in a VSCode extension.
You can define regex as folding markers in a [language-name].configuration.json file. (However, we don't have much customization with this approach)
{
"folding": {
"markers": {
"start": "starting regex",
"end": "ending regex"
}
}
}
You can define a FoldingRangeProvider from within the extension as described in this answer. FoldingRange in vscode package supports folding customization with startLine, endLine, and foldingKind.
You can use Language Server support with textDocument/foldingRange. FoldingRange in the vscode-languageserver-protocol supports folding customization with startLine, endLine, startCharacter, endCharacter, and foldingKind.
Check this for more details.

Unfortunately, not at the moment. There is a an open issue in github for this very topic.

Related

Markdown code block highlight consistency - what is "s" alias

The built-in markdown editor has a "live-preview" for code blocks without open a side previewer.
I was looking for a list of supported language highlight, which as I understand is defined by highlight.js supported language.
I need to add some "ssh config files" in my markdown, but
when I use properties language tag, only side previewer shows the highlight, not the editor itself
when I try with a weird "s" language alias, the editor can detect the comments and non-alphabetic characters. But the side previewer shows nothing...
VSCode screenshot:
My questions:
"s" is not defined as an alias in highlight.js, then how come the editor can detect the language?
Why the editor and previewer do not have the same highlight behavior?
I prefer to have the correct highlight in editor, which language/alias should I use in place of "properties"?
Summarizing previous comments and answers here:
VScode markdown "in-editor" code highlight use "markdown-basic" extension, with a list of supported languages in this file
The "alias" for different languages are "hidden" in the regex of each block definition. for example for R language the alias is R|r|s|S|Rprofile|\\{\\.r.+?\\}. (I extract a complete list of aliases from the source codes and it is shown below)
More specifically for what I want, i.e. key-value pair config file equivalent to properties in highlight.js, there is no exact the same in "markdown-basic", so I will use conf.
Developer: Inspect Editor Tokens and Scopes helps a lot when you see a unfamiliar alias and want to know what it is
List of code block languages aliases for "markdown-basic":
bat|batch
bibtex
c|h
clj|cljs|clojure
coffee|Cakefile|coffee.erb
COMMIT_EDITMSG|MERGE_MSG
cpp|c\\+\\+|cxx
cs|csharp|c#
css|css.erb
dart
dockerfile|Dockerfile
elixir
erlang
fs|fsharp|f#
git-rebase-todo
go|golang
groovy|gvy
handlebars|hbs
html|htm|shtml|xhtml|inc|tmpl|tpl
ini|conf
jade|pug
java|bsh
js|jsx|javascript|es6|mjs|cjs|\\{\\.js.+?\\}
json|json5|sublime-settings|sublime-menu|sublime-keymap|sublime-mousemap|sublime-theme|sublime-build|sublime-project|sublime-completions
jsonc
latex|tex
less
log
lua
Makefile|makefile|GNUmakefile|OCamlMakefile
markdown|md
objectivec|objective-c|mm|objc|obj-c|m|h
patch|diff|rej
perl|pl|pm|pod|t|PL|psgi|vcl
perl6|p6|pl6|pm6|nqp
php|php3|php4|php5|phpt|phtml|aw|ctp
powershell|ps1|psm1|psd1
python|py|py3|rpy|pyw|cpy|SConstruct|Sconstruct|sconstruct|SConscript|gyp|gypi|\\{\\.python.+?\\}
R|r|s|S|Rprofile|\\{\\.r.+?\\}
re
regexp
ruby|rb|rbx|rjs|Rakefile|rake|cgi|fcgi|gemspec|irbrc|Capfile|ru|prawn|Cheffile|Gemfile|Guardfile|Hobofile|Vagrantfile|Appraisals|Rantfile|Berksfile|Berksfile.lock|Thorfile|Puppetfile
rust|rs|\\{\\.rust.+?\\}
scala|sbt
scss
shell|sh|bash|zsh|bashrc|bash_profile|bash_login|profile|bash_logout|.textmate_init|\\{\\.bash.+?\\}
sql|ddl|dml
swift
tsx
typescript|ts
vb
xml|xsd|tld|jsp|pt|cpt|dtml|rss|opml
xsl|xslt
yaml|yml
I don't believe VSCode's native syntax highlighting has anything to do with highlight.js. It is provided by language-specific extensions, some of which ship with the editor.
In this case, VSCode is using its built-in R mode for that code block. You can see the language being used via Developer: Inspect Editor Tokens and Scopes in the command palette. R is an open-source implementation of the language S, so this makes sense.
The Markdown preview, on the other hand, may well use highlight.js and you are right that s is meaningless there.
I don't see a good language code to use in your code fence, but will update this answer if I find one.

Is there a way to select code between certain characters

TL DR
Is there some extension, or other functionality, to select code above and below the cursor that is surrounded by some characters, e.g. %% or % ===== or anything else?
Why
I am coding Matlab in VSCode, since the builtin Matlab editor lacks a lot of useful functionalities. However, One thing that I miss is the ability to run 'sections':
%% section 1
x = 0:0.01:pi;
y = sin(y);
plot(x,y);
%% section 2
x = 0:0.01:pi;
y = cos(y);
plot(x,y);
%% section 3
x = 0:0.01:pi;
y = tan(y);
plot(x,y);
A section can be run using Ctrl+Enter. Since I use Matlab on Windows, there is no support for running the Matlab interpreter from the terminal/cmd.
So I created some AutoHotKey scripts that will copy selected code, open the Matlab window, paste it, and run. This works fine, however, when I want to run a very large section, this means that I have to select this manually, and press my defined shortcut to call the AutoHotkey script. Hence above question.
So say I have the cursor at some line insection 2, how can I select only the code in this section (including or excluding section 'headers', these are comments so does not matter).
I have made an extension Select By that allows the selection based on regular expressions relative to the cursor position. You can specify different expressions for forward and backward search and if you want to include the searched text in the selection.
You can set up to 5 regex searches.
The extension defines 5 commands that can be used in keyboard shortcuts
This can (of course) be done by writing a custom extension.
Since this seems like useful functionality in general and an interesting exercise, I've added the required capability to my personal vscode-smcpeak extension.
To use it:
Install vscode-smcpeak. This has to be installed manually for now. At time of writing, 0.0.7 is latest.
Install macros by ctf0. This one can be installed from within VSCode. Restart VSCode after installing it. (See below regarding the choice of "macros" extension.)
Add to your settings.json (File → Preferences → Settings, then click the "Open Settings (JSON)" icon in the upper right):
// Custom macros for ctf0.macros extension
"macros.list": {
// https://stackoverflow.com/questions/57749780/is-there-a-way-to-select-code-between-certain-characters
"selectPercentRegion": [
{
"command": "smcpeak.goToLineMatching",
"args": {
"regex": "^%%",
"moveUp": true,
"select": false,
"allowZeroMove": true
}
},
{
"command": "smcpeak.goToLineMatching",
"args": {
"regex": "^%%",
"moveUp": false,
"select": true,
"allowZeroMove": false
}
},
"smcpeak.revealCurrentSelection"
]
},
Add to keybindings.json (File → Preferences → Keyboard Shortcuts, then click the "Open Keyboard Shortcuts (JSON)" icon in the upper right):
{
"key": "ctrl+alt+m", // or whatever
"command": "macros.selectPercentRegion"
},
(Note: VSCode will always complain that macros.selectPercentRegion is not a valid command. That's a limitation of the "macros" extension.)
Then, with the cursor within a region delimited by the specified regexes, press the keybinding to activate the macro:
Why use two extensions?
The accepted answer, by rioV8 uses a single extension to answer the OP's question. This looks like a good solution to me, and is simpler to use than mine, so I approve of that being the accepted answer.
However, there is an advantage to my approach: it allows the behavior to be modified in settings.json. For example, the OP asked in a follow-up question about having the command additionally copy the text to the clipboard after selecting. Using the macro-based solution, this is an easy modification to settings.json; simply add:
"editor.action.clipboardCopyAction"
to the end of the selectPercentRegion macro. (That is the command normally bound to Ctrl+C.)
Thus, while my suggestion has more moving parts, I personally prefer this approach.
Which macros extension to use?
As Mark noted in a comment, the most popular macros extension, geddski.macros, is unmaintained. It furthermore has a rather serious bug in that the commands are not properly sequenced, leading to race conditions. (I actually saw this once during my testing.)
There are two forks of geddski.macros on the marketplace, l7ssha.macrosRe and ctf0.macros. l7ssha.macrosRe only adds the "delay" ability, which is an awkward way to resolve the race conditions. ctf0.macros, on the other hand, fully fixes the race condition (via a complete rewrite).
Therefore, I recommend ctf0.macros, and in fact have edited my answer to use it rather than the original geddski.macros extension.
However, be aware:
ctf0.macros uses macros.list rather than macros in settings.json
ctf0.macros requires a restart of VSCode after installation to activate
How it works
The additions are in vscode-smcpeak commit 6d5f5d4689.
My extension registers a new command, smcpeak.goToLineMatching, that searches up or down for a line containing a regex. The logic is very simple, just a loop and regex test.
It also registers smcpeak.revealCurrentSelection, needed because otherwise the selected text might be offscreen and nothing scrolls to it by default.
The macro selectPercentRegion uses goToLineMatching to look upwards for one regex, setting the anchor (selection start) there, then uses it again to look down for another regex (although they are the same here), extending the selection to that point. Then it scrolls to ensure the selection is visible.
It should be straightforward to transplant this code to your own extension if you don't want the rest of the stuff that mine provides. (But mine does not bind any keys, so there should be no downside to having the extra stuff.)
Here is another way to do this, with an extension I wrote Find and Transform.
Make this keybinding in your keybindings.json (or it could be a setting too):
{
"key": "alt+m", // whatever keybinding you want
"command": "findInCurrentFile",
"args": {
"find": "^(%%[\\s\\S]+?)(?=^$)|(^%%[\\s\\S]+)",
"run": [
"$${",
"const sections = vscode.window.activeTextEditor.selections;",
"await vscode.commands.executeCommand('cursorUndo');",
"const mySection = sections.find(section => section.contains(vscode.window.activeTextEditor.selection));",
"if (mySection) {",
"vscode.window.activeTextEditor.selections = [mySection];"
"}",
"}$$",
],
"isRegex": true,
"postCommands": "editor.action.clipboardCopyAction"
}
}
The find regex finds and selects all %% .... sections. But since you only want the section where your cursor started, some code is run to restore that original cursor and then find that section that contains the one current cursor. Then that section is selected. And in the postCommand that selection is saved to the clipboard.
That is using javascript and the vscode extension api within a keybinding or setting.

How to create keybinding that reindents only selected lines in Visual Code

I'm using Visual Studio Code 1.14 on MacOS and have tried creating my own keybinding that re-indents only the lines of code that I've highlighted.
I have this in keybindings.json:
[
{
"key": "alt+cmd+[", "command": "editor.action.reindentlines",
"when": "editorHasSelection && editorTextFocus"
}
]
I chose the commands for the "when": clause based on this article.
The Problem: When I use my custom keyboard shortcut, it re-indents the entire page instead of only the text I've selected.
It's petty, perhaps, but this can cause a formatting nightmare, such as when writing a ReactJS app where VSC's regex pattern for detecting how to indent lines seems to get confused when looking at a mix of javascript and html within a .jsx file. In such cases I only want to re-indent/auto-indent the text I choose - not the entire page.
How can I get the keybinding to function with the behavior I'm looking for?
The when-clause can only change when the command is active - not how it behaves. The issue is that the implementation of the command operates on the whole file, rather than the current selection.
I don't think reindentation of a selection is supported yet, but it seems to be on the roadmap. For instance, it was mentioned in #19847 (emphasis mine):
The reason that right now we don't support Reindent in ranges is that we have some issues with boundaries in embedded-language files. Some of them are just TextMate Grammar issues but I'm sure if that can fix all. Once that issue is addressed, I think it's easy to support reindent in ranges/selection. And then Reindent when paste/moveLines/etc.
Thanks to #Gama11 for pointing me to this github issue.
The solution that accomplishes what I was trying to do is to use the command editor.action.formatSelection instead of editor.action.redindentlines.
As shown by Gama11, reindent in ranges isn't currently supported, however Format Selection is a very similar command that uses different logic to accomplish indentation within a certain range.

How do you hide arbitrary section of code in VS Code?

By "VS Code" I mean the lightweight text editor not the monolithic IDE, unfortunately searching this on google will bring up many pieces of irrelevant information about how to do this in Visual Studio.
To the question itself, Anybody knows how to hide arbitrary selected lines of code in "Visual Studio Code", preferably into a plus sign like collapsing does?
Note: this is different than collapsing nested code which probably could be achieved by Ctrl+K,Ctrl+<num> , what I need here is to hide specific block of code of choice, no matter nested or not.
EDIT: I see there are people who don't understand my requirements.
for example, you may think what I want is this:
before hiding:
for i in j:
for k in i:
for l in k:
somestuff...
after hiding:
[+] for i in j: ...
What I actually want is this:
before hiding:
# doing stuff about a
a = ClassA()
a.bar()
a.i = 2
a.j = 3
a.k = 5
after hiding:
[+] ... ( doing stuff about a )
2017.10.17 EDIT:
turns out VS Code implemented a very similar feature called "Folding Regions" in VS Code 1.17.1 Update. link
You can use the following delimiters for code folding:
C/C++: #pragma region and #pragma endregion
C#: #region and #endregion
CSS: /* #region */ and /* #endregion */
Java: //region and //endregion
JavaScript: //#region and //#endregion and //region and //endregion
PHP: #region and #endregion
Powershell: #region and #endregion
Python: #region and #endregion
VB: #Region and #End Region
See https://github.com/Microsoft/vscode/issues/12146 ([folding] fold regions)
In the Insiders Build v1.70 now is the functionality and command to truly hide arbitrary lines of code. The command is
Create Manual Folding Range from Selection
editor.createFoldingRangeFromSelection
It is bound to Ctrl+K Ctrl+, by default. Select any lines you want to fold.
You can unfold those lines either by clicking the gutter folding controls or this command when the cursor is somewhere on the folded line:
Remove Manual Folding Ranges
editor.removeManualFoldingRanges
The above command is bound to Ctrl+K Ctrl+. by default.
Unfortunately, it doesn't appear that VSCode currently allows you to hide an arbitrary selection of code like Visual Studio does via Ctrl+M,Ctrl+H. For now you could use the code folding feature, which depends on indentation. That is, if you indent the code you want to hide, you could then collapse it via Ctrl+Shift+[, like so:
Obviously, this is kind of an ugly solution to your problem; it requires multiple steps and makes actual changes to the file. Also, it's clearly useless if you're writing in a whitespace-dependent language like Python, but I don't think you are going to find a better solution short of finding an extension (or writing one yourself). It also might be worth posting an issue on the official VSCode GitHub repo if this feature is important to you.
Here is the vs code documentation for folding a selection.
To hide: Highlight the lines you want to fold then press Ctrl+K then Ctrl+,
To unhide: Just click the ">" icon to the left of the row of the folded code or press Ctrl+K then Ctrl+.
Comment with a delimiter with decreased indentation.
Hiding then works as in nested, with the little arrow on the left.
see here
# Below here comes the code to hide.
a = ClassA()
a.bar()
a.i = 2
a.j = 3
a.k = 5

How to filter files shown in Visual Studio Code?

How would you filter the files shown in the folder view in Visual Studio Code?
Reference: Filter files shown in folder
Hiding files and folders
The files.exclude setting lets you define patterns to hide files and folders from several places in VS Code like the explorer and search. Once defined, files and folders matching any of the patterns will be hidden.
{
"files.exclude": {
"**/*.js": true
}
}
Hide derived resources
If you use a language that compiles to another file at the same location of the source file, like TypeScript does to JavaScript, you can easily set an expression to hide those derived files:
"**/*.js": { "when": "$(basename).ts"}
Such a pattern will match on any JavaScript file (**/*.js), but only if a sibling file with the same name and extension, *.ts in this example, is present. The same technique can be used for other transpiled languages, like Coffee Script or Less/Sass, too.
Source: VS Code v0.5.0 (July 2015)
In version after VScode 1.70 (July 2022) all you need to do is press Ctrl+F or F3 to search.
Please refer following post
Searching in Explorer panel after VSCode 1.70
Only applicable for v1.69 and below.
Step #1
Click on Explorer window. This is critical as without focus on Explorer it will not work.
Step #2
Start Typing name you want to filter. It's weird that there is no textbox to take input but... take a leap of faith and type. You will see your typed text in top-right corner in brown background. Now hover on that text.
Step #3
Click on 3 stacked lines to filter..
They look like hamburger menu but they are not. They are saying if it's filtered or not. They are toggled between filtered and just highlight. So, make sure they are like inverted pyramid.
That's it. It should be filtered now.
If you only want to change the setting for this project, then do the following:
File > Save Workspace As > ... enter your {project name}
Then open file: {project name}.code-workspace
And update section settings.
Sample:
{
"folders": [
{
"path": "."
}
],
"settings": {
"files.exclude": {
"**/*.log": true
}
}
}
VScode 1.70 (July 2022) should improve on this "tree filter" feature.
(Available today in Code insiders)
See issue 70646 and PR 152481:
Support find widget in lists/trees
This PR replaces the existing list/tree type filter:
with an bona fide find widget:
While a seemingly simple change, this has some (desired) consequences when searching/filtering in trees. Namely:
We will restore simple keyboard navigation by default.
That is: pressing the letter A will focus the next element which starts with A.
Initiating a search operation requires pressing Ctrl-F or F3, like the editor.
While searching, focus is in the find input box as opposed to the list itself.
Pressing DownArrow will focus the first list element which was found.
We'll preserve all custom behavior of context keys, eg. used by the VIM extension).
In VIM, the pre-existing / command will trigger simple keyboard navigation, as opposed to opening the find widget.
The VIM extension has the option to change this behavior themselves.
And:
In general:
Keyboard navigation is now called type navigation
Filter on type is now called find mode, aligned with a new find concept
Settings
workbench.list.keyboardNavigation has been renamed to workbench.list.defaultFindMode
workbench.list.automaticKeyboardNavigation has been deleted
Commands
list.toggleKeyboardNavigation has been renamed to list.triggerTypeNavigation
list.find has been added
list.closeFind has been added
list.toggleFilterOnType has been renamed to list.toggleFindMode
Context Keys
Mainly used by the vim extension:
listSupportsKeyboardNavigation has been renamed to listSupportsTypeNavigation
listAutomaticKeyboardNavigation has been renamed to listTypeNavigationMode
"With the focus on the File Explorer start to type part of the file name you want to match.You will see a filter box in the top-right of the File Explorer showing what you have typed so far and matching file names will be highlighted."
"Hovering over the filter box and selecting Enable Filter on Type will show only matching files/folders."
documentation: https://code.visualstudio.com/docs/getstarted/userinterface#_filtering-the-document-tree