Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
xxadev
vscode
提交
26b7ed52
V
vscode
项目概览
xxadev
/
vscode
与 Fork 源项目一致
从无法访问的项目Fork
通知
2
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
V
vscode
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
未验证
提交
26b7ed52
编写于
10月 17, 2019
作者:
A
Alexandru Dima
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Fixes #1772: Have bracket actions go to enclosing brackets when not on a bracket
上级
157a3ac5
变更
5
隐藏空白更改
内联
并排
Showing
5 changed file
with
164 addition
and
8 deletion
+164
-8
src/vs/editor/common/model.ts
src/vs/editor/common/model.ts
+7
-0
src/vs/editor/common/model/textModel.ts
src/vs/editor/common/model/textModel.ts
+112
-0
src/vs/editor/common/modes/supports/richEditBrackets.ts
src/vs/editor/common/modes/supports/richEditBrackets.ts
+4
-1
src/vs/editor/contrib/bracketMatching/bracketMatching.ts
src/vs/editor/contrib/bracketMatching/bracketMatching.ts
+16
-7
src/vs/editor/contrib/bracketMatching/test/bracketMatching.test.ts
...itor/contrib/bracketMatching/test/bracketMatching.test.ts
+25
-0
未找到文件。
src/vs/editor/common/model.ts
浏览文件 @
26b7ed52
...
...
@@ -881,6 +881,13 @@ export interface ITextModel {
*/
findNextBracket
(
position
:
IPosition
):
IFoundBracket
|
null
;
/**
* Find the enclosing brackets that contain `position`.
* @param position The position at which to start the search.
* @internal
*/
findEnclosingBrackets
(
position
:
IPosition
):
[
Range
,
Range
]
|
null
;
/**
* Given a `position`, if the position is on top or near a bracket,
* find the matching bracket of that bracket and return the ranges of both brackets.
...
...
src/vs/editor/common/model/textModel.ts
浏览文件 @
26b7ed52
...
...
@@ -2317,6 +2317,118 @@ export class TextModel extends Disposable implements model.ITextModel {
return
null
;
}
public
findEnclosingBrackets
(
_position
:
IPosition
):
[
Range
,
Range
]
|
null
{
const
position
=
this
.
validatePosition
(
_position
);
const
lineCount
=
this
.
getLineCount
();
let
counts
:
number
[]
=
[];
const
resetCounts
=
(
modeBrackets
:
RichEditBrackets
|
null
)
=>
{
counts
=
[];
for
(
let
i
=
0
,
len
=
modeBrackets
?
modeBrackets
.
brackets
.
length
:
0
;
i
<
len
;
i
++
)
{
counts
[
i
]
=
0
;
}
};
const
searchInRange
=
(
modeBrackets
:
RichEditBrackets
,
lineNumber
:
number
,
lineText
:
string
,
searchStartOffset
:
number
,
searchEndOffset
:
number
):
[
Range
,
Range
]
|
null
=>
{
while
(
true
)
{
const
r
=
BracketsUtils
.
findNextBracketInRange
(
modeBrackets
.
forwardRegex
,
lineNumber
,
lineText
,
searchStartOffset
,
searchEndOffset
);
if
(
!
r
)
{
break
;
}
const
hitText
=
lineText
.
substring
(
r
.
startColumn
-
1
,
r
.
endColumn
-
1
).
toLowerCase
();
const
bracket
=
modeBrackets
.
textIsBracket
[
hitText
];
if
(
bracket
)
{
if
(
bracket
.
isOpen
(
hitText
))
{
counts
[
bracket
.
index
]
++
;
}
else
if
(
bracket
.
isClose
(
hitText
))
{
counts
[
bracket
.
index
]
--
;
}
if
(
counts
[
bracket
.
index
]
===
-
1
)
{
return
this
.
_matchFoundBracket
(
r
,
bracket
,
false
);
}
}
searchStartOffset
=
r
.
endColumn
-
1
;
}
return
null
;
};
let
languageId
:
LanguageId
=
-
1
;
let
modeBrackets
:
RichEditBrackets
|
null
=
null
;
for
(
let
lineNumber
=
position
.
lineNumber
;
lineNumber
<=
lineCount
;
lineNumber
++
)
{
const
lineTokens
=
this
.
_getLineTokens
(
lineNumber
);
const
tokenCount
=
lineTokens
.
getCount
();
const
lineText
=
this
.
_buffer
.
getLineContent
(
lineNumber
);
let
tokenIndex
=
0
;
let
searchStartOffset
=
0
;
let
searchEndOffset
=
0
;
if
(
lineNumber
===
position
.
lineNumber
)
{
tokenIndex
=
lineTokens
.
findTokenIndexAtOffset
(
position
.
column
-
1
);
searchStartOffset
=
position
.
column
-
1
;
searchEndOffset
=
position
.
column
-
1
;
const
tokenLanguageId
=
lineTokens
.
getLanguageId
(
tokenIndex
);
if
(
languageId
!==
tokenLanguageId
)
{
languageId
=
tokenLanguageId
;
modeBrackets
=
LanguageConfigurationRegistry
.
getBracketsSupport
(
languageId
);
resetCounts
(
modeBrackets
);
}
}
let
prevSearchInToken
=
true
;
for
(;
tokenIndex
<
tokenCount
;
tokenIndex
++
)
{
const
tokenLanguageId
=
lineTokens
.
getLanguageId
(
tokenIndex
);
if
(
languageId
!==
tokenLanguageId
)
{
// language id change!
if
(
modeBrackets
&&
prevSearchInToken
&&
searchStartOffset
!==
searchEndOffset
)
{
const
r
=
searchInRange
(
modeBrackets
,
lineNumber
,
lineText
,
searchStartOffset
,
searchEndOffset
);
if
(
r
)
{
return
r
;
}
prevSearchInToken
=
false
;
}
languageId
=
tokenLanguageId
;
modeBrackets
=
LanguageConfigurationRegistry
.
getBracketsSupport
(
languageId
);
resetCounts
(
modeBrackets
);
}
const
searchInToken
=
(
!!
modeBrackets
&&
!
ignoreBracketsInToken
(
lineTokens
.
getStandardTokenType
(
tokenIndex
)));
if
(
searchInToken
)
{
// this token should be searched
if
(
prevSearchInToken
)
{
// the previous token should be searched, simply extend searchEndOffset
searchEndOffset
=
lineTokens
.
getEndOffset
(
tokenIndex
);
}
else
{
// the previous token should not be searched
searchStartOffset
=
lineTokens
.
getStartOffset
(
tokenIndex
);
searchEndOffset
=
lineTokens
.
getEndOffset
(
tokenIndex
);
}
}
else
{
// this token should not be searched
if
(
modeBrackets
&&
prevSearchInToken
&&
searchStartOffset
!==
searchEndOffset
)
{
const
r
=
searchInRange
(
modeBrackets
,
lineNumber
,
lineText
,
searchStartOffset
,
searchEndOffset
);
if
(
r
)
{
return
r
;
}
}
}
prevSearchInToken
=
searchInToken
;
}
if
(
modeBrackets
&&
prevSearchInToken
&&
searchStartOffset
!==
searchEndOffset
)
{
const
r
=
searchInRange
(
modeBrackets
,
lineNumber
,
lineText
,
searchStartOffset
,
searchEndOffset
);
if
(
r
)
{
return
r
;
}
}
}
return
null
;
}
private
_toFoundBracket
(
modeBrackets
:
RichEditBrackets
,
r
:
Range
):
model
.
IFoundBracket
|
null
{
if
(
!
r
)
{
return
null
;
...
...
src/vs/editor/common/modes/supports/richEditBrackets.ts
浏览文件 @
26b7ed52
...
...
@@ -17,6 +17,7 @@ export class RichEditBracket {
_richEditBracketBrand
:
void
;
readonly
languageIdentifier
:
LanguageIdentifier
;
readonly
index
:
number
;
readonly
open
:
string
[];
readonly
close
:
string
[];
readonly
forwardRegex
:
RegExp
;
...
...
@@ -24,8 +25,9 @@ export class RichEditBracket {
private
readonly
_openSet
:
Set
<
string
>
;
private
readonly
_closeSet
:
Set
<
string
>
;
constructor
(
languageIdentifier
:
LanguageIdentifier
,
open
:
string
[],
close
:
string
[],
forwardRegex
:
RegExp
,
reversedRegex
:
RegExp
)
{
constructor
(
languageIdentifier
:
LanguageIdentifier
,
index
:
number
,
open
:
string
[],
close
:
string
[],
forwardRegex
:
RegExp
,
reversedRegex
:
RegExp
)
{
this
.
languageIdentifier
=
languageIdentifier
;
this
.
index
=
index
;
this
.
open
=
open
;
this
.
close
=
close
;
this
.
forwardRegex
=
forwardRegex
;
...
...
@@ -125,6 +127,7 @@ export class RichEditBrackets {
this
.
brackets
=
brackets
.
map
((
b
,
index
)
=>
{
return
new
RichEditBracket
(
languageIdentifier
,
index
,
b
.
open
,
b
.
close
,
getRegexForBracketPair
(
b
.
open
,
b
.
close
,
brackets
,
index
),
...
...
src/vs/editor/contrib/bracketMatching/bracketMatching.ts
浏览文件 @
26b7ed52
...
...
@@ -159,10 +159,16 @@ export class BracketMatchingController extends Disposable implements editorCommo
newCursorPosition
=
brackets
[
0
].
getStartPosition
();
}
}
else
{
// find the next bracket if the position isn't on a matching bracket
const
nextBracket
=
model
.
findNextBracket
(
position
);
if
(
nextBracket
&&
nextBracket
.
range
)
{
newCursorPosition
=
nextBracket
.
range
.
getStartPosition
();
// find the enclosing brackets if the position isn't on a matching bracket
const
enclosingBrackets
=
model
.
findEnclosingBrackets
(
position
);
if
(
enclosingBrackets
)
{
newCursorPosition
=
enclosingBrackets
[
0
].
getStartPosition
();
}
else
{
// no enclosing brackets, try the very first next bracket
const
nextBracket
=
model
.
findNextBracket
(
position
);
if
(
nextBracket
&&
nextBracket
.
range
)
{
newCursorPosition
=
nextBracket
.
range
.
getStartPosition
();
}
}
}
...
...
@@ -192,9 +198,12 @@ export class BracketMatchingController extends Disposable implements editorCommo
let
closeBracket
:
Position
|
null
=
null
;
if
(
!
brackets
)
{
const
nextBracket
=
model
.
findNextBracket
(
position
);
if
(
nextBracket
&&
nextBracket
.
range
)
{
brackets
=
model
.
matchBracket
(
nextBracket
.
range
.
getStartPosition
());
brackets
=
model
.
findEnclosingBrackets
(
position
);
if
(
!
brackets
)
{
const
nextBracket
=
model
.
findNextBracket
(
position
);
if
(
nextBracket
&&
nextBracket
.
range
)
{
brackets
=
model
.
matchBracket
(
nextBracket
.
range
.
getStartPosition
());
}
}
}
...
...
src/vs/editor/contrib/bracketMatching/test/bracketMatching.test.ts
浏览文件 @
26b7ed52
...
...
@@ -143,6 +143,31 @@ suite('bracket matching', () => {
mode
.
dispose
();
});
test
(
'
issue #1772: jump to enclosing brackets
'
,
()
=>
{
const
text
=
[
'
const x = {
'
,
'
something: [0, 1, 2],
'
,
'
another: true,
'
,
'
somethingmore: [0, 2, 4]
'
,
'
};
'
,
].
join
(
'
\n
'
);
const
mode
=
new
BracketMode
();
const
model
=
TextModel
.
createFromString
(
text
,
undefined
,
mode
.
getLanguageIdentifier
());
withTestCodeEditor
(
null
,
{
model
:
model
},
(
editor
,
cursor
)
=>
{
const
bracketMatchingController
=
editor
.
registerAndInstantiateContribution
<
BracketMatchingController
>
(
BracketMatchingController
.
ID
,
BracketMatchingController
);
editor
.
setPosition
(
new
Position
(
3
,
5
));
bracketMatchingController
.
jumpToBracket
();
assert
.
deepEqual
(
editor
.
getSelection
(),
new
Selection
(
5
,
1
,
5
,
1
));
bracketMatchingController
.
dispose
();
});
model
.
dispose
();
mode
.
dispose
();
});
test
(
'
issue #45369: Select to Bracket with multicursor
'
,
()
=>
{
let
mode
=
new
BracketMode
();
let
model
=
TextModel
.
createFromString
(
'
{ } { } { }
'
,
undefined
,
mode
.
getLanguageIdentifier
());
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录