123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970 |
- /*---------------------------------------------------------------------------------------------
- * Copyright (c) Microsoft Corporation. All rights reserved.
- * Licensed under the MIT License. See License.txt in the project root for license information.
- *--------------------------------------------------------------------------------------------*/
- var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
- var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
- if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
- else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
- return c > 3 && r && Object.defineProperty(target, key, r), r;
- };
- var __param = (this && this.__param) || function (paramIndex, decorator) {
- return function (target, key) { decorator(target, key, paramIndex); }
- };
- import { createCancelablePromise, Delayer, RunOnceScheduler } from '../../../base/common/async.js';
- import { onUnexpectedError } from '../../../base/common/errors.js';
- import { KeyChord } from '../../../base/common/keyCodes.js';
- import { Disposable, DisposableStore } from '../../../base/common/lifecycle.js';
- import { escapeRegExpCharacters } from '../../../base/common/strings.js';
- import * as types from '../../../base/common/types.js';
- import './folding.css';
- import { StableEditorScrollState } from '../../browser/core/editorState.js';
- import { EditorAction, registerEditorAction, registerEditorContribution, registerInstantiatedEditorAction } from '../../browser/editorExtensions.js';
- import { EditorContextKeys } from '../../common/editorContextKeys.js';
- import { FoldingRangeKind, FoldingRangeProviderRegistry } from '../../common/modes.js';
- import { LanguageConfigurationRegistry } from '../../common/modes/languageConfigurationRegistry.js';
- import { FoldingModel, getNextFoldLine, getParentFoldLine as getParentFoldLine, getPreviousFoldLine, setCollapseStateAtLevel, setCollapseStateForMatchingLines, setCollapseStateForRest, setCollapseStateForType, setCollapseStateLevelsDown, setCollapseStateLevelsUp, setCollapseStateUp, toggleCollapseState } from './foldingModel.js';
- import { HiddenRangeModel } from './hiddenRangeModel.js';
- import { IndentRangeProvider } from './indentRangeProvider.js';
- import { ID_INIT_PROVIDER, InitializingRangeProvider } from './intializingRangeProvider.js';
- import * as nls from '../../../nls.js';
- import { IContextKeyService, RawContextKey } from '../../../platform/contextkey/common/contextkey.js';
- import { editorSelectionBackground, iconForeground, registerColor, transparent } from '../../../platform/theme/common/colorRegistry.js';
- import { registerThemingParticipant, ThemeIcon } from '../../../platform/theme/common/themeService.js';
- import { foldingCollapsedIcon, FoldingDecorationProvider, foldingExpandedIcon } from './foldingDecorations.js';
- import { ID_SYNTAX_PROVIDER, SyntaxRangeProvider } from './syntaxRangeProvider.js';
- const CONTEXT_FOLDING_ENABLED = new RawContextKey('foldingEnabled', false);
- let FoldingController = class FoldingController extends Disposable {
- constructor(editor, contextKeyService) {
- super();
- this.contextKeyService = contextKeyService;
- this.localToDispose = this._register(new DisposableStore());
- this.editor = editor;
- const options = this.editor.getOptions();
- this._isEnabled = options.get(37 /* folding */);
- this._useFoldingProviders = options.get(38 /* foldingStrategy */) !== 'indentation';
- this._unfoldOnClickAfterEndOfLine = options.get(41 /* unfoldOnClickAfterEndOfLine */);
- this._restoringViewState = false;
- this._currentModelHasFoldedImports = false;
- this._foldingImportsByDefault = options.get(40 /* foldingImportsByDefault */);
- this.foldingModel = null;
- this.hiddenRangeModel = null;
- this.rangeProvider = null;
- this.foldingRegionPromise = null;
- this.foldingStateMemento = null;
- this.foldingModelPromise = null;
- this.updateScheduler = null;
- this.cursorChangedScheduler = null;
- this.mouseDownInfo = null;
- this.foldingDecorationProvider = new FoldingDecorationProvider(editor);
- this.foldingDecorationProvider.autoHideFoldingControls = options.get(98 /* showFoldingControls */) === 'mouseover';
- this.foldingDecorationProvider.showFoldingHighlights = options.get(39 /* foldingHighlight */);
- this.foldingEnabled = CONTEXT_FOLDING_ENABLED.bindTo(this.contextKeyService);
- this.foldingEnabled.set(this._isEnabled);
- this._register(this.editor.onDidChangeModel(() => this.onModelChanged()));
- this._register(this.editor.onDidChangeConfiguration((e) => {
- if (e.hasChanged(37 /* folding */)) {
- this._isEnabled = this.editor.getOptions().get(37 /* folding */);
- this.foldingEnabled.set(this._isEnabled);
- this.onModelChanged();
- }
- if (e.hasChanged(98 /* showFoldingControls */) || e.hasChanged(39 /* foldingHighlight */)) {
- const options = this.editor.getOptions();
- this.foldingDecorationProvider.autoHideFoldingControls = options.get(98 /* showFoldingControls */) === 'mouseover';
- this.foldingDecorationProvider.showFoldingHighlights = options.get(39 /* foldingHighlight */);
- this.triggerFoldingModelChanged();
- }
- if (e.hasChanged(38 /* foldingStrategy */)) {
- this._useFoldingProviders = this.editor.getOptions().get(38 /* foldingStrategy */) !== 'indentation';
- this.onFoldingStrategyChanged();
- }
- if (e.hasChanged(41 /* unfoldOnClickAfterEndOfLine */)) {
- this._unfoldOnClickAfterEndOfLine = this.editor.getOptions().get(41 /* unfoldOnClickAfterEndOfLine */);
- }
- if (e.hasChanged(40 /* foldingImportsByDefault */)) {
- this._foldingImportsByDefault = this.editor.getOptions().get(40 /* foldingImportsByDefault */);
- }
- }));
- this.onModelChanged();
- }
- static get(editor) {
- return editor.getContribution(FoldingController.ID);
- }
- /**
- * Store view state.
- */
- saveViewState() {
- let model = this.editor.getModel();
- if (!model || !this._isEnabled || model.isTooLargeForTokenization()) {
- return {};
- }
- if (this.foldingModel) { // disposed ?
- let collapsedRegions = this.foldingModel.isInitialized ? this.foldingModel.getMemento() : this.hiddenRangeModel.getMemento();
- let provider = this.rangeProvider ? this.rangeProvider.id : undefined;
- return { collapsedRegions, lineCount: model.getLineCount(), provider, foldedImports: this._currentModelHasFoldedImports };
- }
- return undefined;
- }
- /**
- * Restore view state.
- */
- restoreViewState(state) {
- let model = this.editor.getModel();
- if (!model || !this._isEnabled || model.isTooLargeForTokenization() || !this.hiddenRangeModel) {
- return;
- }
- if (!state || state.lineCount !== model.getLineCount()) {
- return;
- }
- this._currentModelHasFoldedImports = !!state.foldedImports;
- if (!state.collapsedRegions) {
- return;
- }
- if (state.provider === ID_SYNTAX_PROVIDER || state.provider === ID_INIT_PROVIDER) {
- this.foldingStateMemento = state;
- }
- const collapsedRegions = state.collapsedRegions;
- // set the hidden ranges right away, before waiting for the folding model.
- if (this.hiddenRangeModel.applyMemento(collapsedRegions)) {
- const foldingModel = this.getFoldingModel();
- if (foldingModel) {
- foldingModel.then(foldingModel => {
- if (foldingModel) {
- this._restoringViewState = true;
- try {
- foldingModel.applyMemento(collapsedRegions);
- }
- finally {
- this._restoringViewState = false;
- }
- }
- }).then(undefined, onUnexpectedError);
- }
- }
- }
- onModelChanged() {
- this.localToDispose.clear();
- let model = this.editor.getModel();
- if (!this._isEnabled || !model || model.isTooLargeForTokenization()) {
- // huge files get no view model, so they cannot support hidden areas
- return;
- }
- this._currentModelHasFoldedImports = false;
- this.foldingModel = new FoldingModel(model, this.foldingDecorationProvider);
- this.localToDispose.add(this.foldingModel);
- this.hiddenRangeModel = new HiddenRangeModel(this.foldingModel);
- this.localToDispose.add(this.hiddenRangeModel);
- this.localToDispose.add(this.hiddenRangeModel.onDidChange(hr => this.onHiddenRangesChanges(hr)));
- this.updateScheduler = new Delayer(200);
- this.cursorChangedScheduler = new RunOnceScheduler(() => this.revealCursor(), 200);
- this.localToDispose.add(this.cursorChangedScheduler);
- this.localToDispose.add(FoldingRangeProviderRegistry.onDidChange(() => this.onFoldingStrategyChanged()));
- this.localToDispose.add(this.editor.onDidChangeModelLanguageConfiguration(() => this.onFoldingStrategyChanged())); // covers model language changes as well
- this.localToDispose.add(this.editor.onDidChangeModelContent(e => this.onDidChangeModelContent(e)));
- this.localToDispose.add(this.editor.onDidChangeCursorPosition(() => this.onCursorPositionChanged()));
- this.localToDispose.add(this.editor.onMouseDown(e => this.onEditorMouseDown(e)));
- this.localToDispose.add(this.editor.onMouseUp(e => this.onEditorMouseUp(e)));
- this.localToDispose.add({
- dispose: () => {
- if (this.foldingRegionPromise) {
- this.foldingRegionPromise.cancel();
- this.foldingRegionPromise = null;
- }
- if (this.updateScheduler) {
- this.updateScheduler.cancel();
- }
- this.updateScheduler = null;
- this.foldingModel = null;
- this.foldingModelPromise = null;
- this.hiddenRangeModel = null;
- this.cursorChangedScheduler = null;
- this.foldingStateMemento = null;
- if (this.rangeProvider) {
- this.rangeProvider.dispose();
- }
- this.rangeProvider = null;
- }
- });
- this.triggerFoldingModelChanged();
- }
- onFoldingStrategyChanged() {
- if (this.rangeProvider) {
- this.rangeProvider.dispose();
- }
- this.rangeProvider = null;
- this.triggerFoldingModelChanged();
- }
- getRangeProvider(editorModel) {
- if (this.rangeProvider) {
- return this.rangeProvider;
- }
- this.rangeProvider = new IndentRangeProvider(editorModel); // fallback
- if (this._useFoldingProviders && this.foldingModel) {
- let foldingProviders = FoldingRangeProviderRegistry.ordered(this.foldingModel.textModel);
- if (foldingProviders.length === 0 && this.foldingStateMemento && this.foldingStateMemento.collapsedRegions) {
- const rangeProvider = this.rangeProvider = new InitializingRangeProvider(editorModel, this.foldingStateMemento.collapsedRegions, () => {
- // if after 30 the InitializingRangeProvider is still not replaced, force a refresh
- this.foldingStateMemento = null;
- this.onFoldingStrategyChanged();
- }, 30000);
- return rangeProvider; // keep memento in case there are still no foldingProviders on the next request.
- }
- else if (foldingProviders.length > 0) {
- this.rangeProvider = new SyntaxRangeProvider(editorModel, foldingProviders, () => this.triggerFoldingModelChanged());
- }
- }
- this.foldingStateMemento = null;
- return this.rangeProvider;
- }
- getFoldingModel() {
- return this.foldingModelPromise;
- }
- onDidChangeModelContent(e) {
- var _a;
- (_a = this.hiddenRangeModel) === null || _a === void 0 ? void 0 : _a.notifyChangeModelContent(e);
- this.triggerFoldingModelChanged();
- }
- triggerFoldingModelChanged() {
- if (this.updateScheduler) {
- if (this.foldingRegionPromise) {
- this.foldingRegionPromise.cancel();
- this.foldingRegionPromise = null;
- }
- this.foldingModelPromise = this.updateScheduler.trigger(() => {
- const foldingModel = this.foldingModel;
- if (!foldingModel) { // null if editor has been disposed, or folding turned off
- return null;
- }
- const provider = this.getRangeProvider(foldingModel.textModel);
- let foldingRegionPromise = this.foldingRegionPromise = createCancelablePromise(token => provider.compute(token));
- return foldingRegionPromise.then(foldingRanges => {
- if (foldingRanges && foldingRegionPromise === this.foldingRegionPromise) { // new request or cancelled in the meantime?
- let scrollState;
- if (this._foldingImportsByDefault && !this._currentModelHasFoldedImports) {
- const hasChanges = foldingRanges.setCollapsedAllOfType(FoldingRangeKind.Imports.value, true);
- if (hasChanges) {
- scrollState = StableEditorScrollState.capture(this.editor);
- this._currentModelHasFoldedImports = hasChanges;
- }
- }
- // some cursors might have moved into hidden regions, make sure they are in expanded regions
- let selections = this.editor.getSelections();
- let selectionLineNumbers = selections ? selections.map(s => s.startLineNumber) : [];
- foldingModel.update(foldingRanges, selectionLineNumbers);
- if (scrollState) {
- scrollState.restore(this.editor);
- }
- }
- return foldingModel;
- });
- }).then(undefined, (err) => {
- onUnexpectedError(err);
- return null;
- });
- }
- }
- onHiddenRangesChanges(hiddenRanges) {
- if (this.hiddenRangeModel && hiddenRanges.length && !this._restoringViewState) {
- let selections = this.editor.getSelections();
- if (selections) {
- if (this.hiddenRangeModel.adjustSelections(selections)) {
- this.editor.setSelections(selections);
- }
- }
- }
- this.editor.setHiddenAreas(hiddenRanges);
- }
- onCursorPositionChanged() {
- if (this.hiddenRangeModel && this.hiddenRangeModel.hasRanges()) {
- this.cursorChangedScheduler.schedule();
- }
- }
- revealCursor() {
- const foldingModel = this.getFoldingModel();
- if (!foldingModel) {
- return;
- }
- foldingModel.then(foldingModel => {
- if (foldingModel) {
- let selections = this.editor.getSelections();
- if (selections && selections.length > 0) {
- let toToggle = [];
- for (let selection of selections) {
- let lineNumber = selection.selectionStartLineNumber;
- if (this.hiddenRangeModel && this.hiddenRangeModel.isHidden(lineNumber)) {
- toToggle.push(...foldingModel.getAllRegionsAtLine(lineNumber, r => r.isCollapsed && lineNumber > r.startLineNumber));
- }
- }
- if (toToggle.length) {
- foldingModel.toggleCollapseState(toToggle);
- this.reveal(selections[0].getPosition());
- }
- }
- }
- }).then(undefined, onUnexpectedError);
- }
- onEditorMouseDown(e) {
- this.mouseDownInfo = null;
- if (!this.hiddenRangeModel || !e.target || !e.target.range) {
- return;
- }
- if (!e.event.leftButton && !e.event.middleButton) {
- return;
- }
- const range = e.target.range;
- let iconClicked = false;
- switch (e.target.type) {
- case 4 /* GUTTER_LINE_DECORATIONS */:
- const data = e.target.detail;
- const offsetLeftInGutter = e.target.element.offsetLeft;
- const gutterOffsetX = data.offsetX - offsetLeftInGutter;
- // const gutterOffsetX = data.offsetX - data.glyphMarginWidth - data.lineNumbersWidth - data.glyphMarginLeft;
- // TODO@joao TODO@alex TODO@martin this is such that we don't collide with dirty diff
- if (gutterOffsetX < 5) { // the whitespace between the border and the real folding icon border is 5px
- return;
- }
- iconClicked = true;
- break;
- case 7 /* CONTENT_EMPTY */: {
- if (this._unfoldOnClickAfterEndOfLine && this.hiddenRangeModel.hasRanges()) {
- const data = e.target.detail;
- if (!data.isAfterLines) {
- break;
- }
- }
- return;
- }
- case 6 /* CONTENT_TEXT */: {
- if (this.hiddenRangeModel.hasRanges()) {
- let model = this.editor.getModel();
- if (model && range.startColumn === model.getLineMaxColumn(range.startLineNumber)) {
- break;
- }
- }
- return;
- }
- default:
- return;
- }
- this.mouseDownInfo = { lineNumber: range.startLineNumber, iconClicked };
- }
- onEditorMouseUp(e) {
- const foldingModel = this.getFoldingModel();
- if (!foldingModel || !this.mouseDownInfo || !e.target) {
- return;
- }
- let lineNumber = this.mouseDownInfo.lineNumber;
- let iconClicked = this.mouseDownInfo.iconClicked;
- let range = e.target.range;
- if (!range || range.startLineNumber !== lineNumber) {
- return;
- }
- if (iconClicked) {
- if (e.target.type !== 4 /* GUTTER_LINE_DECORATIONS */) {
- return;
- }
- }
- else {
- let model = this.editor.getModel();
- if (!model || range.startColumn !== model.getLineMaxColumn(lineNumber)) {
- return;
- }
- }
- foldingModel.then(foldingModel => {
- if (foldingModel) {
- let region = foldingModel.getRegionAtLine(lineNumber);
- if (region && region.startLineNumber === lineNumber) {
- let isCollapsed = region.isCollapsed;
- if (iconClicked || isCollapsed) {
- let surrounding = e.event.altKey;
- let toToggle = [];
- if (surrounding) {
- let filter = (otherRegion) => !otherRegion.containedBy(region) && !region.containedBy(otherRegion);
- let toMaybeToggle = foldingModel.getRegionsInside(null, filter);
- for (const r of toMaybeToggle) {
- if (r.isCollapsed) {
- toToggle.push(r);
- }
- }
- // if any surrounding regions are folded, unfold those. Otherwise, fold all surrounding
- if (toToggle.length === 0) {
- toToggle = toMaybeToggle;
- }
- }
- else {
- let recursive = e.event.middleButton || e.event.shiftKey;
- if (recursive) {
- for (const r of foldingModel.getRegionsInside(region)) {
- if (r.isCollapsed === isCollapsed) {
- toToggle.push(r);
- }
- }
- }
- // when recursive, first only collapse all children. If all are already folded or there are no children, also fold parent.
- if (isCollapsed || !recursive || toToggle.length === 0) {
- toToggle.push(region);
- }
- }
- foldingModel.toggleCollapseState(toToggle);
- this.reveal({ lineNumber, column: 1 });
- }
- }
- }
- }).then(undefined, onUnexpectedError);
- }
- reveal(position) {
- this.editor.revealPositionInCenterIfOutsideViewport(position, 0 /* Smooth */);
- }
- };
- FoldingController.ID = 'editor.contrib.folding';
- FoldingController = __decorate([
- __param(1, IContextKeyService)
- ], FoldingController);
- export { FoldingController };
- class FoldingAction extends EditorAction {
- runEditorCommand(accessor, editor, args) {
- let foldingController = FoldingController.get(editor);
- if (!foldingController) {
- return;
- }
- let foldingModelPromise = foldingController.getFoldingModel();
- if (foldingModelPromise) {
- this.reportTelemetry(accessor, editor);
- return foldingModelPromise.then(foldingModel => {
- if (foldingModel) {
- this.invoke(foldingController, foldingModel, editor, args);
- const selection = editor.getSelection();
- if (selection) {
- foldingController.reveal(selection.getStartPosition());
- }
- }
- });
- }
- }
- getSelectedLines(editor) {
- let selections = editor.getSelections();
- return selections ? selections.map(s => s.startLineNumber) : [];
- }
- getLineNumbers(args, editor) {
- if (args && args.selectionLines) {
- return args.selectionLines.map(l => l + 1); // to 0-bases line numbers
- }
- return this.getSelectedLines(editor);
- }
- run(_accessor, _editor) {
- }
- }
- function foldingArgumentsConstraint(args) {
- if (!types.isUndefined(args)) {
- if (!types.isObject(args)) {
- return false;
- }
- const foldingArgs = args;
- if (!types.isUndefined(foldingArgs.levels) && !types.isNumber(foldingArgs.levels)) {
- return false;
- }
- if (!types.isUndefined(foldingArgs.direction) && !types.isString(foldingArgs.direction)) {
- return false;
- }
- if (!types.isUndefined(foldingArgs.selectionLines) && (!types.isArray(foldingArgs.selectionLines) || !foldingArgs.selectionLines.every(types.isNumber))) {
- return false;
- }
- }
- return true;
- }
- class UnfoldAction extends FoldingAction {
- constructor() {
- super({
- id: 'editor.unfold',
- label: nls.localize('unfoldAction.label', "Unfold"),
- alias: 'Unfold',
- precondition: CONTEXT_FOLDING_ENABLED,
- kbOpts: {
- kbExpr: EditorContextKeys.editorTextFocus,
- primary: 2048 /* CtrlCmd */ | 1024 /* Shift */ | 89 /* BracketRight */,
- mac: {
- primary: 2048 /* CtrlCmd */ | 512 /* Alt */ | 89 /* BracketRight */
- },
- weight: 100 /* EditorContrib */
- },
- description: {
- description: 'Unfold the content in the editor',
- args: [
- {
- name: 'Unfold editor argument',
- description: `Property-value pairs that can be passed through this argument:
- * 'levels': Number of levels to unfold. If not set, defaults to 1.
- * 'direction': If 'up', unfold given number of levels up otherwise unfolds down.
- * 'selectionLines': The start lines (0-based) of the editor selections to apply the unfold action to. If not set, the active selection(s) will be used.
- `,
- constraint: foldingArgumentsConstraint,
- schema: {
- 'type': 'object',
- 'properties': {
- 'levels': {
- 'type': 'number',
- 'default': 1
- },
- 'direction': {
- 'type': 'string',
- 'enum': ['up', 'down'],
- 'default': 'down'
- },
- 'selectionLines': {
- 'type': 'array',
- 'items': {
- 'type': 'number'
- }
- }
- }
- }
- }
- ]
- }
- });
- }
- invoke(_foldingController, foldingModel, editor, args) {
- let levels = args && args.levels || 1;
- let lineNumbers = this.getLineNumbers(args, editor);
- if (args && args.direction === 'up') {
- setCollapseStateLevelsUp(foldingModel, false, levels, lineNumbers);
- }
- else {
- setCollapseStateLevelsDown(foldingModel, false, levels, lineNumbers);
- }
- }
- }
- class UnFoldRecursivelyAction extends FoldingAction {
- constructor() {
- super({
- id: 'editor.unfoldRecursively',
- label: nls.localize('unFoldRecursivelyAction.label', "Unfold Recursively"),
- alias: 'Unfold Recursively',
- precondition: CONTEXT_FOLDING_ENABLED,
- kbOpts: {
- kbExpr: EditorContextKeys.editorTextFocus,
- primary: KeyChord(2048 /* CtrlCmd */ | 41 /* KeyK */, 2048 /* CtrlCmd */ | 89 /* BracketRight */),
- weight: 100 /* EditorContrib */
- }
- });
- }
- invoke(_foldingController, foldingModel, editor, _args) {
- setCollapseStateLevelsDown(foldingModel, false, Number.MAX_VALUE, this.getSelectedLines(editor));
- }
- }
- class FoldAction extends FoldingAction {
- constructor() {
- super({
- id: 'editor.fold',
- label: nls.localize('foldAction.label', "Fold"),
- alias: 'Fold',
- precondition: CONTEXT_FOLDING_ENABLED,
- kbOpts: {
- kbExpr: EditorContextKeys.editorTextFocus,
- primary: 2048 /* CtrlCmd */ | 1024 /* Shift */ | 87 /* BracketLeft */,
- mac: {
- primary: 2048 /* CtrlCmd */ | 512 /* Alt */ | 87 /* BracketLeft */
- },
- weight: 100 /* EditorContrib */
- },
- description: {
- description: 'Fold the content in the editor',
- args: [
- {
- name: 'Fold editor argument',
- description: `Property-value pairs that can be passed through this argument:
- * 'levels': Number of levels to fold.
- * 'direction': If 'up', folds given number of levels up otherwise folds down.
- * 'selectionLines': The start lines (0-based) of the editor selections to apply the fold action to. If not set, the active selection(s) will be used.
- If no levels or direction is set, folds the region at the locations or if already collapsed, the first uncollapsed parent instead.
- `,
- constraint: foldingArgumentsConstraint,
- schema: {
- 'type': 'object',
- 'properties': {
- 'levels': {
- 'type': 'number',
- },
- 'direction': {
- 'type': 'string',
- 'enum': ['up', 'down'],
- },
- 'selectionLines': {
- 'type': 'array',
- 'items': {
- 'type': 'number'
- }
- }
- }
- }
- }
- ]
- }
- });
- }
- invoke(_foldingController, foldingModel, editor, args) {
- let lineNumbers = this.getLineNumbers(args, editor);
- const levels = args && args.levels;
- const direction = args && args.direction;
- if (typeof levels !== 'number' && typeof direction !== 'string') {
- // fold the region at the location or if already collapsed, the first uncollapsed parent instead.
- setCollapseStateUp(foldingModel, true, lineNumbers);
- }
- else {
- if (direction === 'up') {
- setCollapseStateLevelsUp(foldingModel, true, levels || 1, lineNumbers);
- }
- else {
- setCollapseStateLevelsDown(foldingModel, true, levels || 1, lineNumbers);
- }
- }
- }
- }
- class ToggleFoldAction extends FoldingAction {
- constructor() {
- super({
- id: 'editor.toggleFold',
- label: nls.localize('toggleFoldAction.label', "Toggle Fold"),
- alias: 'Toggle Fold',
- precondition: CONTEXT_FOLDING_ENABLED,
- kbOpts: {
- kbExpr: EditorContextKeys.editorTextFocus,
- primary: KeyChord(2048 /* CtrlCmd */ | 41 /* KeyK */, 2048 /* CtrlCmd */ | 42 /* KeyL */),
- weight: 100 /* EditorContrib */
- }
- });
- }
- invoke(_foldingController, foldingModel, editor) {
- let selectedLines = this.getSelectedLines(editor);
- toggleCollapseState(foldingModel, 1, selectedLines);
- }
- }
- class FoldRecursivelyAction extends FoldingAction {
- constructor() {
- super({
- id: 'editor.foldRecursively',
- label: nls.localize('foldRecursivelyAction.label', "Fold Recursively"),
- alias: 'Fold Recursively',
- precondition: CONTEXT_FOLDING_ENABLED,
- kbOpts: {
- kbExpr: EditorContextKeys.editorTextFocus,
- primary: KeyChord(2048 /* CtrlCmd */ | 41 /* KeyK */, 2048 /* CtrlCmd */ | 87 /* BracketLeft */),
- weight: 100 /* EditorContrib */
- }
- });
- }
- invoke(_foldingController, foldingModel, editor) {
- let selectedLines = this.getSelectedLines(editor);
- setCollapseStateLevelsDown(foldingModel, true, Number.MAX_VALUE, selectedLines);
- }
- }
- class FoldAllBlockCommentsAction extends FoldingAction {
- constructor() {
- super({
- id: 'editor.foldAllBlockComments',
- label: nls.localize('foldAllBlockComments.label', "Fold All Block Comments"),
- alias: 'Fold All Block Comments',
- precondition: CONTEXT_FOLDING_ENABLED,
- kbOpts: {
- kbExpr: EditorContextKeys.editorTextFocus,
- primary: KeyChord(2048 /* CtrlCmd */ | 41 /* KeyK */, 2048 /* CtrlCmd */ | 85 /* Slash */),
- weight: 100 /* EditorContrib */
- }
- });
- }
- invoke(_foldingController, foldingModel, editor) {
- if (foldingModel.regions.hasTypes()) {
- setCollapseStateForType(foldingModel, FoldingRangeKind.Comment.value, true);
- }
- else {
- const editorModel = editor.getModel();
- if (!editorModel) {
- return;
- }
- const comments = LanguageConfigurationRegistry.getComments(editorModel.getLanguageId());
- if (comments && comments.blockCommentStartToken) {
- let regExp = new RegExp('^\\s*' + escapeRegExpCharacters(comments.blockCommentStartToken));
- setCollapseStateForMatchingLines(foldingModel, regExp, true);
- }
- }
- }
- }
- class FoldAllRegionsAction extends FoldingAction {
- constructor() {
- super({
- id: 'editor.foldAllMarkerRegions',
- label: nls.localize('foldAllMarkerRegions.label', "Fold All Regions"),
- alias: 'Fold All Regions',
- precondition: CONTEXT_FOLDING_ENABLED,
- kbOpts: {
- kbExpr: EditorContextKeys.editorTextFocus,
- primary: KeyChord(2048 /* CtrlCmd */ | 41 /* KeyK */, 2048 /* CtrlCmd */ | 29 /* Digit8 */),
- weight: 100 /* EditorContrib */
- }
- });
- }
- invoke(_foldingController, foldingModel, editor) {
- if (foldingModel.regions.hasTypes()) {
- setCollapseStateForType(foldingModel, FoldingRangeKind.Region.value, true);
- }
- else {
- const editorModel = editor.getModel();
- if (!editorModel) {
- return;
- }
- const foldingRules = LanguageConfigurationRegistry.getFoldingRules(editorModel.getLanguageId());
- if (foldingRules && foldingRules.markers && foldingRules.markers.start) {
- let regExp = new RegExp(foldingRules.markers.start);
- setCollapseStateForMatchingLines(foldingModel, regExp, true);
- }
- }
- }
- }
- class UnfoldAllRegionsAction extends FoldingAction {
- constructor() {
- super({
- id: 'editor.unfoldAllMarkerRegions',
- label: nls.localize('unfoldAllMarkerRegions.label', "Unfold All Regions"),
- alias: 'Unfold All Regions',
- precondition: CONTEXT_FOLDING_ENABLED,
- kbOpts: {
- kbExpr: EditorContextKeys.editorTextFocus,
- primary: KeyChord(2048 /* CtrlCmd */ | 41 /* KeyK */, 2048 /* CtrlCmd */ | 30 /* Digit9 */),
- weight: 100 /* EditorContrib */
- }
- });
- }
- invoke(_foldingController, foldingModel, editor) {
- if (foldingModel.regions.hasTypes()) {
- setCollapseStateForType(foldingModel, FoldingRangeKind.Region.value, false);
- }
- else {
- const editorModel = editor.getModel();
- if (!editorModel) {
- return;
- }
- const foldingRules = LanguageConfigurationRegistry.getFoldingRules(editorModel.getLanguageId());
- if (foldingRules && foldingRules.markers && foldingRules.markers.start) {
- let regExp = new RegExp(foldingRules.markers.start);
- setCollapseStateForMatchingLines(foldingModel, regExp, false);
- }
- }
- }
- }
- class FoldAllRegionsExceptAction extends FoldingAction {
- constructor() {
- super({
- id: 'editor.foldAllExcept',
- label: nls.localize('foldAllExcept.label', "Fold All Regions Except Selected"),
- alias: 'Fold All Regions Except Selected',
- precondition: CONTEXT_FOLDING_ENABLED,
- kbOpts: {
- kbExpr: EditorContextKeys.editorTextFocus,
- primary: KeyChord(2048 /* CtrlCmd */ | 41 /* KeyK */, 2048 /* CtrlCmd */ | 83 /* Minus */),
- weight: 100 /* EditorContrib */
- }
- });
- }
- invoke(_foldingController, foldingModel, editor) {
- let selectedLines = this.getSelectedLines(editor);
- setCollapseStateForRest(foldingModel, true, selectedLines);
- }
- }
- class UnfoldAllRegionsExceptAction extends FoldingAction {
- constructor() {
- super({
- id: 'editor.unfoldAllExcept',
- label: nls.localize('unfoldAllExcept.label', "Unfold All Regions Except Selected"),
- alias: 'Unfold All Regions Except Selected',
- precondition: CONTEXT_FOLDING_ENABLED,
- kbOpts: {
- kbExpr: EditorContextKeys.editorTextFocus,
- primary: KeyChord(2048 /* CtrlCmd */ | 41 /* KeyK */, 2048 /* CtrlCmd */ | 81 /* Equal */),
- weight: 100 /* EditorContrib */
- }
- });
- }
- invoke(_foldingController, foldingModel, editor) {
- let selectedLines = this.getSelectedLines(editor);
- setCollapseStateForRest(foldingModel, false, selectedLines);
- }
- }
- class FoldAllAction extends FoldingAction {
- constructor() {
- super({
- id: 'editor.foldAll',
- label: nls.localize('foldAllAction.label', "Fold All"),
- alias: 'Fold All',
- precondition: CONTEXT_FOLDING_ENABLED,
- kbOpts: {
- kbExpr: EditorContextKeys.editorTextFocus,
- primary: KeyChord(2048 /* CtrlCmd */ | 41 /* KeyK */, 2048 /* CtrlCmd */ | 21 /* Digit0 */),
- weight: 100 /* EditorContrib */
- }
- });
- }
- invoke(_foldingController, foldingModel, _editor) {
- setCollapseStateLevelsDown(foldingModel, true);
- }
- }
- class UnfoldAllAction extends FoldingAction {
- constructor() {
- super({
- id: 'editor.unfoldAll',
- label: nls.localize('unfoldAllAction.label', "Unfold All"),
- alias: 'Unfold All',
- precondition: CONTEXT_FOLDING_ENABLED,
- kbOpts: {
- kbExpr: EditorContextKeys.editorTextFocus,
- primary: KeyChord(2048 /* CtrlCmd */ | 41 /* KeyK */, 2048 /* CtrlCmd */ | 40 /* KeyJ */),
- weight: 100 /* EditorContrib */
- }
- });
- }
- invoke(_foldingController, foldingModel, _editor) {
- setCollapseStateLevelsDown(foldingModel, false);
- }
- }
- class FoldLevelAction extends FoldingAction {
- getFoldingLevel() {
- return parseInt(this.id.substr(FoldLevelAction.ID_PREFIX.length));
- }
- invoke(_foldingController, foldingModel, editor) {
- setCollapseStateAtLevel(foldingModel, this.getFoldingLevel(), true, this.getSelectedLines(editor));
- }
- }
- FoldLevelAction.ID_PREFIX = 'editor.foldLevel';
- FoldLevelAction.ID = (level) => FoldLevelAction.ID_PREFIX + level;
- /** Action to go to the parent fold of current line */
- class GotoParentFoldAction extends FoldingAction {
- constructor() {
- super({
- id: 'editor.gotoParentFold',
- label: nls.localize('gotoParentFold.label', "Go to Parent Fold"),
- alias: 'Go to Parent Fold',
- precondition: CONTEXT_FOLDING_ENABLED,
- kbOpts: {
- kbExpr: EditorContextKeys.editorTextFocus,
- weight: 100 /* EditorContrib */
- }
- });
- }
- invoke(_foldingController, foldingModel, editor) {
- let selectedLines = this.getSelectedLines(editor);
- if (selectedLines.length > 0) {
- let startLineNumber = getParentFoldLine(selectedLines[0], foldingModel);
- if (startLineNumber !== null) {
- editor.setSelection({
- startLineNumber: startLineNumber,
- startColumn: 1,
- endLineNumber: startLineNumber,
- endColumn: 1
- });
- }
- }
- }
- }
- /** Action to go to the previous fold of current line */
- class GotoPreviousFoldAction extends FoldingAction {
- constructor() {
- super({
- id: 'editor.gotoPreviousFold',
- label: nls.localize('gotoPreviousFold.label', "Go to Previous Folding Range"),
- alias: 'Go to Previous Folding Range',
- precondition: CONTEXT_FOLDING_ENABLED,
- kbOpts: {
- kbExpr: EditorContextKeys.editorTextFocus,
- weight: 100 /* EditorContrib */
- }
- });
- }
- invoke(_foldingController, foldingModel, editor) {
- let selectedLines = this.getSelectedLines(editor);
- if (selectedLines.length > 0) {
- let startLineNumber = getPreviousFoldLine(selectedLines[0], foldingModel);
- if (startLineNumber !== null) {
- editor.setSelection({
- startLineNumber: startLineNumber,
- startColumn: 1,
- endLineNumber: startLineNumber,
- endColumn: 1
- });
- }
- }
- }
- }
- /** Action to go to the next fold of current line */
- class GotoNextFoldAction extends FoldingAction {
- constructor() {
- super({
- id: 'editor.gotoNextFold',
- label: nls.localize('gotoNextFold.label', "Go to Next Folding Range"),
- alias: 'Go to Next Folding Range',
- precondition: CONTEXT_FOLDING_ENABLED,
- kbOpts: {
- kbExpr: EditorContextKeys.editorTextFocus,
- weight: 100 /* EditorContrib */
- }
- });
- }
- invoke(_foldingController, foldingModel, editor) {
- let selectedLines = this.getSelectedLines(editor);
- if (selectedLines.length > 0) {
- let startLineNumber = getNextFoldLine(selectedLines[0], foldingModel);
- if (startLineNumber !== null) {
- editor.setSelection({
- startLineNumber: startLineNumber,
- startColumn: 1,
- endLineNumber: startLineNumber,
- endColumn: 1
- });
- }
- }
- }
- }
- registerEditorContribution(FoldingController.ID, FoldingController);
- registerEditorAction(UnfoldAction);
- registerEditorAction(UnFoldRecursivelyAction);
- registerEditorAction(FoldAction);
- registerEditorAction(FoldRecursivelyAction);
- registerEditorAction(FoldAllAction);
- registerEditorAction(UnfoldAllAction);
- registerEditorAction(FoldAllBlockCommentsAction);
- registerEditorAction(FoldAllRegionsAction);
- registerEditorAction(UnfoldAllRegionsAction);
- registerEditorAction(FoldAllRegionsExceptAction);
- registerEditorAction(UnfoldAllRegionsExceptAction);
- registerEditorAction(ToggleFoldAction);
- registerEditorAction(GotoParentFoldAction);
- registerEditorAction(GotoPreviousFoldAction);
- registerEditorAction(GotoNextFoldAction);
- for (let i = 1; i <= 7; i++) {
- registerInstantiatedEditorAction(new FoldLevelAction({
- id: FoldLevelAction.ID(i),
- label: nls.localize('foldLevelAction.label', "Fold Level {0}", i),
- alias: `Fold Level ${i}`,
- precondition: CONTEXT_FOLDING_ENABLED,
- kbOpts: {
- kbExpr: EditorContextKeys.editorTextFocus,
- primary: KeyChord(2048 /* CtrlCmd */ | 41 /* KeyK */, 2048 /* CtrlCmd */ | (21 /* Digit0 */ + i)),
- weight: 100 /* EditorContrib */
- }
- }));
- }
- export const foldBackgroundBackground = registerColor('editor.foldBackground', { light: transparent(editorSelectionBackground, 0.3), dark: transparent(editorSelectionBackground, 0.3), hc: null }, nls.localize('foldBackgroundBackground', "Background color behind folded ranges. The color must not be opaque so as not to hide underlying decorations."), true);
- export const editorFoldForeground = registerColor('editorGutter.foldingControlForeground', { dark: iconForeground, light: iconForeground, hc: iconForeground }, nls.localize('editorGutter.foldingControlForeground', 'Color of the folding control in the editor gutter.'));
- registerThemingParticipant((theme, collector) => {
- const foldBackground = theme.getColor(foldBackgroundBackground);
- if (foldBackground) {
- collector.addRule(`.monaco-editor .folded-background { background-color: ${foldBackground}; }`);
- }
- const editorFoldColor = theme.getColor(editorFoldForeground);
- if (editorFoldColor) {
- collector.addRule(`
- .monaco-editor .cldr${ThemeIcon.asCSSSelector(foldingExpandedIcon)},
- .monaco-editor .cldr${ThemeIcon.asCSSSelector(foldingCollapsedIcon)} {
- color: ${editorFoldColor} !important;
- }
- `);
- }
- });
|