forked from SublimeHaskell/SublimeHaskell
-
Notifications
You must be signed in to change notification settings - Fork 1
/
ghci.py
66 lines (57 loc) · 2.3 KB
/
ghci.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
import re
import os
import sublime
import sublime_plugin
if int(sublime.version()) < 3000:
from sublime_haskell_common import *
import symbols
else:
from SublimeHaskell.sublime_haskell_common import *
import SublimeHaskell.symbols as symbols
def parse_info(name, contents):
"""
Parses result of :i <name> command of ghci and returns derived symbols.Declaration
"""
functionRegex = '{0}\s+::\s+(?P<type>.*?)(\s+--(.*))?$'.format(name)
dataRegex = '(?P<what>(newtype|type|data))\s+((?P<ctx>(.*))=>\s+)?(?P<name>\S+)\s+(?P<args>(\w+\s+)*)=(\s*(?P<def>.*)\s+-- Defined)?'
classRegex = '(?P<what>class)\s+((?P<ctx>(.*))=>\s+)?(?P<name>\S+)\s+(?P<args>(\w+\s+)*)(.*)where$'
if name[0].isupper():
# data, class, type or newtype
matched = re.search(dataRegex, contents, re.MULTILINE) or re.search(classRegex, contents, re.MULTILINE)
if matched:
what = matched.group('what')
args = matched.group('args').strip().split(' ') if matched.group('args') else []
ctx = matched.group('ctx')
definition = matched.group('def')
if definition:
definition.strip()
if what == 'class':
return symbols.Class(name, ctx, args)
elif what == 'data':
return symbols.Data(name, ctx, args, definition)
elif what == 'type':
return symbols.Type(name, ctx, args, definition)
elif what == 'newtype':
return symbols.Newtype(name, ctx, args, definition)
else:
raise RuntimeError('Unknown type of symbol: {0}'.format(what))
else:
# function
matched = re.search(functionRegex, contents, re.MULTILINE)
if matched:
return symbols.Function(name, matched.group('type'))
return None
def ghci_info(module, name, cabal = None):
"""
Returns info for name as symbol
"""
ghci_cmd = [
":m + " + module,
":i " + module + "." + name,
":q"]
ghc_opts = get_setting_async('ghc_opts')
(exit_code, stdout, stderr) = call_and_wait_with_input(ghci_append_package_db(['ghci'] + ghc_opts, cabal = cabal), "\n".join(ghci_cmd))
stdout = crlf2lf(stdout)
if exit_code == 0:
return parse_info(name, stdout)
return None