mirror of
https://github.com/IHaskell/IHaskell.git
synced 2025-04-16 03:16:20 +00:00
Adding filepath completion in strings, closes #122
This commit is contained in:
parent
75cff70fe5
commit
943eb9fd27
@ -36,7 +36,43 @@
|
||||
"cell_type": "code",
|
||||
"collapsed": false,
|
||||
"input": [
|
||||
":doc map"
|
||||
"getStringTarget :: String -> String\n",
|
||||
"getStringTarget = go \"\" . reverse\n",
|
||||
" where\n",
|
||||
" go acc rest = case rest of\n",
|
||||
" '\"':'\\\\':rem -> go ('\"':acc) rem\n",
|
||||
" '\"':rem -> acc\n",
|
||||
" ' ':'\\\\':rem -> go (' ':acc) rem\n",
|
||||
" ' ':rem -> acc\n",
|
||||
" x:rem -> go (x:acc) rem\n",
|
||||
" [] -> acc\n",
|
||||
"\n",
|
||||
"\" ~/archive/\n",
|
||||
":load \" ~/archive/"
|
||||
],
|
||||
"language": "python",
|
||||
"metadata": {
|
||||
"hidden": false
|
||||
},
|
||||
"outputs": [
|
||||
{
|
||||
"html": [
|
||||
"<span class='err-msg'>Parse error (line 12, column 13): lexical error in string/character literal at end of input</span>"
|
||||
],
|
||||
"metadata": {},
|
||||
"output_type": "display_data",
|
||||
"text": [
|
||||
"Parse error (line 12, column 13): lexical error in string/character literal at end of input"
|
||||
]
|
||||
}
|
||||
],
|
||||
"prompt_number": 1
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"collapsed": false,
|
||||
"input": [
|
||||
"getStringTarget \"absdf\\\" he\\\\\\\"llo\""
|
||||
],
|
||||
"language": "python",
|
||||
"metadata": {
|
||||
@ -45,59 +81,13 @@
|
||||
"outputs": [
|
||||
{
|
||||
"metadata": {},
|
||||
"output_type": "display_data"
|
||||
},
|
||||
{
|
||||
"html": [
|
||||
"<span class='hoogle-name'><a target='_blank' href='http://hackage.haskell.org/packages/archive/base/latest/doc/html/Prelude.html#v:map'>map</a> ∷ (a → b) → [a] → [b]</span><span class='hoogle-sub'>(<span class='hoogle-head'>package</span> <span class='hoogle-package'>base</span>, <span class='hoogle-head'>module</span> <span class='hoogle-module'>Prelude</span>)</span><div class='hoogle-doc'><div class='hoogle-text'>map f xs is the list obtained by applying f to each element of xs, i.e.,\n",
|
||||
"</div>\n",
|
||||
"<div class='hoogle-text'></div>\n",
|
||||
"<div class='hoogle-code'>> map f [x1, x2, ..., xn] == [f x1, f x2, ..., f xn]\n",
|
||||
"> map f [x1, x2, ...] == [f x1, f x2, ...] \n",
|
||||
"</div>\n",
|
||||
"</div>\n",
|
||||
"<span class='hoogle-name'><a target='_blank' href='http://hackage.haskell.org/packages/archive/bytestring/latest/doc/html/Data-ByteString-Char8.html#v:map'>map</a> ∷ (Char → Char) → ByteString → ByteString</span><span class='hoogle-sub'>(<span class='hoogle-head'>package</span> <span class='hoogle-package'>bytestring</span>, <span class='hoogle-head'>module</span> <span class='hoogle-module'>Data.ByteString.Char8</span>)</span><div class='hoogle-doc'><div class='hoogle-text'>O(n) map f xs is the ByteString obtained by applying f to each element of xs \n",
|
||||
"</div>\n",
|
||||
"</div>\n",
|
||||
"<span class='hoogle-name'><a target='_blank' href='http://hackage.haskell.org/packages/archive/text/latest/doc/html/Data-Text.html#v:map'>map</a> ∷ (Char → Char) → Text → Text</span><span class='hoogle-sub'>(<span class='hoogle-head'>package</span> <span class='hoogle-package'>text</span>, <span class='hoogle-head'>module</span> <span class='hoogle-module'>Data.Text</span>)</span><div class='hoogle-doc'><div class='hoogle-text'>O(n) map f t is the Text obtained by applying f to each element of t. Subject to fusion. Performs replacement on invalid scalar values. \n",
|
||||
"</div>\n",
|
||||
"</div>\n",
|
||||
"<span class='hoogle-name'><a target='_blank' href='http://hackage.haskell.org/packages/archive/containers/latest/doc/html/Data-IntSet.html#v:map'>map</a> ∷ (Key → Key) → IntSet → IntSet</span><span class='hoogle-sub'>(<span class='hoogle-head'>package</span> <span class='hoogle-package'>containers</span>, <span class='hoogle-head'>module</span> <span class='hoogle-module'>Data.IntSet</span>)</span><div class='hoogle-doc'><div class='hoogle-text'>O(n*min(n,W)). map f s is the set obtained by applying f to each element of s.\n",
|
||||
"</div>\n",
|
||||
"<div class='hoogle-text'></div>\n",
|
||||
"<div class='hoogle-text'>It's worth noting that the size of the result may be smaller if, for some (x,y), x /= y && f x == f y \n",
|
||||
"</div>\n",
|
||||
"</div>\n",
|
||||
"<span class='hoogle-name'><a target='_blank' href='http://hackage.haskell.org/packages/archive/bytestring/latest/doc/html/Data-ByteString-Lazy.html#v:map'>map</a> ∷ (Word8 → Word8) → ByteString → ByteString</span><span class='hoogle-sub'>(<span class='hoogle-head'>package</span> <span class='hoogle-package'>bytestring</span>, <span class='hoogle-head'>module</span> <span class='hoogle-module'>Data.ByteString.Lazy</span>)</span><div class='hoogle-doc'><div class='hoogle-text'>O(n) map f xs is the ByteString obtained by applying f to each element of xs. \n",
|
||||
"</div>\n",
|
||||
"</div>\n",
|
||||
"<span class='hoogle-name'><a target='_blank' href='http://hackage.haskell.org/packages/archive/bytestring/latest/doc/html/Data-ByteString.html#v:map'>map</a> ∷ (Word8 → Word8) → ByteString → ByteString</span><span class='hoogle-sub'>(<span class='hoogle-head'>package</span> <span class='hoogle-package'>bytestring</span>, <span class='hoogle-head'>module</span> <span class='hoogle-module'>Data.ByteString</span>)</span><div class='hoogle-doc'><div class='hoogle-text'>O(n) map f xs is the ByteString obtained by applying f to each element of xs. This function is subject to array fusion. \n",
|
||||
"</div>\n",
|
||||
"</div>\n",
|
||||
"<span class='hoogle-name'><a target='_blank' href='http://hackage.haskell.org/packages/archive/containers/latest/doc/html/Data-IntMap-Strict.html#v:map'>map</a> ∷ (a → b) → IntMap a → IntMap b</span><span class='hoogle-sub'>(<span class='hoogle-head'>package</span> <span class='hoogle-package'>containers</span>, <span class='hoogle-head'>module</span> <span class='hoogle-module'>Data.IntMap.Strict</span>)</span><div class='hoogle-doc'><div class='hoogle-text'>O(n). Map a function over all values in the map.\n",
|
||||
"</div>\n",
|
||||
"<div class='hoogle-text'></div>\n",
|
||||
"<div class='hoogle-code'>> map (++ \"x\") (fromList [(5,\"a\"), (3,\"b\")]) == fromList [(3, \"bx\"), (5, \"ax\")] \n",
|
||||
"</div>\n",
|
||||
"</div>\n",
|
||||
"<span class='hoogle-name'><a target='_blank' href='http://hackage.haskell.org/packages/archive/containers/latest/doc/html/Data-Map-Lazy.html#v:map'>map</a> ∷ (a → b) → Map k a → Map k b</span><span class='hoogle-sub'>(<span class='hoogle-head'>package</span> <span class='hoogle-package'>containers</span>, <span class='hoogle-head'>module</span> <span class='hoogle-module'>Data.Map.Lazy</span>)</span><div class='hoogle-doc'><div class='hoogle-text'>O(n). Map a function over all values in the map.\n",
|
||||
"</div>\n",
|
||||
"<div class='hoogle-text'></div>\n",
|
||||
"<div class='hoogle-code'>> map (++ \"x\") (fromList [(5,\"a\"), (3,\"b\")]) == fromList [(3, \"bx\"), (5, \"ax\")] \n",
|
||||
"</div>\n",
|
||||
"</div>\n",
|
||||
"<span class='hoogle-name'><a target='_blank' href='http://hackage.haskell.org/packages/archive/containers/latest/doc/html/Data-Set.html#v:map'>map</a> ∷ Ord b ⇒ (a → b) → Set a → Set b</span><span class='hoogle-sub'>(<span class='hoogle-head'>package</span> <span class='hoogle-package'>containers</span>, <span class='hoogle-head'>module</span> <span class='hoogle-module'>Data.Set</span>)</span><div class='hoogle-doc'><div class='hoogle-text'>O(n*log n). map f s is the set obtained by applying f to each element of s.\n",
|
||||
"</div>\n",
|
||||
"<div class='hoogle-text'></div>\n",
|
||||
"<div class='hoogle-text'>It's worth noting that the size of the result may be smaller if, for some (x,y), x /= y && f x == f y \n",
|
||||
"</div>\n",
|
||||
"</div>\n"
|
||||
],
|
||||
"metadata": {},
|
||||
"output_type": "display_data"
|
||||
"output_type": "display_data",
|
||||
"text": [
|
||||
"\"he\\\"llo\""
|
||||
]
|
||||
}
|
||||
],
|
||||
"prompt_number": 4
|
||||
"prompt_number": 13
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
|
@ -69,14 +69,15 @@ complete line pos = do
|
||||
moduleNames = nub $ concatMap getNames db
|
||||
|
||||
let target = completionTarget line pos
|
||||
completion = completionType line pos target
|
||||
|
||||
let matchedText = case completionType line pos target of
|
||||
let matchedText = case completion of
|
||||
HsFilePath _ match -> match
|
||||
FilePath _ match -> match
|
||||
otherwise -> intercalate "." target
|
||||
|
||||
options <-
|
||||
case completionType line pos target of
|
||||
case completion of
|
||||
Empty -> return []
|
||||
|
||||
Identifier candidate ->
|
||||
@ -175,10 +176,18 @@ completionType line loc target
|
||||
-- If it's empty, no completion.
|
||||
| null target
|
||||
= Empty
|
||||
|
||||
-- When in a string, complete filenames.
|
||||
| cursorInString line loc
|
||||
= FilePath (getStringTarget lineUpToCursor) (getStringTarget lineUpToCursor)
|
||||
|
||||
-- Complete module names in imports and elsewhere.
|
||||
| startswith "import" stripped && isModName
|
||||
= ModuleName dotted candidate
|
||||
| isModName && (not . null . init) target
|
||||
= Qualified dotted candidate
|
||||
|
||||
-- Default to completing identifiers.
|
||||
| otherwise
|
||||
= Identifier candidate
|
||||
where stripped = strip line
|
||||
@ -196,6 +205,26 @@ completionType line loc target
|
||||
else []
|
||||
Left _ -> Empty
|
||||
|
||||
cursorInString str loc = nquotes (take loc str) `mod` 2 /= 0
|
||||
|
||||
nquotes ('\\':'"':xs) = nquotes xs
|
||||
nquotes ('"':xs) = 1 + nquotes xs
|
||||
nquotes (_:xs) = nquotes xs
|
||||
nquotes [] = 0
|
||||
|
||||
-- Get the bit of a string that might be a filename completion.
|
||||
-- Logic is a bit convoluted, but basically go backwards from the
|
||||
-- end, stopping at any quote or space, unless they are escaped.
|
||||
getStringTarget :: String -> String
|
||||
getStringTarget = go "" . reverse
|
||||
where
|
||||
go acc rest = case rest of
|
||||
'"':'\\':rem -> go ('"':acc) rem
|
||||
'"':rem -> acc
|
||||
' ':'\\':rem -> go (' ':acc) rem
|
||||
' ':rem -> acc
|
||||
x:rem -> go (x:acc) rem
|
||||
[] -> acc
|
||||
|
||||
-- | Get the word under a given cursor location.
|
||||
completionTarget :: String -> Int -> [String]
|
||||
|
Loading…
x
Reference in New Issue
Block a user