提交 f1cf555d 编写于 作者: M Martin Aeschlimann

"fold" command when invoked on a folded line should apply to the enclosing level. Fixes #87810

上级 54ee1655
......@@ -14,7 +14,7 @@ import { ScrollType, IEditorContribution } from 'vs/editor/common/editorCommon';
import { ITextModel } from 'vs/editor/common/model';
import { registerEditorAction, registerEditorContribution, ServicesAccessor, EditorAction, registerInstantiatedEditorAction } from 'vs/editor/browser/editorExtensions';
import { ICodeEditor, IEditorMouseEvent, MouseTargetType } from 'vs/editor/browser/editorBrowser';
import { FoldingModel, setCollapseStateAtLevel, CollapseMemento, setCollapseStateLevelsDown, setCollapseStateLevelsUp, setCollapseStateForMatchingLines, setCollapseStateForType, toggleCollapseState } from 'vs/editor/contrib/folding/foldingModel';
import { FoldingModel, setCollapseStateAtLevel, CollapseMemento, setCollapseStateLevelsDown, setCollapseStateLevelsUp, setCollapseStateForMatchingLines, setCollapseStateForType, toggleCollapseState, setCollapseStateUp } from 'vs/editor/contrib/folding/foldingModel';
import { FoldingDecorationProvider } from './foldingDecorations';
import { FoldingRegions, FoldingRegion } from './foldingRanges';
import { EditorContextKeys } from 'vs/editor/common/editorContextKeys';
......@@ -617,9 +617,10 @@ class FoldAction extends FoldingAction<FoldingArguments> {
{
name: 'Fold editor argument',
description: `Property-value pairs that can be passed through this argument:
* 'levels': Number of levels to fold. Defaults to 1.
* '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: {
......@@ -627,12 +628,10 @@ class FoldAction extends FoldingAction<FoldingArguments> {
'properties': {
'levels': {
'type': 'number',
'default': 1
},
'direction': {
'type': 'string',
'enum': ['up', 'down'],
'default': 'down'
},
'selectionLines': {
'type': 'array',
......@@ -649,12 +648,20 @@ class FoldAction extends FoldingAction<FoldingArguments> {
}
invoke(_foldingController: FoldingController, foldingModel: FoldingModel, editor: ICodeEditor, args: FoldingArguments): void {
let levels = args && args.levels || 1;
let lineNumbers = this.getLineNumbers(args, editor);
if (args && args.direction === 'up') {
setCollapseStateLevelsUp(foldingModel, true, levels, lineNumbers);
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 {
setCollapseStateLevelsDown(foldingModel, true, levels, lineNumbers);
if (direction === 'up') {
setCollapseStateLevelsUp(foldingModel, true, levels || 1, lineNumbers);
} else {
setCollapseStateLevelsDown(foldingModel, true, levels || 1, lineNumbers);
}
}
}
}
......
......@@ -273,7 +273,7 @@ export function toggleCollapseState(foldingModel: FoldingModel, levels: number,
* @param levels The number of levels. Use 1 to only impact the regions at the location, use Number.MAX_VALUE for all levels.
* @param lineNumbers the location of the regions to collapse or expand, or if not set, all regions in the model.
*/
export function setCollapseStateLevelsDown(foldingModel: FoldingModel, doCollapse: boolean, levels = Number.MAX_VALUE, lineNumbers?: number[]) {
export function setCollapseStateLevelsDown(foldingModel: FoldingModel, doCollapse: boolean, levels = Number.MAX_VALUE, lineNumbers?: number[]): void {
let toToggle: FoldingRegion[] = [];
if (lineNumbers && lineNumbers.length > 0) {
for (let lineNumber of lineNumbers) {
......@@ -299,9 +299,9 @@ export function setCollapseStateLevelsDown(foldingModel: FoldingModel, doCollaps
* Collapse or expand the regions at the given locations including all parents.
* @param doCollapse Wheter to collase or expand
* @param levels The number of levels. Use 1 to only impact the regions at the location, use Number.MAX_VALUE for all levels.
* @param lineNumbers the location of the regions to collapse or expand, or if not set, all regions in the model.
* @param lineNumbers the location of the regions to collapse or expand.
*/
export function setCollapseStateLevelsUp(foldingModel: FoldingModel, doCollapse: boolean, levels: number, lineNumbers: number[]) {
export function setCollapseStateLevelsUp(foldingModel: FoldingModel, doCollapse: boolean, levels: number, lineNumbers: number[]): void {
let toToggle: FoldingRegion[] = [];
for (let lineNumber of lineNumbers) {
let regions = foldingModel.getAllRegionsAtLine(lineNumber, (region, level) => region.isCollapsed !== doCollapse && level <= levels);
......@@ -310,6 +310,22 @@ export function setCollapseStateLevelsUp(foldingModel: FoldingModel, doCollapse:
foldingModel.toggleCollapseState(toToggle);
}
/**
* Collapse or expand a region at the given locations. If the inner most region is already collapsed/expanded, uses the first parent instead.
* @param doCollapse Wheter to collase or expand
* @param lineNumbers the location of the regions to collapse or expand.
*/
export function setCollapseStateUp(foldingModel: FoldingModel, doCollapse: boolean, lineNumbers: number[]): void {
let toToggle: FoldingRegion[] = [];
for (let lineNumber of lineNumbers) {
let regions = foldingModel.getAllRegionsAtLine(lineNumber, (region, ) => region.isCollapsed !== doCollapse);
if (regions.length > 0) {
toToggle.push(regions[0]);
}
}
foldingModel.toggleCollapseState(toToggle);
}
/**
* Folds or unfolds all regions that have a given level, except if they contain one of the blocked lines.
* @param foldLevel level. Level == 1 is the top level
......
......@@ -3,7 +3,7 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as assert from 'assert';
import { FoldingModel, setCollapseStateAtLevel, setCollapseStateLevelsDown, setCollapseStateLevelsUp, setCollapseStateForMatchingLines } from 'vs/editor/contrib/folding/foldingModel';
import { FoldingModel, setCollapseStateAtLevel, setCollapseStateLevelsDown, setCollapseStateLevelsUp, setCollapseStateForMatchingLines, setCollapseStateUp } from 'vs/editor/contrib/folding/foldingModel';
import { TextModel, ModelDecorationOptions } from 'vs/editor/common/model/textModel';
import { computeRanges } from 'vs/editor/contrib/folding/indentRangeProvider';
import { TrackedRangeStickiness, IModelDeltaDecoration, ITextModel, IModelDecorationsChangeAccessor } from 'vs/editor/common/model';
......@@ -587,6 +587,50 @@ suite('Folding Model', () => {
});
test('setCollapseStateUp', () => {
let lines = [
/* 1*/ '//#region',
/* 2*/ '//#endregion',
/* 3*/ 'class A {',
/* 4*/ ' void foo() {',
/* 5*/ ' if (true) {',
/* 6*/ ' return;',
/* 7*/ ' }',
/* 8*/ '',
/* 9*/ ' if (true) {',
/* 10*/ ' return;',
/* 11*/ ' }',
/* 12*/ ' }',
/* 13*/ '}'];
let textModel = TextModel.createFromString(lines.join('\n'));
try {
let foldingModel = new FoldingModel(textModel, new TestDecorationProvider(textModel));
let ranges = computeRanges(textModel, false, { start: /^\/\/#region$/, end: /^\/\/#endregion$/ });
foldingModel.update(ranges);
let r1 = r(1, 2, false);
let r2 = r(3, 12, false);
let r3 = r(4, 11, false);
let r4 = r(5, 6, false);
let r5 = r(9, 10, false);
assertRanges(foldingModel, [r1, r2, r3, r4, r5]);
setCollapseStateUp(foldingModel, true, [5]);
assertFoldedRanges(foldingModel, [r4], '1');
setCollapseStateUp(foldingModel, true, [5]);
assertFoldedRanges(foldingModel, [r3, r4], '2');
setCollapseStateUp(foldingModel, true, [4]);
assertFoldedRanges(foldingModel, [r2, r3, r4], '2');
} finally {
textModel.dispose();
}
});
test('setCollapseStateForMatchingLines', () => {
let lines = [
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册