Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
C
CodeMirror
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Package registry
Container Registry
Model registry
Operate
Environments
Terraform modules
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Issue analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Terms and privacy
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
Moritz Aurel Pascal Schubotz
CodeMirror
Commits
3c8b5a72
Commit
3c8b5a72
authored
7 years ago
by
Marijn Haverbeke
Browse files
Options
Downloads
Patches
Plain Diff
[searchcursor addon] Refactor
parent
09adaf41
No related branches found
Branches containing commit
No related tags found
Tags containing commit
No related merge requests found
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
addon/search/searchcursor.js
+154
-156
154 additions, 156 deletions
addon/search/searchcursor.js
test/search_test.js
+4
-4
4 additions, 4 deletions
test/search_test.js
with
158 additions
and
160 deletions
addon/search/searchcursor.js
+
154
−
156
View file @
3c8b5a72
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: http://codemirror.net/LICENSE
(
function
(
mod
)
{
;
(
function
(
mod
)
{
if
(
typeof
exports
==
"
object
"
&&
typeof
module
==
"
object
"
)
// CommonJS
mod
(
require
(
"
../../lib/codemirror
"
))
;
mod
(
require
(
"
../../lib/codemirror
"
))
else
if
(
typeof
define
==
"
function
"
&&
define
.
amd
)
// AMD
define
([
"
../../lib/codemirror
"
],
mod
)
;
define
([
"
../../lib/codemirror
"
],
mod
)
else
// Plain browser env
mod
(
CodeMirror
)
;
mod
(
CodeMirror
)
})(
function
(
CodeMirror
)
{
"
use strict
"
;
var
Pos
=
CodeMirror
.
Pos
;
"
use strict
"
var
Pos
=
CodeMirror
.
Pos
function
ensureGlobal
(
regexp
)
{
return
regexp
.
global
?
regexp
:
new
RegExp
(
regexp
.
source
,
regexp
.
ignoreCase
?
"
ig
"
:
"
g
"
)
}
function
searchRegexpForward
(
doc
,
regexp
,
start
)
{
regexp
=
ensureGlobal
(
regexp
)
for
(
var
line
=
start
.
line
,
ch
=
start
.
ch
,
last
=
doc
.
lastLine
();
line
<=
last
;
line
++
,
ch
=
0
)
{
regexp
.
lastIndex
=
ch
var
string
=
doc
.
getLine
(
line
),
match
=
regexp
.
exec
(
string
)
if
(
match
&&
match
[
0
].
length
)
return
{
from
:
Pos
(
line
,
match
.
index
),
to
:
Pos
(
line
,
match
.
index
+
match
[
0
].
length
),
match
:
match
}
}
}
function
searchRegexpBackward
(
doc
,
regexp
,
start
)
{
regexp
=
ensureGlobal
(
regexp
)
for
(
var
line
=
start
.
line
,
ch
=
start
.
ch
,
first
=
doc
.
firstLine
();
line
>=
first
;
line
--
,
ch
=
-
1
)
{
var
string
=
doc
.
getLine
(
line
),
cutOff
=
0
,
match
if
(
ch
>
-
1
)
string
=
string
.
slice
(
0
,
ch
)
for
(;;)
{
regexp
.
lastIndex
=
cutOff
var
newMatch
=
regexp
.
exec
(
string
)
if
(
!
newMatch
)
break
match
=
newMatch
cutOff
=
match
.
index
+
(
match
[
0
].
length
||
1
)
if
(
cutOff
==
line
.
length
)
break
}
if
(
match
&&
match
[
0
].
length
)
return
{
from
:
Pos
(
line
,
match
.
index
),
to
:
Pos
(
line
,
match
.
index
+
match
[
0
].
length
),
match
:
match
}
}
}
function
doFold
(
str
)
{
return
str
.
toLowerCase
()
}
function
noFold
(
str
)
{
return
str
}
// Maps a position in a case-folded line back to a position in the original line
// (compensating for codepoints increasing in number during folding)
function
adjustPos
(
orig
,
folded
,
pos
)
{
if
(
orig
.
length
==
folded
.
length
)
return
pos
for
(
var
pos1
=
Math
.
min
(
pos
,
orig
.
length
);;)
{
var
len1
=
orig
.
slice
(
0
,
pos1
).
toLowerCase
().
length
if
(
len1
<
pos
)
++
pos1
else
if
(
len1
>
pos
)
--
pos1
else
return
pos1
}
}
function
searchStringForward
(
doc
,
query
,
start
,
caseFold
)
{
// Empty string would match anything and never progress, so we
// define it to match nothing instead.
if
(
!
query
.
length
)
return
null
var
fold
=
caseFold
?
doFold
:
noFold
var
lines
=
fold
(
query
).
split
(
/
\r
|
\n\r?
/
)
search
:
for
(
var
line
=
start
.
line
,
ch
=
start
.
ch
,
last
=
doc
.
lastLine
()
+
1
-
lines
.
length
;
line
<=
last
;
line
++
,
ch
=
0
)
{
var
orig
=
doc
.
getLine
(
line
).
slice
(
ch
),
string
=
fold
(
orig
)
if
(
lines
.
length
==
1
)
{
var
found
=
string
.
indexOf
(
lines
[
0
])
if
(
found
==
-
1
)
continue
search
var
start
=
adjustPos
(
orig
,
string
,
found
)
+
ch
return
{
from
:
Pos
(
line
,
adjustPos
(
orig
,
string
,
found
)
+
ch
),
to
:
Pos
(
line
,
adjustPos
(
orig
,
string
,
found
+
lines
[
0
].
length
)
+
ch
)}
}
else
{
var
cutFrom
=
string
.
length
-
lines
[
0
].
length
if
(
string
.
slice
(
cutFrom
)
!=
lines
[
0
])
continue
search
for
(
var
i
=
1
;
i
<
lines
.
length
-
1
;
i
++
)
if
(
fold
(
doc
.
getLine
(
line
+
i
))
!=
lines
[
i
])
continue
search
var
end
=
doc
.
getLine
(
line
+
lines
.
length
-
1
),
endString
=
fold
(
end
),
lastLine
=
lines
[
lines
.
length
-
1
]
if
(
end
.
slice
(
0
,
lastLine
.
length
)
!=
lastLine
)
continue
search
return
{
from
:
Pos
(
line
,
adjustPos
(
orig
,
string
,
cutFrom
)
+
ch
),
to
:
Pos
(
line
+
lines
.
length
-
1
,
adjustPos
(
end
,
endString
,
lastLine
.
length
))}
}
}
}
function
searchStringBackward
(
doc
,
query
,
start
,
caseFold
)
{
if
(
!
query
.
length
)
return
null
var
fold
=
caseFold
?
doFold
:
noFold
var
lines
=
fold
(
query
).
split
(
/
\r
|
\n\r?
/
)
search
:
for
(
var
line
=
start
.
line
,
ch
=
start
.
ch
,
first
=
doc
.
firstLine
()
-
1
+
lines
.
length
;
line
>=
first
;
line
--
,
ch
=
-
1
)
{
var
orig
=
doc
.
getLine
(
line
)
if
(
ch
>
-
1
)
orig
=
orig
.
slice
(
0
,
ch
)
var
string
=
fold
(
orig
)
if
(
lines
.
length
==
1
)
{
var
found
=
string
.
lastIndexOf
(
lines
[
0
])
if
(
found
==
-
1
)
continue
search
return
{
from
:
Pos
(
line
,
adjustPos
(
orig
,
string
,
found
)),
to
:
Pos
(
line
,
adjustPos
(
orig
,
string
,
found
+
lines
[
0
].
length
))}
}
else
{
var
lastLine
=
lines
[
lines
.
length
-
1
]
if
(
string
.
slice
(
0
,
lastLine
.
length
)
!=
lastLine
)
continue
search
for
(
var
i
=
1
,
start
=
line
-
lines
.
length
+
1
;
i
<
lines
.
length
-
1
;
i
++
)
if
(
fold
(
doc
.
getLine
(
start
+
i
))
!=
lines
[
i
])
continue
search
var
top
=
doc
.
getLine
(
line
+
1
-
lines
.
length
),
topString
=
fold
(
top
)
if
(
topString
.
slice
(
topString
.
length
-
lines
[
0
].
length
)
!=
lines
[
0
])
continue
search
return
{
from
:
Pos
(
line
+
1
-
lines
.
length
,
adjustPos
(
top
,
topString
,
top
.
length
-
lines
[
0
].
length
)),
to
:
Pos
(
line
,
adjustPos
(
orig
,
string
,
lastLine
.
length
))}
}
}
}
function
SearchCursor
(
doc
,
query
,
pos
,
caseFold
)
{
this
.
atOccurrence
=
false
;
this
.
doc
=
doc
;
if
(
caseFold
==
null
&&
typeof
query
==
"
string
"
)
caseFold
=
false
;
pos
=
pos
?
doc
.
clipPos
(
pos
)
:
Pos
(
0
,
0
);
this
.
pos
=
{
from
:
pos
,
to
:
pos
};
// The matches method is filled in based on the type of query.
// It takes a position and a direction, and returns an object
// describing the next occurrence of the query, or null if no
// more matches were found.
if
(
typeof
query
!=
"
string
"
)
{
// Regexp match
if
(
!
query
.
global
)
query
=
new
RegExp
(
query
.
source
,
query
.
ignoreCase
?
"
ig
"
:
"
g
"
);
this
.
atOccurrence
=
false
this
.
doc
=
doc
pos
=
pos
?
doc
.
clipPos
(
pos
)
:
Pos
(
0
,
0
)
this
.
pos
=
{
from
:
pos
,
to
:
pos
}
if
(
typeof
query
==
"
string
"
)
{
if
(
caseFold
==
null
)
caseFold
=
false
this
.
matches
=
function
(
reverse
,
pos
)
{
if
(
reverse
)
{
query
.
lastIndex
=
0
;
var
line
=
doc
.
getLine
(
pos
.
line
).
slice
(
0
,
pos
.
ch
),
cutOff
=
0
,
match
,
start
;
for
(;;)
{
query
.
lastIndex
=
cutOff
;
var
newMatch
=
query
.
exec
(
line
);
if
(
!
newMatch
)
break
;
match
=
newMatch
;
start
=
match
.
index
;
cutOff
=
match
.
index
+
(
match
[
0
].
length
||
1
);
if
(
cutOff
==
line
.
length
)
break
;
}
var
matchLen
=
(
match
&&
match
[
0
].
length
)
||
0
;
if
(
!
matchLen
)
{
if
(
start
==
0
&&
line
.
length
==
0
)
{
match
=
undefined
;}
else
if
(
start
!=
doc
.
getLine
(
pos
.
line
).
length
)
{
matchLen
++
;
}
}
}
else
{
query
.
lastIndex
=
pos
.
ch
;
var
line
=
doc
.
getLine
(
pos
.
line
),
match
=
query
.
exec
(
line
);
var
matchLen
=
(
match
&&
match
[
0
].
length
)
||
0
;
var
start
=
match
&&
match
.
index
;
if
(
start
+
matchLen
!=
line
.
length
&&
!
matchLen
)
matchLen
=
1
;
}
if
(
match
&&
matchLen
)
return
{
from
:
Pos
(
pos
.
line
,
start
),
to
:
Pos
(
pos
.
line
,
start
+
matchLen
),
match
:
match
};
};
}
else
{
// String query
var
origQuery
=
query
;
if
(
caseFold
)
query
=
query
.
toLowerCase
();
var
fold
=
caseFold
?
function
(
str
){
return
str
.
toLowerCase
();}
:
function
(
str
){
return
str
;};
var
target
=
query
.
split
(
"
\n
"
);
// Different methods for single-line and multi-line queries
if
(
target
.
length
==
1
)
{
if
(
!
query
.
length
)
{
// Empty string would match anything and never progress, so
// we define it to match nothing instead.
this
.
matches
=
function
()
{};
}
else
{
this
.
matches
=
function
(
reverse
,
pos
)
{
if
(
reverse
)
{
var
orig
=
doc
.
getLine
(
pos
.
line
).
slice
(
0
,
pos
.
ch
),
line
=
fold
(
orig
);
var
match
=
line
.
lastIndexOf
(
query
);
if
(
match
>
-
1
)
{
match
=
adjustPos
(
orig
,
line
,
match
);
return
{
from
:
Pos
(
pos
.
line
,
match
),
to
:
Pos
(
pos
.
line
,
match
+
origQuery
.
length
)};
}
}
else
{
var
orig
=
doc
.
getLine
(
pos
.
line
).
slice
(
pos
.
ch
),
line
=
fold
(
orig
);
var
match
=
line
.
indexOf
(
query
);
if
(
match
>
-
1
)
{
match
=
adjustPos
(
orig
,
line
,
match
)
+
pos
.
ch
;
return
{
from
:
Pos
(
pos
.
line
,
match
),
to
:
Pos
(
pos
.
line
,
match
+
origQuery
.
length
)};
}
}
};
}
}
else
{
var
origTarget
=
origQuery
.
split
(
"
\n
"
);
this
.
matches
=
function
(
reverse
,
pos
)
{
var
last
=
target
.
length
-
1
;
if
(
reverse
)
{
if
(
pos
.
line
-
(
target
.
length
-
1
)
<
doc
.
firstLine
())
return
;
if
(
fold
(
doc
.
getLine
(
pos
.
line
).
slice
(
0
,
origTarget
[
last
].
length
))
!=
target
[
target
.
length
-
1
])
return
;
var
to
=
Pos
(
pos
.
line
,
origTarget
[
last
].
length
);
for
(
var
ln
=
pos
.
line
-
1
,
i
=
last
-
1
;
i
>=
1
;
--
i
,
--
ln
)
if
(
target
[
i
]
!=
fold
(
doc
.
getLine
(
ln
)))
return
;
var
line
=
doc
.
getLine
(
ln
),
cut
=
line
.
length
-
origTarget
[
0
].
length
;
if
(
fold
(
line
.
slice
(
cut
))
!=
target
[
0
])
return
;
return
{
from
:
Pos
(
ln
,
cut
),
to
:
to
};
}
else
{
if
(
pos
.
line
+
(
target
.
length
-
1
)
>
doc
.
lastLine
())
return
;
var
line
=
doc
.
getLine
(
pos
.
line
),
cut
=
line
.
length
-
origTarget
[
0
].
length
;
if
(
fold
(
line
.
slice
(
cut
))
!=
target
[
0
])
return
;
var
from
=
Pos
(
pos
.
line
,
cut
);
for
(
var
ln
=
pos
.
line
+
1
,
i
=
1
;
i
<
last
;
++
i
,
++
ln
)
if
(
target
[
i
]
!=
fold
(
doc
.
getLine
(
ln
)))
return
;
if
(
fold
(
doc
.
getLine
(
ln
).
slice
(
0
,
origTarget
[
last
].
length
))
!=
target
[
last
])
return
;
return
{
from
:
from
,
to
:
Pos
(
ln
,
origTarget
[
last
].
length
)};
}
};
return
(
reverse
?
searchStringBackward
:
searchStringForward
)(
doc
,
query
,
pos
,
caseFold
)
}
}
else
{
query
=
ensureGlobal
(
query
)
this
.
matches
=
function
(
reverse
,
pos
)
{
return
(
reverse
?
searchRegexpBackward
:
searchRegexpForward
)(
doc
,
query
,
pos
)
}
}
}
SearchCursor
.
prototype
=
{
findNext
:
function
()
{
return
this
.
find
(
false
)
;
},
findPrevious
:
function
()
{
return
this
.
find
(
true
)
;
},
findNext
:
function
()
{
return
this
.
find
(
false
)},
findPrevious
:
function
()
{
return
this
.
find
(
true
)},
find
:
function
(
reverse
)
{
var
self
=
this
,
pos
=
this
.
doc
.
clipPos
(
reverse
?
this
.
pos
.
from
:
this
.
pos
.
to
);
function
savePosAndFail
(
line
)
{
var
pos
=
Pos
(
line
,
0
);
self
.
pos
=
{
from
:
pos
,
to
:
pos
};
self
.
atOccurrence
=
false
;
return
false
;
}
for
(;;)
{
if
(
this
.
pos
=
this
.
matches
(
reverse
,
pos
))
{
this
.
atOccurrence
=
true
;
return
this
.
pos
.
match
||
true
;
}
if
(
reverse
)
{
if
(
!
pos
.
line
)
return
savePosAndFail
(
0
);
pos
=
Pos
(
pos
.
line
-
1
,
this
.
doc
.
getLine
(
pos
.
line
-
1
).
length
);
}
else
{
var
maxLine
=
this
.
doc
.
lineCount
();
if
(
pos
.
line
==
maxLine
-
1
)
return
savePosAndFail
(
maxLine
);
pos
=
Pos
(
pos
.
line
+
1
,
0
);
}
var
result
=
this
.
matches
(
reverse
,
this
.
doc
.
clipPos
(
reverse
?
this
.
pos
.
from
:
this
.
pos
.
to
))
if
(
result
)
{
this
.
pos
=
result
this
.
atOccurrence
=
true
return
this
.
pos
.
match
||
true
}
else
{
var
end
=
Pos
(
reverse
?
this
.
doc
.
firstLine
()
:
this
.
doc
.
lastLine
()
+
1
,
0
)
this
.
pos
=
{
from
:
end
,
to
:
end
}
return
this
.
atOccurrence
=
false
}
},
from
:
function
()
{
if
(
this
.
atOccurrence
)
return
this
.
pos
.
from
;
},
to
:
function
()
{
if
(
this
.
atOccurrence
)
return
this
.
pos
.
to
;
},
from
:
function
()
{
if
(
this
.
atOccurrence
)
return
this
.
pos
.
from
},
to
:
function
()
{
if
(
this
.
atOccurrence
)
return
this
.
pos
.
to
},
replace
:
function
(
newText
,
origin
)
{
if
(
!
this
.
atOccurrence
)
return
;
var
lines
=
CodeMirror
.
splitLines
(
newText
)
;
this
.
doc
.
replaceRange
(
lines
,
this
.
pos
.
from
,
this
.
pos
.
to
,
origin
)
;
if
(
!
this
.
atOccurrence
)
return
var
lines
=
CodeMirror
.
splitLines
(
newText
)
this
.
doc
.
replaceRange
(
lines
,
this
.
pos
.
from
,
this
.
pos
.
to
,
origin
)
this
.
pos
.
to
=
Pos
(
this
.
pos
.
from
.
line
+
lines
.
length
-
1
,
lines
[
lines
.
length
-
1
].
length
+
(
lines
.
length
==
1
?
this
.
pos
.
from
.
ch
:
0
));
}
};
// Maps a position in a case-folded line back to a position in the original line
// (compensating for codepoints increasing in number during folding)
function
adjustPos
(
orig
,
folded
,
pos
)
{
if
(
orig
.
length
==
folded
.
length
)
return
pos
;
for
(
var
pos1
=
Math
.
min
(
pos
,
orig
.
length
);;)
{
var
len1
=
orig
.
slice
(
0
,
pos1
).
toLowerCase
().
length
;
if
(
len1
<
pos
)
++
pos1
;
else
if
(
len1
>
pos
)
--
pos1
;
else
return
pos1
;
lines
[
lines
.
length
-
1
].
length
+
(
lines
.
length
==
1
?
this
.
pos
.
from
.
ch
:
0
))
}
}
CodeMirror
.
defineExtension
(
"
getSearchCursor
"
,
function
(
query
,
pos
,
caseFold
)
{
return
new
SearchCursor
(
this
.
doc
,
query
,
pos
,
caseFold
)
;
})
;
return
new
SearchCursor
(
this
.
doc
,
query
,
pos
,
caseFold
)
})
CodeMirror
.
defineDocExtension
(
"
getSearchCursor
"
,
function
(
query
,
pos
,
caseFold
)
{
return
new
SearchCursor
(
this
,
query
,
pos
,
caseFold
)
;
})
;
return
new
SearchCursor
(
this
,
query
,
pos
,
caseFold
)
})
CodeMirror
.
defineExtension
(
"
selectMatches
"
,
function
(
query
,
caseFold
)
{
var
ranges
=
[]
;
var
cur
=
this
.
getSearchCursor
(
query
,
this
.
getCursor
(
"
from
"
),
caseFold
)
;
var
ranges
=
[]
var
cur
=
this
.
getSearchCursor
(
query
,
this
.
getCursor
(
"
from
"
),
caseFold
)
while
(
cur
.
findNext
())
{
if
(
CodeMirror
.
cmpPos
(
cur
.
to
(),
this
.
getCursor
(
"
to
"
))
>
0
)
break
;
ranges
.
push
({
anchor
:
cur
.
from
(),
head
:
cur
.
to
()})
;
if
(
CodeMirror
.
cmpPos
(
cur
.
to
(),
this
.
getCursor
(
"
to
"
))
>
0
)
break
ranges
.
push
({
anchor
:
cur
.
from
(),
head
:
cur
.
to
()})
}
if
(
ranges
.
length
)
this
.
setSelections
(
ranges
,
0
)
;
})
;
})
;
this
.
setSelections
(
ranges
,
0
)
})
})
This diff is collapsed.
Click to expand it.
test/search_test.js
+
4
−
4
View file @
3c8b5a72
...
...
@@ -31,10 +31,10 @@
run
(
doc
,
"
cde
"
,
false
,
0
,
2
,
0
,
5
,
1
,
2
,
1
,
5
);
});
test
(
"
multiline
"
,
"
hallo
"
,
"
goodbye
"
,
function
(
doc
)
{
run
(
doc
,
"
llo
\n
goo
"
,
false
,
0
,
2
,
1
,
3
);
run
(
doc
,
"
blah
\n
hall
"
,
false
);
run
(
doc
,
"
bye
\n
eye
"
,
false
);
test
(
"
multiline
"
,
"
hallo
"
,
"
a
"
,
"
b
"
,
"
goodbye
"
,
function
(
doc
)
{
run
(
doc
,
"
llo
\
n
a
\n
b
\
n
goo
"
,
false
,
0
,
2
,
3
,
3
);
run
(
doc
,
"
blah
\
n
a
\n
b
\
n
hall
"
,
false
);
run
(
doc
,
"
bye
\
n
x
\
n
eye
"
,
false
);
});
test
(
"
regexp
"
,
"
abcde
"
,
"
abcde
"
,
function
(
doc
)
{
...
...
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment