Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Fixed column calc

  • Loading branch information...
commit 7fb3078a2fc71c2c769d4503eb2cabd61bfa295a 1 parent 4f21484
@mvoidex mvoidex authored
View
10 CabalInspector.hs
@@ -12,12 +12,14 @@ import Distribution.PackageDescription.Parse
import qualified System.Environment as Environment
data CabalInfo = CabalInfo {
- cabalExecutables :: [CabalExecutable] }
+ cabalExecutables :: [CabalExecutable],
+ cabalSourceDirs :: [FilePath] }
deriving (Show)
instance Json.ToJSON CabalInfo where
toJSON info = Json.object [
- "executables" .= cabalExecutables info]
+ "executables" .= cabalExecutables info,
+ "source-dirs" .= cabalSourceDirs info]
data CabalExecutable = CabalExecutable {
executableName :: String,
@@ -31,7 +33,9 @@ instance Json.ToJSON CabalExecutable where
analyzeCabal :: String -> Either String CabalInfo
analyzeCabal source = case parsePackageDescription source of
- ParseOk _ r -> Right $ CabalInfo $ map (uncurry CabalExecutable . second (exeName . condTreeData)) $ condExecutables r
+ ParseOk _ r -> Right CabalInfo {
+ cabalExecutables = map (uncurry CabalExecutable . second (exeName . condTreeData)) $ condExecutables r,
+ cabalSourceDirs = maybe [] (hsSourceDirs . libBuildInfo . condTreeData) $ condLibrary r }
ParseFailed e -> Left $ "Parse failed: " ++ show e
main :: IO ()
View
2  autocomplete.py
@@ -992,7 +992,7 @@ def _refresh_module_info(self, filename, standalone = True):
ghc_opts_args = [' '.join(ghc_opts)] if ghc_opts else []
exit_code, stdout, stderr = call_and_wait(
- [MODULE_INSPECTOR_EXE_PATH, filename] + ghc_opts_args, cwd = get_cwd(filename))
+ [MODULE_INSPECTOR_EXE_PATH, filename] + ghc_opts_args, cwd = get_source_dir(filename))
module_inspector_out = MODULE_INSPECTOR_RE.search(stdout)
View
36 haskell_type.py
@@ -12,6 +12,7 @@
from SublimeHaskell.autocomplete import autocompletion
from SublimeHaskell.hdevtools import hdevtools_type
from SublimeHaskell.ghcmod import ghcmod_type
+ from functools import reduce
# Used to find out the module name.
MODULE_RE_STR = r'module\s+([^\s\(]*)' # "module" followed by everything that is neither " " nor "("
@@ -24,7 +25,6 @@
# Name of the sublime panel in which type information is shown.
TYPE_PANEL_NAME = 'haskell_type_panel'
-
def parse_ghc_mod_type_line(l):
"""
Returns the `groupdict()` of GHCMOD_TYPE_LINE_RE matching the given line,
@@ -33,17 +33,44 @@ def parse_ghc_mod_type_line(l):
match = GHCMOD_TYPE_LINE_RE.match(l)
return match and match.groupdict()
+def tabs_offset(view, point):
+ """
+ Returns count of '\t' before point in line multiplied by 7
+ 8 is size of type as supposed by ghc-mod, to every '\t' will add 7 to column
+ Subtract this value to get sublime column by ghc-mod column, add to get ghc-mod column by sublime column
+ """
+ cur_line = view.substr(view.line(point))
+ return len(filter(lambda ch: ch == '\t', cur_line)) * 7
+
+def sublime_column_to_type_column(view, line, column):
+ cur_line = view.substr(view.line(view.text_point(line, column)))
+ return column + len(filter(lambda ch: ch == '\t', cur_line)) * 7 + 1
+
+def type_column_to_sublime_column(view, line, column):
+ cur_line = view.substr(view.line(view.text_point(line - 1, 0)))
+ col = 1
+ real_col = 0
+ for c in cur_line:
+ col += (8 if c == '\t' else 1)
+ real_col += 1
+ if col >= column:
+ return real_col
+ return real_col
+
class FilePosition(object):
def __init__(self, line, column):
self.line = line
self.column = column
def point(self, view):
- return view.text_point(self.line - 1, self.column - 1)
+ # Note, that sublime suppose that '\t' is 'tab_size' length
+ # But '\t' is one character
+ return view.text_point(self.line - 1, type_column_to_sublime_column(view, self.line, self.column))
def position_by_point(view, point):
+ tabs = tabs_offset(view, point)
(r, c) = view.rowcol(point)
- return FilePosition(r + 1, c + 1)
+ return FilePosition(r + 1, c + 1 + tabs)
class RegionType(object):
def __init__(self, typename, start, end = None):
@@ -88,6 +115,7 @@ def parse_type_output(s):
def haskell_type(filename, module_name, line, column, cabal = None):
result = None
+
if get_setting_async('enable_hdevtools'):
result = hdevtools_type(filename, line, column, cabal = cabal)
if not result:
@@ -108,6 +136,8 @@ def get_types(self, filename = None, line = None, column = None):
line = r + 1
column = c + 1
+ column = sublime_column_to_type_column(self.view, r, c)
+
module_name = None
with autocompletion.database.files as files:
if filename in files:
View
10 hdevtools.py
@@ -27,7 +27,13 @@ def call_hdevtools_and_wait(arg_list, filename = None, cabal = None):
if package_db:
ghs_opts.append('-package_db {0}'.format(package_db))
- ghc_opts_args = ["-g", ' '.join(ghc_opts)] if ghc_opts else []
+ source_dir = get_source_dir(filename)
+ ghc_opts.append('-i {0}'.format(source_dir))
+
+ ghc_opts_args = []
+ if ghc_opts:
+ for opt in ghc_opts:
+ ghc_opts_args.extend(["-g", opt])
if hdevtools_socket:
arg_list.append('--socket={0}'.format(hdevtools_socket))
@@ -35,7 +41,7 @@ def call_hdevtools_and_wait(arg_list, filename = None, cabal = None):
try:
command = ['hdevtools'] + arg_list + ghc_opts_args
- exit_code, out, err = call_and_wait(['hdevtools'] + arg_list + ghc_opts_args)
+ exit_code, out, err = call_and_wait(['hdevtools'] + arg_list + ghc_opts_args, cwd = source_dir)
if exit_code != 0:
raise Exception("hdevtools exited with status %d and stderr: %s" % (exit_code, err))
View
43 sublime_haskell_common.py
@@ -1,6 +1,7 @@
import errno
import fnmatch
import os
+import json
import sublime
import sublime_plugin
import subprocess
@@ -17,6 +18,8 @@
# Panel for SublimeHaskell errors
SUBLIME_ERROR_PANEL_NAME = 'haskell_sublime_load'
+# Used to detect hs-source-dirs for project
+CABAL_INSPECTOR_EXE_PATH = None
# Setting can't be get from not main threads
# So we using a trick:
@@ -317,6 +320,37 @@ def set_setting(key, value):
def set_setting_async(key, value):
sublime.set_timeout(lambda: set_setting(key, value), 0)
+def get_source_dir(filename):
+ """
+ Get root of hs-source-dirs for filename in project
+ """
+ if not filename:
+ return os.getcwd()
+
+ (cabal_dir, project_name) = get_cabal_project_dir_and_name_of_file(filename)
+ if not cabal_dir:
+ return os.path.dirname(filename)
+
+ cabal_file = get_cabal_in_dir(cabal_dir)
+ exit_code, out, err = call_and_wait([CABAL_INSPECTOR_EXE_PATH, cabal_file])
+
+ if exit_code == 0:
+ info = json.loads(out)
+
+ dirs = ["."]
+
+ if 'error' not in info:
+ dirs.extend(info['source-dirs'])
+
+ paths = [os.path.normpath(os.path.join(cabal_dir, d)) for d in dirs]
+ paths.sort(key = lambda p: -len(p))
+
+ for p in paths:
+ if filename.startswith(p):
+ return p
+
+ return os.path.dirname(filename)
+
def get_cwd(filename = None):
"""
Get cwd for filename: cabal project path, file path or os.getcwd()
@@ -331,14 +365,17 @@ def call_ghcmod_and_wait(arg_list, filename=None, cabal = None):
"""
ghc_opts = get_setting_async('ghc_opts')
- ghc_opts_args = ["-g", ' '.join(ghc_opts)] if ghc_opts else []
+ ghc_opts_args = []
+ if ghc_opts:
+ for opt in ghc_opts:
+ ghc_opts_args.extend(["-g", opt])
try:
command = attach_cabal_sandbox(['ghc-mod'] + arg_list + ghc_opts_args, cabal)
# log('running ghc-mod: {0}'.format(command))
- exit_code, out, err = call_and_wait(command, cwd=get_cwd(filename))
+ exit_code, out, err = call_and_wait(command, cwd=get_source_dir(filename))
if exit_code != 0:
raise Exception("ghc-mod exited with status %d and stderr: %s" % (exit_code, err))
@@ -563,7 +600,9 @@ def sublime_haskell_package_path():
def plugin_loaded():
global PACKAGE_PATH
+ global CABAL_INSPECTOR_EXE_PATH
PACKAGE_PATH = sublime_haskell_package_path()
+ CABAL_INSPECTOR_EXE_PATH = os.path.join(PACKAGE_PATH, 'CabalInspector')
preload_settings()
if int(sublime.version()) < 3000:
Please sign in to comment.
Something went wrong with that request. Please try again.