forked from dbp/sublime-rust
/
util.py
147 lines (121 loc) · 4.35 KB
/
util.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
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
"""General utilities used by the Rust package."""
import sublime
import textwrap
import threading
import time
import os
def index_with(l, cb):
"""Find the index of a value in a sequence using a callback.
:param l: The sequence to search.
:param cb: Function to call, should return true if the given value matches
what you are searching for.
:returns: Returns the index of the match, or -1 if no match.
"""
for i, v in enumerate(l):
if cb(v):
return i
return -1
def multiline_fix(s):
"""Remove indentation from a multi-line string."""
return textwrap.dedent(s).lstrip()
def get_setting(name, default=None):
"""Retrieve a setting from Sublime settings."""
pdata = sublime.active_window().project_data()
if pdata:
v = pdata.get('settings', {}).get(name)
if v is not None:
return v
settings = sublime.load_settings('RustEnhanced.sublime-settings')
v = settings.get(name)
if v is not None:
return v
settings = sublime.load_settings('Preferences.sublime-settings')
# XXX: Also check "Distraction Free"?
return settings.get(name, default)
_last_debug = time.time()
def debug(msg, *args):
"""Display a general debug message."""
global _last_debug
t = time.time()
d = t - _last_debug
_last_debug = t
n = threading.current_thread().name
print('%s +%.3f ' % (n, d), end='')
print(msg % args)
def get_rustc_version(window, cwd, toolchain=None):
"""Returns the rust version for the given directory.
:Returns: A string such as '1.16.0' or '1.17.0-nightly'.
"""
from . import rust_proc
cmd = ['rustc']
if toolchain:
cmd.append('+' + toolchain)
cmd.append('--version')
output = rust_proc.check_output(window, cmd, cwd)
# Example outputs:
# rustc 1.15.1 (021bd294c 2017-02-08)
# rustc 1.16.0-beta.2 (bc15d5281 2017-02-16)
# rustc 1.17.0-nightly (306035c21 2017-02-18)
return output.split()[1]
def find_cargo_manifest(path):
"""Find the Cargo.toml file in the given path, or any of its parents.
:Returns: The path where Cargo.toml is found, or None.
"""
path = os.path.normpath(path)
if os.path.isfile(path):
path = os.path.dirname(path)
while True:
manifest = os.path.join(path, 'Cargo.toml')
if os.path.exists(manifest):
return path
parent = os.path.dirname(path)
if parent == path:
return None
path = parent
def active_view_is_rust(window=None, view=None):
"""Determine if the current view is a Rust source file.
:param window: The Sublime window (defaults to active window).
:param view: The view to check (defaults to active view).
:Returns: True if it is a Rust source file, False if not.
"""
if view is None:
if window is None:
window = sublime.active_window()
view = window.active_view()
if not view:
return False
# Require it to be saved to disk.
if not view.file_name():
return False
return 'source.rust' in view.scope_name(0)
def get_cargo_metadata(window, cwd, toolchain=None):
"""Load Cargo metadata.
:returns: None on failure, otherwise a dictionary from Cargo:
- packages: List of packages:
- name
- manifest_path: Path to Cargo.toml.
- targets: List of target dictionaries:
- name: Name of target.
- src_path: Path of top-level source file. May be a
relative path.
- kind: List of kinds. May contain multiple entries if
`crate-type` specifies multiple values in Cargo.toml.
Lots of different types of values:
- Libraries: 'lib', 'rlib', 'dylib', 'cdylib', 'staticlib',
'proc-macro'
- Executables: 'bin', 'test', 'example', 'bench'
- build.rs: 'custom-build'
:raises ProcessTermiantedError: Process was terminated by another thread.
"""
from . import rust_proc
cmd = ['cargo']
if toolchain:
cmd.append('+' + toolchain)
cmd.extend(['metadata', '--no-deps'])
output = rust_proc.slurp_json(window,
cmd,
cwd=cwd)
if output:
return output[0]
else:
return None