Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
掘金者说
vscode
提交
71c8b150
V
vscode
项目概览
掘金者说
/
vscode
与 Fork 源项目一致
从无法访问的项目Fork
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
V
vscode
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
71c8b150
编写于
2月 09, 2016
作者:
M
Martin Aeschlimann
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Folding using indentation
上级
c3d1b9fa
变更
17
隐藏空白更改
内联
并排
Showing
17 changed file
with
614 addition
and
20 deletion
+614
-20
src/vs/editor/browser/editor.all.js
src/vs/editor/browser/editor.all.js
+1
-0
src/vs/editor/browser/editorBrowser.ts
src/vs/editor/browser/editorBrowser.ts
+5
-0
src/vs/editor/browser/widget/codeEditorWidget.ts
src/vs/editor/browser/widget/codeEditorWidget.ts
+6
-0
src/vs/editor/common/viewModel/splitLinesCollection.ts
src/vs/editor/common/viewModel/splitLinesCollection.ts
+169
-10
src/vs/editor/common/viewModel/viewModel.ts
src/vs/editor/common/viewModel/viewModel.ts
+11
-0
src/vs/editor/contrib/folding/browser/arrow-collapse-dark.svg
...vs/editor/contrib/folding/browser/arrow-collapse-dark.svg
+1
-0
src/vs/editor/contrib/folding/browser/arrow-collapse.svg
src/vs/editor/contrib/folding/browser/arrow-collapse.svg
+1
-0
src/vs/editor/contrib/folding/browser/arrow-expand-dark.svg
src/vs/editor/contrib/folding/browser/arrow-expand-dark.svg
+1
-0
src/vs/editor/contrib/folding/browser/arrow-expand.svg
src/vs/editor/contrib/folding/browser/arrow-expand.svg
+1
-0
src/vs/editor/contrib/folding/browser/folding.css
src/vs/editor/contrib/folding/browser/folding.css
+35
-0
src/vs/editor/contrib/folding/browser/folding.ts
src/vs/editor/contrib/folding/browser/folding.ts
+223
-0
src/vs/editor/contrib/folding/common/foldingRange.ts
src/vs/editor/contrib/folding/common/foldingRange.ts
+11
-0
src/vs/editor/contrib/folding/common/indentFoldStrategy.ts
src/vs/editor/contrib/folding/common/indentFoldStrategy.ts
+67
-0
src/vs/editor/contrib/folding/test/indentFold.test.ts
src/vs/editor/contrib/folding/test/indentFold.test.ts
+75
-0
src/vs/editor/test/common/viewModel/splitLinesCollection.test.ts
...editor/test/common/viewModel/splitLinesCollection.test.ts
+2
-2
src/vs/workbench/browser/parts/editor/textEditor.ts
src/vs/workbench/browser/parts/editor/textEditor.ts
+1
-0
src/vs/workbench/parts/git/browser/media/git.contribution.css
...vs/workbench/parts/git/browser/media/git.contribution.css
+4
-8
未找到文件。
src/vs/editor/browser/editor.all.js
浏览文件 @
71c8b150
...
...
@@ -38,6 +38,7 @@ define([
'
vs/editor/contrib/wordHighlighter/common/wordHighlighter
'
,
'
vs/editor/contrib/workerStatusReporter/browser/workerStatusReporter
'
,
'
vs/editor/contrib/defineKeybinding/browser/defineKeybinding
'
,
"
vs/editor/contrib/folding/browser/folding
"
,
// include these in the editor bundle because they are widely used by many languages
'
vs/editor/common/languages.common
'
...
...
src/vs/editor/browser/editorBrowser.ts
浏览文件 @
71c8b150
...
...
@@ -591,6 +591,11 @@ export interface ICodeEditor extends EditorCommon.ICommonCodeEditor {
* Warning: the results of this method are innacurate for positions that are outside the current editor viewport.
*/
getScrolledVisiblePosition
(
position
:
EditorCommon
.
IPosition
):
{
top
:
number
;
left
:
number
;
height
:
number
;
};
/**
* Set the model ranges that will be hidden in the view.
*/
setHiddenAreas
(
ranges
:
EditorCommon
.
IRange
[]):
void
;
}
/**
...
...
src/vs/editor/browser/widget/codeEditorWidget.ts
浏览文件 @
71c8b150
...
...
@@ -365,6 +365,12 @@ export class CodeEditorWidget extends CommonCodeEditor implements EditorBrowser.
this
.
_view
.
render
(
true
);
}
public
setHiddenAreas
(
ranges
:
EditorCommon
.
IRange
[]):
void
{
if
(
this
.
viewModel
)
{
this
.
viewModel
.
setHiddenAreas
(
ranges
);
}
}
_attachModel
(
model
:
EditorCommon
.
IModel
):
void
{
this
.
_view
=
null
;
...
...
src/vs/editor/common/viewModel/splitLinesCollection.ts
浏览文件 @
71c8b150
...
...
@@ -5,6 +5,7 @@
'
use strict
'
;
import
{
Position
}
from
'
vs/editor/common/core/position
'
;
import
{
Range
}
from
'
vs/editor/common/core/range
'
;
import
{
PrefixSumComputer
,
IPrefixSumIndexOfResult
}
from
'
vs/editor/common/viewModel/prefixSumComputer
'
;
import
{
FilteredLineTokens
,
IdentityFilteredLineTokens
}
from
'
vs/editor/common/viewModel/filteredLineTokens
'
;
import
{
ILinesCollection
}
from
'
vs/editor/common/viewModel/viewModel
'
;
...
...
@@ -41,6 +42,8 @@ export interface IModel {
}
export
interface
ISplitLine
{
isVisible
():
boolean
;
setVisible
(
isVisible
:
boolean
):
void
;
getOutputLineCount
():
number
;
getOutputLineContent
(
model
:
IModel
,
myLineNumber
:
number
,
outputLineIndex
:
number
):
string
;
getOutputLineMinColumn
(
model
:
IModel
,
myLineNumber
:
number
,
outputLineIndex
:
number
):
number
;
...
...
@@ -52,33 +55,66 @@ export interface ISplitLine {
class
IdentitySplitLine
implements
ISplitLine
{
public
static
INSTANCE
=
new
IdentitySplitLine
();
private
_isVisible
:
boolean
;
public
constructor
(
isVisible
:
boolean
)
{
this
.
_isVisible
=
isVisible
;
}
public
isVisible
():
boolean
{
return
this
.
_isVisible
;
}
public
setVisible
(
isVisible
:
boolean
):
void
{
this
.
_isVisible
=
isVisible
;
}
public
getOutputLineCount
():
number
{
if
(
!
this
.
_isVisible
)
{
return
0
;
}
return
1
;
}
public
getOutputLineContent
(
model
:
IModel
,
myLineNumber
:
number
,
outputLineIndex
:
number
):
string
{
if
(
!
this
.
_isVisible
)
{
throw
new
Error
(
'
Not supported
'
);
}
return
model
.
getLineContent
(
myLineNumber
);
}
public
getOutputLineMinColumn
(
model
:
IModel
,
myLineNumber
:
number
,
outputLineIndex
:
number
):
number
{
if
(
!
this
.
_isVisible
)
{
throw
new
Error
(
'
Not supported
'
);
}
return
model
.
getLineMinColumn
(
myLineNumber
);
}
public
getOutputLineMaxColumn
(
model
:
IModel
,
myLineNumber
:
number
,
outputLineIndex
:
number
):
number
{
if
(
!
this
.
_isVisible
)
{
throw
new
Error
(
'
Not supported
'
);
}
return
model
.
getLineMaxColumn
(
myLineNumber
);
}
public
getOutputLineTokens
(
model
:
IModel
,
myLineNumber
:
number
,
outputLineIndex
:
number
,
inaccurateTokensAcceptable
:
boolean
):
EditorCommon
.
IViewLineTokens
{
if
(
!
this
.
_isVisible
)
{
throw
new
Error
(
'
Not supported
'
);
}
return
new
IdentityFilteredLineTokens
(
model
.
getLineTokens
(
myLineNumber
,
inaccurateTokensAcceptable
),
model
.
getLineMaxColumn
(
myLineNumber
)
-
1
);
}
public
getInputColumnOfOutputPosition
(
outputLineIndex
:
number
,
outputColumn
:
number
):
number
{
if
(
!
this
.
_isVisible
)
{
throw
new
Error
(
'
Not supported
'
);
}
return
outputColumn
;
}
public
getOutputPositionOfInputPosition
(
deltaLineNumber
:
number
,
inputColumn
:
number
):
EditorCommon
.
IEditorPosition
{
if
(
!
this
.
_isVisible
)
{
throw
new
Error
(
'
Not supported
'
);
}
return
new
Position
(
deltaLineNumber
,
inputColumn
);
}
}
...
...
@@ -90,15 +126,28 @@ export class SplitLine implements ISplitLine {
private
wrappedIndent
:
string
;
private
wrappedIndentLength
:
number
;
private
_isVisible
:
boolean
;
constructor
(
positionMapper
:
ILineMapping
)
{
constructor
(
positionMapper
:
ILineMapping
,
isVisible
:
boolean
)
{
this
.
positionMapper
=
positionMapper
;
this
.
wrappedIndent
=
this
.
positionMapper
.
getWrappedLinesIndent
();
this
.
wrappedIndentLength
=
this
.
wrappedIndent
.
length
;
this
.
outputLineCount
=
this
.
positionMapper
.
getOutputLineCount
();
this
.
_isVisible
=
isVisible
;
}
public
isVisible
():
boolean
{
return
this
.
_isVisible
;
}
public
setVisible
(
isVisible
:
boolean
):
void
{
this
.
_isVisible
=
isVisible
;
}
public
getOutputLineCount
():
number
{
if
(
!
this
.
_isVisible
)
{
return
0
;
}
return
this
.
outputLineCount
;
}
...
...
@@ -114,6 +163,9 @@ export class SplitLine implements ISplitLine {
}
public
getOutputLineContent
(
model
:
IModel
,
myLineNumber
:
number
,
outputLineIndex
:
number
):
string
{
if
(
!
this
.
_isVisible
)
{
throw
new
Error
(
'
Not supported
'
);
}
var
startOffset
=
this
.
getInputStartOffsetOfOutputLineIndex
(
outputLineIndex
);
var
endOffset
=
this
.
getInputEndOffsetOfOutputLineIndex
(
model
,
myLineNumber
,
outputLineIndex
);
var
r
=
model
.
getLineContent
(
myLineNumber
).
substring
(
startOffset
,
endOffset
);
...
...
@@ -127,6 +179,9 @@ export class SplitLine implements ISplitLine {
public
getOutputLineMinColumn
(
model
:
IModel
,
myLineNumber
:
number
,
outputLineIndex
:
number
):
number
{
if
(
!
this
.
_isVisible
)
{
throw
new
Error
(
'
Not supported
'
);
}
if
(
outputLineIndex
>
0
)
{
return
this
.
wrappedIndentLength
+
1
;
}
...
...
@@ -134,10 +189,16 @@ export class SplitLine implements ISplitLine {
}
public
getOutputLineMaxColumn
(
model
:
IModel
,
myLineNumber
:
number
,
outputLineIndex
:
number
):
number
{
if
(
!
this
.
_isVisible
)
{
throw
new
Error
(
'
Not supported
'
);
}
return
this
.
getOutputLineContent
(
model
,
myLineNumber
,
outputLineIndex
).
length
+
1
;
}
public
getOutputLineTokens
(
model
:
IModel
,
myLineNumber
:
number
,
outputLineIndex
:
number
,
inaccurateTokensAcceptable
:
boolean
):
EditorCommon
.
IViewLineTokens
{
if
(
!
this
.
_isVisible
)
{
throw
new
Error
(
'
Not supported
'
);
}
var
startOffset
=
this
.
getInputStartOffsetOfOutputLineIndex
(
outputLineIndex
);
var
endOffset
=
this
.
getInputEndOffsetOfOutputLineIndex
(
model
,
myLineNumber
,
outputLineIndex
);
var
deltaStartIndex
=
0
;
...
...
@@ -148,6 +209,9 @@ export class SplitLine implements ISplitLine {
}
public
getInputColumnOfOutputPosition
(
outputLineIndex
:
number
,
outputColumn
:
number
):
number
{
if
(
!
this
.
_isVisible
)
{
throw
new
Error
(
'
Not supported
'
);
}
var
adjustedColumn
=
outputColumn
-
1
;
if
(
outputLineIndex
>
0
)
{
if
(
adjustedColumn
<
this
.
wrappedIndentLength
)
{
...
...
@@ -160,6 +224,9 @@ export class SplitLine implements ISplitLine {
}
public
getOutputPositionOfInputPosition
(
deltaLineNumber
:
number
,
inputColumn
:
number
):
EditorCommon
.
IEditorPosition
{
if
(
!
this
.
_isVisible
)
{
throw
new
Error
(
'
Not supported
'
);
}
this
.
positionMapper
.
getOutputPositionOfInputOffset
(
inputColumn
-
1
,
tmpOutputPosition
);
var
outputLineIndex
=
tmpOutputPosition
.
outputLineIndex
;
var
outputColumn
=
tmpOutputPosition
.
outputOffset
+
1
;
...
...
@@ -173,13 +240,13 @@ export class SplitLine implements ISplitLine {
}
}
function
createSplitLine
(
linePositionMapperFactory
:
ILineMapperFactory
,
text
:
string
,
tabSize
:
number
,
wrappingColumn
:
number
,
columnsForFullWidthChar
:
number
,
wrappingIndent
:
EditorCommon
.
WrappingIndent
):
ISplitLine
{
function
createSplitLine
(
linePositionMapperFactory
:
ILineMapperFactory
,
text
:
string
,
tabSize
:
number
,
wrappingColumn
:
number
,
columnsForFullWidthChar
:
number
,
wrappingIndent
:
EditorCommon
.
WrappingIndent
,
isVisible
:
boolean
):
ISplitLine
{
var
positionMapper
=
linePositionMapperFactory
.
createLineMapping
(
text
,
tabSize
,
wrappingColumn
,
columnsForFullWidthChar
,
wrappingIndent
);
if
(
positionMapper
===
null
)
{
// No mapping needed
return
IdentitySplitLine
.
INSTANCE
;
return
new
IdentitySplitLine
(
isVisible
)
;
}
else
{
return
new
SplitLine
(
positionMapper
);
return
new
SplitLine
(
positionMapper
,
isVisible
);
}
}
...
...
@@ -197,6 +264,7 @@ export class SplitLinesCollection implements ILinesCollection {
private
linePositionMapperFactory
:
ILineMapperFactory
;
private
tmpIndexOfResult
:
IPrefixSumIndexOfResult
;
private
hiddenAreasIds
:
string
[];
constructor
(
model
:
EditorCommon
.
IModel
,
linePositionMapperFactory
:
ILineMapperFactory
,
tabSize
:
number
,
wrappingColumn
:
number
,
columnsForFullWidthChar
:
number
,
wrappingIndent
:
EditorCommon
.
WrappingIndent
)
{
this
.
model
=
model
;
...
...
@@ -215,6 +283,10 @@ export class SplitLinesCollection implements ILinesCollection {
};
}
public
dispose
():
void
{
this
.
hiddenAreasIds
=
this
.
model
.
deltaDecorations
(
this
.
hiddenAreasIds
,
[]);
}
private
_ensureValidState
():
void
{
var
modelVersion
=
this
.
model
.
getVersionId
();
if
(
modelVersion
!==
this
.
_validModelVersionId
)
{
...
...
@@ -224,13 +296,14 @@ export class SplitLinesCollection implements ILinesCollection {
private
constructLines
():
void
{
this
.
lines
=
[];
this
.
hiddenAreasIds
=
[];
var
line
:
ISplitLine
,
values
:
number
[]
=
[],
linesContent
=
this
.
model
.
getLinesContent
();
for
(
var
i
=
0
,
lineCount
=
linesContent
.
length
;
i
<
lineCount
;
i
++
)
{
line
=
createSplitLine
(
this
.
linePositionMapperFactory
,
linesContent
[
i
],
this
.
tabSize
,
this
.
wrappingColumn
,
this
.
columnsForFullWidthChar
,
this
.
wrappingIndent
);
line
=
createSplitLine
(
this
.
linePositionMapperFactory
,
linesContent
[
i
],
this
.
tabSize
,
this
.
wrappingColumn
,
this
.
columnsForFullWidthChar
,
this
.
wrappingIndent
,
true
);
values
[
i
]
=
line
.
getOutputLineCount
();
this
.
lines
[
i
]
=
line
;
}
...
...
@@ -240,6 +313,62 @@ export class SplitLinesCollection implements ILinesCollection {
this
.
prefixSumComputer
=
new
PrefixSumComputer
(
values
);
}
private
getHiddenAreas
():
EditorCommon
.
IEditorRange
[]
{
return
this
.
hiddenAreasIds
.
map
((
decId
)
=>
{
return
this
.
model
.
getDecorationRange
(
decId
);
}).
sort
(
Range
.
compareRangesUsingStarts
);
}
public
setHiddenAreas
(
ranges
:
EditorCommon
.
IRange
[],
emit
:(
evenType
:
string
,
payload
:
any
)
=>
void
):
void
{
var
newDecorations
:
EditorCommon
.
IModelDeltaDecoration
[]
=
[];
for
(
var
i
=
0
;
i
<
ranges
.
length
;
i
++
)
{
newDecorations
.
push
({
range
:
ranges
[
i
],
options
:
{
}
});
}
this
.
hiddenAreasIds
=
this
.
model
.
deltaDecorations
(
this
.
hiddenAreasIds
,
newDecorations
);
var
hiddenAreas
=
this
.
getHiddenAreas
();
var
hiddenAreaStart
=
1
,
hiddenAreaEnd
=
0
;
var
hiddenAreaIdx
=
-
1
;
var
nextLineNumberToUpdateHiddenArea
=
(
hiddenAreaIdx
+
1
<
hiddenAreas
.
length
)
?
hiddenAreaEnd
+
1
:
this
.
lines
.
length
+
2
;
for
(
var
i
=
0
;
i
<
this
.
lines
.
length
;
i
++
)
{
var
lineNumber
=
i
+
1
;
if
(
lineNumber
===
nextLineNumberToUpdateHiddenArea
)
{
hiddenAreaIdx
++
;
hiddenAreaStart
=
hiddenAreas
[
hiddenAreaIdx
].
startLineNumber
;
hiddenAreaEnd
=
hiddenAreas
[
hiddenAreaIdx
].
endLineNumber
;
nextLineNumberToUpdateHiddenArea
=
(
hiddenAreaIdx
+
1
<
hiddenAreas
.
length
)
?
hiddenAreaEnd
+
1
:
this
.
lines
.
length
+
2
;
}
var
lineChanged
=
false
;
if
(
lineNumber
>=
hiddenAreaStart
&&
lineNumber
<=
hiddenAreaEnd
)
{
// Line should be hidden
if
(
this
.
lines
[
i
].
isVisible
())
{
this
.
lines
[
i
].
setVisible
(
false
);
lineChanged
=
true
;
}
}
else
{
// Line should be visible
if
(
!
this
.
lines
[
i
].
isVisible
())
{
this
.
lines
[
i
].
setVisible
(
true
);
lineChanged
=
true
;
}
}
if
(
lineChanged
)
{
var
newOutputLineCount
=
this
.
lines
[
i
].
getOutputLineCount
();
this
.
prefixSumComputer
.
changeValue
(
i
,
newOutputLineCount
);
}
}
emit
(
EditorCommon
.
ViewEventNames
.
ModelFlushedEvent
,
null
);
}
public
setTabSize
(
newTabSize
:
number
,
emit
:(
evenType
:
string
,
payload
:
any
)
=>
void
):
boolean
{
if
(
this
.
tabSize
===
newTabSize
)
{
return
false
;
...
...
@@ -286,6 +415,7 @@ export class SplitLinesCollection implements ILinesCollection {
return
;
}
this
.
_validModelVersionId
=
versionId
;
var
outputFromLineNumber
=
(
fromLineNumber
===
1
?
1
:
this
.
prefixSumComputer
.
getAccumulatedValue
(
fromLineNumber
-
2
)
+
1
);
var
outputToLineNumber
=
this
.
prefixSumComputer
.
getAccumulatedValue
(
toLineNumber
-
1
);
...
...
@@ -304,6 +434,17 @@ export class SplitLinesCollection implements ILinesCollection {
return
;
}
this
.
_validModelVersionId
=
versionId
;
var
hiddenAreas
=
this
.
getHiddenAreas
();
var
isInHiddenArea
=
false
;
var
testPosition
=
new
Position
(
fromLineNumber
,
1
);
for
(
var
i
=
0
;
i
<
hiddenAreas
.
length
;
i
++
)
{
if
(
hiddenAreas
[
i
].
containsPosition
(
testPosition
))
{
isInHiddenArea
=
true
;
break
;
}
}
var
outputFromLineNumber
=
(
fromLineNumber
===
1
?
1
:
this
.
prefixSumComputer
.
getAccumulatedValue
(
fromLineNumber
-
2
)
+
1
);
var
line
:
ISplitLine
,
...
...
@@ -314,7 +455,7 @@ export class SplitLinesCollection implements ILinesCollection {
insertPrefixSumValues
:
number
[]
=
[];
for
(
var
i
=
0
,
len
=
text
.
length
;
i
<
len
;
i
++
)
{
var
line
=
createSplitLine
(
this
.
linePositionMapperFactory
,
text
[
i
],
this
.
tabSize
,
this
.
wrappingColumn
,
this
.
columnsForFullWidthChar
,
this
.
wrappingIndent
);
var
line
=
createSplitLine
(
this
.
linePositionMapperFactory
,
text
[
i
],
this
.
tabSize
,
this
.
wrappingColumn
,
this
.
columnsForFullWidthChar
,
this
.
wrappingIndent
,
!
isInHiddenArea
);
insertLines
.
push
(
line
);
outputLineCount
=
line
.
getOutputLineCount
();
...
...
@@ -341,7 +482,8 @@ export class SplitLinesCollection implements ILinesCollection {
var
lineIndex
=
lineNumber
-
1
;
var
oldOutputLineCount
=
this
.
lines
[
lineIndex
].
getOutputLineCount
();
var
line
=
createSplitLine
(
this
.
linePositionMapperFactory
,
newText
,
this
.
tabSize
,
this
.
wrappingColumn
,
this
.
columnsForFullWidthChar
,
this
.
wrappingIndent
);
var
isVisible
=
this
.
lines
[
lineIndex
].
isVisible
();
var
line
=
createSplitLine
(
this
.
linePositionMapperFactory
,
newText
,
this
.
tabSize
,
this
.
wrappingColumn
,
this
.
columnsForFullWidthChar
,
this
.
wrappingIndent
,
isVisible
);
this
.
lines
[
lineIndex
]
=
line
;
var
newOutputLineCount
=
this
.
lines
[
lineIndex
].
getOutputLineCount
();
...
...
@@ -460,8 +602,25 @@ export class SplitLinesCollection implements ILinesCollection {
if
(
inputLineNumber
>
this
.
lines
.
length
)
{
inputLineNumber
=
this
.
lines
.
length
;
}
var
deltaLineNumber
=
1
+
(
inputLineNumber
===
1
?
0
:
this
.
prefixSumComputer
.
getAccumulatedValue
(
inputLineNumber
-
2
));
var
r
=
this
.
lines
[
inputLineNumber
-
1
].
getOutputPositionOfInputPosition
(
deltaLineNumber
,
inputColumn
);
let
lineIndex
=
inputLineNumber
-
1
,
lineIndexChanged
=
false
;
while
(
lineIndex
>
0
&&
!
this
.
lines
[
lineIndex
].
isVisible
())
{
lineIndex
--
;
lineIndexChanged
=
true
;
}
if
(
lineIndex
===
0
&&
!
this
.
lines
[
lineIndex
].
isVisible
())
{
// Could not reach a real line
return
new
Position
(
1
,
1
);
}
var
deltaLineNumber
=
1
+
(
lineIndex
===
0
?
0
:
this
.
prefixSumComputer
.
getAccumulatedValue
(
lineIndex
-
1
));
var
r
:
EditorCommon
.
IEditorPosition
;
if
(
lineIndexChanged
)
{
r
=
this
.
lines
[
lineIndex
].
getOutputPositionOfInputPosition
(
deltaLineNumber
,
this
.
model
.
getLineMaxColumn
(
lineIndex
+
1
));
}
else
{
r
=
this
.
lines
[
inputLineNumber
-
1
].
getOutputPositionOfInputPosition
(
deltaLineNumber
,
inputColumn
);
}
// console.log('in -> out ' + inputLineNumber + ',' + inputColumn + ' ===> ' + r.lineNumber + ',' + r.column);
return
r
;
}
...
...
src/vs/editor/common/viewModel/viewModel.ts
浏览文件 @
71c8b150
...
...
@@ -30,6 +30,8 @@ export interface ILinesCollection {
getOutputLineTokens
(
outputLineNumber
:
number
,
inaccurateTokensAcceptable
:
boolean
):
EditorCommon
.
IViewLineTokens
;
convertOutputPositionToInputPosition
(
viewLineNumber
:
number
,
viewColumn
:
number
):
EditorCommon
.
IEditorPosition
;
convertInputPositionToOutputPosition
(
inputLineNumber
:
number
,
inputColumn
:
number
):
EditorCommon
.
IEditorPosition
;
setHiddenAreas
(
ranges
:
EditorCommon
.
IRange
[],
emit
:(
evenType
:
string
,
payload
:
any
)
=>
void
):
void
;
dispose
():
void
;
}
export
class
ViewModel
extends
EventEmitter
implements
EditorCommon
.
IViewModel
{
...
...
@@ -78,6 +80,14 @@ export class ViewModel extends EventEmitter implements EditorCommon.IViewModel {
}));
}
public
setHiddenAreas
(
ranges
:
EditorCommon
.
IRange
[]):
void
{
this
.
deferredEmit
(()
=>
{
this
.
lines
.
setHiddenAreas
(
ranges
,
(
eventType
:
string
,
payload
:
any
)
=>
this
.
emit
(
eventType
,
payload
));
this
.
decorations
.
onLineMappingChanged
((
eventType
:
string
,
payload
:
any
)
=>
this
.
emit
(
eventType
,
payload
));
this
.
cursors
.
onLineMappingChanged
((
eventType
:
string
,
payload
:
any
)
=>
this
.
emit
(
eventType
,
payload
));
});
}
public
dispose
():
void
{
this
.
listenersToRemove
.
forEach
((
element
)
=>
{
element
();
...
...
@@ -86,6 +96,7 @@ export class ViewModel extends EventEmitter implements EditorCommon.IViewModel {
this
.
listenersToRemove
=
[];
this
.
decorations
.
dispose
();
this
.
decorations
=
null
;
this
.
lines
.
dispose
();
this
.
lines
=
null
;
this
.
configuration
=
null
;
this
.
model
=
null
;
...
...
src/vs/editor/contrib/folding/browser/arrow-collapse-dark.svg
0 → 100644
浏览文件 @
71c8b150
<svg
xmlns=
"http://www.w3.org/2000/svg"
width=
"16"
height=
"16"
><path
fill=
"#e8e8e8"
d=
"M6 4v8l4-4-4-4zm1 2.414l1.586 1.586-1.586 1.586v-3.172z"
/></svg>
\ No newline at end of file
src/vs/editor/contrib/folding/browser/arrow-collapse.svg
0 → 100644
浏览文件 @
71c8b150
<svg
xmlns=
"http://www.w3.org/2000/svg"
width=
"16"
height=
"16"
><path
fill=
"#646465"
d=
"M6 4v8l4-4-4-4zm1 2.414l1.586 1.586-1.586 1.586v-3.172z"
/></svg>
\ No newline at end of file
src/vs/editor/contrib/folding/browser/arrow-expand-dark.svg
0 → 100644
浏览文件 @
71c8b150
<svg
xmlns=
"http://www.w3.org/2000/svg"
width=
"16"
height=
"16"
><path
fill=
"#e8e8e8"
d=
"M11 10.07h-5.656l5.656-5.656v5.656z"
/></svg>
\ No newline at end of file
src/vs/editor/contrib/folding/browser/arrow-expand.svg
0 → 100644
浏览文件 @
71c8b150
<svg
xmlns=
"http://www.w3.org/2000/svg"
width=
"16"
height=
"16"
><path
fill=
"#646465"
d=
"M11 10.07h-5.656l5.656-5.656v5.656z"
/></svg>
\ No newline at end of file
src/vs/editor/contrib/folding/browser/folding.css
0 → 100644
浏览文件 @
71c8b150
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
.monaco-editor
.folding
{
background-image
:
url('arrow-expand.svg')
;
background-repeat
:
no-repeat
;
margin-left
:
5px
;
}
.monaco-editor
.folding.collapsed
{
background-image
:
url('arrow-collapse.svg')
;
}
.vs-dark
.monaco-editor
.folding
{
background-image
:
url('arrow-expand-dark.svg')
;
}
.vs-dark
.monaco-editor
.folding.collapsed
{
background-image
:
url('arrow-collapse-dark.svg')
;
}
.monaco-editor
.inline-folded
{
color
:
grey
!important
;
}
.monaco-editor
.inline-folded
:after
{
color
:
grey
;
margin
:
0.1em
0.2em
0
0.2em
;
content
:
"⋯"
;
display
:
inline-block
;
line-height
:
1em
;
}
src/vs/editor/contrib/folding/browser/folding.ts
0 → 100644
浏览文件 @
71c8b150
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
/// <amd-dependency path="vs/css!./folding" />
'
use strict
'
;
import
{
RunOnceScheduler
}
from
'
vs/base/common/async
'
;
import
{
Range
}
from
'
vs/editor/common/core/range
'
;
import
EditorCommon
=
require
(
'
vs/editor/common/editorCommon
'
);
import
{
IMouseEvent
,
ICodeEditor
}
from
'
vs/editor/browser/editorBrowser
'
;
import
{
INullService
}
from
'
vs/platform/instantiation/common/instantiation
'
;
import
{
IDisposable
,
disposeAll
}
from
'
vs/base/common/lifecycle
'
;
import
Modes
=
require
(
'
vs/editor/common/modes
'
);
import
{
EditorBrowserRegistry
}
from
'
vs/editor/browser/editorBrowserExtensions
'
;
import
{
TPromise
}
from
'
vs/base/common/winjs.base
'
;
import
foldStrategy
=
require
(
'
vs/editor/contrib/folding/common/indentFoldStrategy
'
);
import
{
IFoldingRange
}
from
'
vs/editor/contrib/folding/common/foldingRange
'
;
class
CollapsableRegion
{
public
visualDecorationId
:
string
;
public
rangeDecorationId
:
string
;
public
isCollapsed
:
boolean
;
public
constructor
(
range
:
IFoldingRange
,
model
:
EditorCommon
.
IModel
,
changeAccessor
:
EditorCommon
.
IModelDecorationsChangeAccessor
,
isCollapsed
:
boolean
)
{
this
.
isCollapsed
=
isCollapsed
;
var
maxColumn
=
model
.
getLineMaxColumn
(
range
.
startLineNumber
);
var
visualRng
=
{
startLineNumber
:
range
.
startLineNumber
,
startColumn
:
maxColumn
-
1
,
endLineNumber
:
range
.
startLineNumber
,
endColumn
:
maxColumn
};
this
.
visualDecorationId
=
changeAccessor
.
addDecoration
(
visualRng
,
this
.
getVisualDecorationOptions
());
var
colRng
=
{
startLineNumber
:
range
.
startLineNumber
,
startColumn
:
1
,
endLineNumber
:
range
.
endLineNumber
,
endColumn
:
model
.
getLineMaxColumn
(
range
.
endLineNumber
)
};
this
.
rangeDecorationId
=
changeAccessor
.
addDecoration
(
colRng
,
{});
}
public
getVisualDecorationOptions
():
EditorCommon
.
IModelDecorationOptions
{
if
(
this
.
isCollapsed
)
{
return
{
inlineClassName
:
'
inline-folded
'
,
linesDecorationsClassName
:
'
folding collapsed
'
};
}
else
{
return
{
linesDecorationsClassName
:
'
folding
'
};
}
}
public
dispose
(
changeAccessor
:
EditorCommon
.
IModelDecorationsChangeAccessor
):
void
{
changeAccessor
.
removeDecoration
(
this
.
visualDecorationId
);
changeAccessor
.
removeDecoration
(
this
.
rangeDecorationId
);
}
}
export
class
Folding
implements
EditorCommon
.
IEditorContribution
{
static
ID
=
'
editor.contrib.folding
'
;
private
editor
:
ICodeEditor
;
private
globalToDispose
:
IDisposable
[];
private
computeToken
:
number
;
private
updateScheduler
:
RunOnceScheduler
;
private
localToDispose
:
IDisposable
[];
private
decorations
:
CollapsableRegion
[];
constructor
(
editor
:
ICodeEditor
,
@
INullService
nullService
)
{
this
.
editor
=
editor
;
this
.
globalToDispose
=
[];
this
.
localToDispose
=
[];
this
.
decorations
=
[];
this
.
computeToken
=
0
;
this
.
globalToDispose
.
push
(
this
.
editor
.
addListener2
(
EditorCommon
.
EventType
.
ModelChanged
,
()
=>
this
.
onModelChanged
()));
this
.
globalToDispose
.
push
(
this
.
editor
.
addListener2
(
EditorCommon
.
EventType
.
ModelModeChanged
,
()
=>
this
.
onModelChanged
()));
this
.
onModelChanged
();
}
public
getId
():
string
{
return
Folding
.
ID
;
}
public
dispose
():
void
{
this
.
cleanState
();
this
.
globalToDispose
=
disposeAll
(
this
.
globalToDispose
);
}
private
cleanState
():
void
{
this
.
localToDispose
=
disposeAll
(
this
.
localToDispose
);
}
private
onModelChanged
():
void
{
this
.
cleanState
();
var
model
=
this
.
editor
.
getModel
();
if
(
!
model
)
{
return
;
}
this
.
updateScheduler
=
new
RunOnceScheduler
(()
=>
{
var
myToken
=
(
++
this
.
computeToken
);
this
.
computeCollapsableRegions
().
then
(
regions
=>
{
if
(
myToken
!==
this
.
computeToken
)
{
// A new request was made in the meantime or the model was changed
return
;
}
this
.
editor
.
changeDecorations
((
changeAccessor
:
EditorCommon
.
IModelDecorationsChangeAccessor
)
=>
{
var
collapsedStartLineNumbers
:{[
lineNumber
:
string
]:
boolean
}
=
{};
this
.
decorations
.
forEach
((
dec
)
=>
{
if
(
dec
.
isCollapsed
)
{
var
oldRange
=
model
.
getDecorationRange
(
dec
.
visualDecorationId
);
collapsedStartLineNumbers
[
oldRange
.
startLineNumber
.
toString
()]
=
true
;
}
changeAccessor
.
removeDecoration
(
dec
.
rangeDecorationId
);
changeAccessor
.
removeDecoration
(
dec
.
visualDecorationId
);
});
this
.
decorations
=
[];
regions
.
forEach
(
region
=>
{
this
.
decorations
.
push
(
new
CollapsableRegion
(
region
,
model
,
changeAccessor
,
collapsedStartLineNumbers
[
region
.
startLineNumber
.
toString
()]));
});
});
this
.
updateHiddenAreas
();
});
},
500
);
this
.
localToDispose
.
push
(
this
.
updateScheduler
);
this
.
localToDispose
.
push
(
this
.
editor
.
addListener2
(
'
change
'
,
()
=>
this
.
updateScheduler
.
schedule
()));
this
.
localToDispose
.
push
({
dispose
:
()
=>
{
++
this
.
computeToken
;
this
.
editor
.
changeDecorations
((
changeAccessor
:
EditorCommon
.
IModelDecorationsChangeAccessor
)
=>
{
this
.
decorations
.
forEach
((
dec
)
=>
dec
.
dispose
(
changeAccessor
));
});
}});
this
.
localToDispose
.
push
(
this
.
editor
.
addListener2
(
EditorCommon
.
EventType
.
MouseDown
,
(
e
)
=>
this
.
_onEditorMouseDown
(
e
)));
this
.
updateScheduler
.
schedule
();
}
private
computeCollapsableRegions
()
:
TPromise
<
IFoldingRange
[]
>
{
let
tabSize
=
this
.
editor
.
getIndentationOptions
().
tabSize
;
var
model
=
this
.
editor
.
getModel
();
if
(
!
model
)
{
return
TPromise
.
as
([]);
}
let
ranges
=
foldStrategy
.
computeRanges
(
model
,
tabSize
);
return
TPromise
.
as
(
ranges
);
}
private
_onEditorMouseDown
(
e
:
IMouseEvent
):
void
{
if
(
e
.
target
.
type
!==
EditorCommon
.
MouseTargetType
.
GUTTER_LINE_DECORATIONS
)
{
return
;
}
if
(
this
.
decorations
.
length
===
0
)
{
return
;
}
var
position
=
e
.
target
.
position
;
if
(
!
position
)
{
return
;
}
var
model
=
this
.
editor
.
getModel
();
var
hasChanges
=
false
;
this
.
editor
.
changeDecorations
((
changeAccessor
:
EditorCommon
.
IModelDecorationsChangeAccessor
)
=>
{
for
(
var
i
=
0
;
i
<
this
.
decorations
.
length
;
i
++
)
{
var
dec
=
this
.
decorations
[
i
];
var
decRange
=
model
.
getDecorationRange
(
dec
.
rangeDecorationId
);
if
(
decRange
.
startLineNumber
===
position
.
lineNumber
)
{
dec
.
isCollapsed
=
!
dec
.
isCollapsed
;
changeAccessor
.
changeDecorationOptions
(
dec
.
visualDecorationId
,
dec
.
getVisualDecorationOptions
());
hasChanges
=
true
;
break
;
}
}
});
if
(
hasChanges
)
{
this
.
updateHiddenAreas
();
}
}
private
updateHiddenAreas
():
void
{
var
model
=
this
.
editor
.
getModel
();
var
hiddenAreas
:
EditorCommon
.
IRange
[]
=
[];
this
.
decorations
.
filter
((
dec
)
=>
dec
.
isCollapsed
).
forEach
((
dec
)
=>
{
var
decRange
=
model
.
getDecorationRange
(
dec
.
rangeDecorationId
);
hiddenAreas
.
push
({
startLineNumber
:
decRange
.
startLineNumber
+
1
,
startColumn
:
1
,
endLineNumber
:
decRange
.
endLineNumber
,
endColumn
:
1
});
});
this
.
editor
.
setHiddenAreas
(
hiddenAreas
);
}
}
EditorBrowserRegistry
.
registerEditorContribution
(
Folding
);
\ No newline at end of file
src/vs/editor/contrib/folding/common/foldingRange.ts
0 → 100644
浏览文件 @
71c8b150
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'
use strict
'
;
export
interface
IFoldingRange
{
startLineNumber
:
number
;
endLineNumber
:
number
;
}
\ No newline at end of file
src/vs/editor/contrib/folding/common/indentFoldStrategy.ts
0 → 100644
浏览文件 @
71c8b150
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'
use strict
'
;
import
{
TPromise
}
from
'
vs/base/common/winjs.base
'
;
import
EditorCommon
=
require
(
'
vs/editor/common/editorCommon
'
);
import
{
IFoldingRange
}
from
'
vs/editor/contrib/folding/common/foldingRange
'
;
export
function
computeRanges
(
model
:
EditorCommon
.
IModel
,
tabSize
:
number
,
minimumRangeSize
:
number
=
1
)
:
IFoldingRange
[]
{
let
result
:
IFoldingRange
[]
=
[];
let
createRange
=
(
startLineNumber
:
number
,
endLineNumber
:
number
)
=>
{
// create a collapsible region only if has the minimumRangeSize
if
(
endLineNumber
-
startLineNumber
>=
minimumRangeSize
)
{
result
.
push
({
startLineNumber
,
endLineNumber
});
}
}
var
previousRegions
:
{
indent
:
number
,
line
:
number
}[]
=
[];
previousRegions
.
push
({
indent
:
-
1
,
line
:
model
.
getLineCount
()
+
1
});
// sentinel, not make sure there's at least one entry
for
(
var
line
=
model
.
getLineCount
();
line
>
0
;
line
--
)
{
var
indent
=
computeIndentLevel
(
model
.
getLineContent
(
line
),
tabSize
);
let
previous
=
previousRegions
[
previousRegions
.
length
-
1
];
// all previous regions with larger indent can be completed
if
(
previous
.
indent
>
indent
)
{
do
{
previousRegions
.
pop
();
previous
=
previousRegions
[
previousRegions
.
length
-
1
];
}
while
(
previous
.
indent
>
indent
);
createRange
(
line
,
previous
.
line
-
1
);
if
(
previous
.
indent
===
indent
)
{
previous
.
line
=
line
;
}
}
if
(
previous
.
indent
<
indent
)
{
// new region with a bigger indent
previousRegions
.
push
({
indent
,
line
});
}
}
return
result
;
}
function
computeIndentLevel
(
line
:
string
,
tabSize
:
number
):
number
{
let
i
=
0
;
let
indent
=
0
;
while
(
i
<
line
.
length
)
{
let
ch
=
line
.
charAt
(
i
);
if
(
ch
===
'
'
)
{
indent
++
;
}
else
if
(
ch
===
'
\t
'
)
{
indent
++
;
indent
+=
(
indent
%
tabSize
);
}
else
{
break
;
}
i
++
;
}
return
indent
;
}
src/vs/editor/contrib/folding/test/indentFold.test.ts
0 → 100644
浏览文件 @
71c8b150
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'
use strict
'
;
import
assert
=
require
(
'
assert
'
);
import
foldStrategy
=
require
(
'
vs/editor/contrib/folding/common/indentFoldStrategy
'
);
import
{
IFoldingRange
}
from
'
vs/editor/contrib/folding/common/foldingRange
'
;
import
{
Model
}
from
'
vs/editor/common/model/model
'
;
suite
(
'
Folding
'
,
()
=>
{
function
assertRanges
(
lines
:
string
[],
tabSize
:
number
,
expected
:
IFoldingRange
[]):
void
{
let
model
=
new
Model
(
lines
.
join
(
'
\n
'
),
null
);
let
actual
=
foldStrategy
.
computeRanges
(
model
,
tabSize
);
actual
.
sort
((
r1
,
r2
)
=>
r1
.
startLineNumber
-
r2
.
startLineNumber
);
assert
.
deepEqual
(
actual
,
expected
);
model
.
dispose
();
}
function
r
(
startLineNumber
:
number
,
endLineNumber
:
number
):
IFoldingRange
{
return
{
startLineNumber
,
endLineNumber
};
}
test
(
'
t1
'
,
()
=>
{
assertRanges
([
'
A
'
,
'
A
'
,
'
A
'
,
'
A
'
],
4
,
[
r
(
1
,
4
)]);
});
test
(
'
t2
'
,
()
=>
{
assertRanges
([
'
A
'
,
'
A
'
,
'
A
'
,
'
A
'
,
'
A
'
],
4
,
[
r
(
1
,
5
),
r
(
3
,
5
)]
);
});
test
(
'
t3
'
,
()
=>
{
assertRanges
([
'
A
'
,
'
A
'
,
'
A
'
,
'
A
'
,
'
A
'
],
4
,
[
r
(
1
,
4
),
r
(
2
,
4
),
r
(
3
,
4
)]
);
});
test
(
'
t4
'
,
()
=>
{
assertRanges
([
'
A
'
,
'
A
'
,
'
A
'
],
4
,
[]
);
});
test
(
'
Javadoc
'
,
()
=>
{
assertRanges
([
'
/**
'
,
'
* Comment
'
,
'
*/
'
,
'
class A {
'
,
'
void foo() {
'
,
'
}
'
,
'
}
'
,
],
4
,
[
r
(
1
,
3
),
r
(
4
,
6
)]
);
});
})
\ No newline at end of file
src/vs/editor/test/common/viewModel/splitLinesCollection.test.ts
浏览文件 @
71c8b150
...
...
@@ -83,8 +83,8 @@ function pos(lineNumber: number, column: number): Position.Position {
return
new
Position
.
Position
(
lineNumber
,
column
);
}
function
createSplitLine
(
splitLengths
:
number
[],
wrappedLinesPrefix
:
string
):
SplitLinesCollection
.
SplitLine
{
return
new
SplitLinesCollection
.
SplitLine
(
createLineMapping
(
splitLengths
,
wrappedLinesPrefix
));
function
createSplitLine
(
splitLengths
:
number
[],
wrappedLinesPrefix
:
string
,
isVisible
:
boolean
=
true
):
SplitLinesCollection
.
SplitLine
{
return
new
SplitLinesCollection
.
SplitLine
(
createLineMapping
(
splitLengths
,
wrappedLinesPrefix
)
,
isVisible
);
}
function
createLineMapping
(
breakingLengths
:
number
[],
wrappedLinesPrefix
:
string
):
SplitLinesCollection
.
ILineMapping
{
...
...
src/vs/workbench/browser/parts/editor/textEditor.ts
浏览文件 @
71c8b150
...
...
@@ -111,6 +111,7 @@ export abstract class BaseTextEditor extends BaseEditor {
overviewRulerLanes
:
3
,
readOnly
:
this
.
contextService
.
getOptions
().
readOnly
,
glyphMargin
:
true
,
lineDecorationsWidth
:
24
,
lineNumbersMinChars
:
3
,
theme
:
this
.
_storageService
.
get
(
Preferences
.
THEME
,
StorageScope
.
GLOBAL
,
DEFAULT_THEME_ID
)
};
...
...
src/vs/workbench/parts/git/browser/media/git.contribution.css
浏览文件 @
71c8b150
...
...
@@ -49,24 +49,20 @@
/* Git dirty diff editor decorations */
.monaco-editor
.git-dirty-modified-diff-glyph
{
b
ackground-color
:
rgba
(
0
,
122
,
204
,
0.6
);
b
order-left
:
3px
solid
rgba
(
0
,
122
,
204
,
0.6
);
margin-left
:
5px
;
width
:
3px
!important
;
}
.monaco-editor.vs-dark
.git-dirty-modified-diff-glyph
{
b
ackground-color
:
rgba
(
0
,
188
,
242
,
0.6
);
b
order-left
:
3px
solid
rgba
(
0
,
188
,
242
,
0.6
);
margin-left
:
5px
;
width
:
3px
!important
;
}
.monaco-editor
.git-dirty-added-diff-glyph
{
b
ackground-color
:
rgba
(
45
,
136
,
62
,
0.6
);
b
order-left
:
3px
solid
rgba
(
45
,
136
,
62
,
0.6
);
margin-left
:
5px
;
width
:
3px
!important
;
}
.monaco-editor.vs-dark
.git-dirty-added-diff-glyph
{
b
ackground-color
:
rgba
(
127
,
186
,
0
,
0.6
);
b
order-left
:
3px
solid
rgba
(
127
,
186
,
0
,
0.6
);
margin-left
:
5px
;
width
:
3px
!important
;
}
.monaco-editor
.git-dirty-deleted-diff-glyph
:after
{
content
:
''
;
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录