Skip to content

Commit 608e20d

Browse files
authored
Merge pull request #338 from nickspoons/support-wsl-cygwin
Translate Windows<->Unix paths in WSL and Cygwin
2 parents b69aeed + a098b14 commit 608e20d

File tree

8 files changed

+105
-148
lines changed

8 files changed

+105
-148
lines changed

autoload/OmniSharp.vim

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ function! OmniSharp#Complete(findstart, base) abort
2929

3030
return start
3131
else
32-
let omnisharp_last_completion_result = pyeval('Completion().get_completions("s:column", "a:base")')
32+
let omnisharp_last_completion_result = pyeval('getCompletions("s:column", "a:base")')
3333
let s:omnisharp_last_completion_dictionary = {}
3434
for completion in omnisharp_last_completion_result
3535
let s:omnisharp_last_completion_dictionary[get(completion, 'word')] = completion

autoload/OmniSharp/util.vim

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,14 @@ function! s:resolve_local_config(solution_path) abort
1818
return ''
1919
endfunction
2020

21+
function! s:is_cygwin() abort
22+
return has('win32unix')
23+
endfunction
24+
25+
function! s:is_wsl() abort
26+
return strlen(system('grep Microsoft /proc/version')) > 0
27+
endfunction
28+
2129
function! OmniSharp#util#path_join(parts) abort
2230
if type(a:parts) == type('')
2331
let parts = [a:parts]
@@ -34,6 +42,16 @@ function! OmniSharp#util#get_start_cmd(solution_path) abort
3442
if fnamemodify(solution_path, ':t') ==? s:roslyn_server_files
3543
let solution_path = fnamemodify(solution_path, ':h')
3644
endif
45+
46+
if g:OmniSharp_translate_cygwin_wsl == 1 && (s:is_cygwin() || s:is_wsl())
47+
" Future releases of WSL will have a wslpath tool, similar to cygpath - when
48+
" this becomes standard then this block can be replaced with a call to
49+
" wslpath/cygpath
50+
let prefix = s:is_cygwin() ? '^/cygdrive/' : '^/mnt/'
51+
let solution_path = substitute(solution_path, prefix.'\([a-zA-Z]\)/', '\u\1:\\', '')
52+
let solution_path = substitute(solution_path, '/', '\\', 'g')
53+
endif
54+
3755
let g:OmniSharp_running_slns += [solution_path]
3856
let port = exists('b:OmniSharp_port') ? b:OmniSharp_port : g:OmniSharp_port
3957

doc/omnisharp-vim.txt

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,9 @@ OPTIONS *omnisharp-options*
4444

4545
*'g:syntastic_cs_checkers'*
4646
Use this option to enable syntastic integration >
47-
let g:syntastic_cs_checkers=['syntax', 'semantic', 'issues']
47+
let g:syntastic_cs_checkers=['syntax', 'semantic', 'issues'] " v1 server
48+
OR
49+
let g:syntastic_cs_checkers=['code_checker'] " roslyn
4850
<
4951

5052
*'g:OmniSharp_selector_ui'*
@@ -83,6 +85,12 @@ Default: 'v1' >
8385
let g:OmniSharp_server_type='roslyn'
8486
<
8587

88+
*'g:OmniSharp_server_path'*
89+
Use this option to give the full path to the roslyn or v1 omnisharp server
90+
executable. >
91+
let g:OmniSharp_server_path='/home/username/omnisharp/omnisharp.http-linux-x64/omnisharp/OmniSharp.exe'
92+
<
93+
8694
*'g:OmniSharp_host'*
8795
Use this option to specify the host address of the OmniSharp server.
8896
Default: 'http://localhost:2000' >
@@ -101,7 +109,7 @@ server. Default: 1 >
101109
let g:OmniSharp_timeout=1
102110
<
103111

104-
*'g:omnicomplete_fetch_full_documentation'*
112+
*'g:omnicomplete_fetch_full_documentation'*
105113
Use this option to specify whether OmniSharp will fetch full documentation on
106114
completion suggestions. By default, only type/method signatures are fetched for
107115
performance reasons. Full documentation can still be fetched when needed using
@@ -115,6 +123,15 @@ Default: 0 >
115123
let g:OmniSharp_want_snippet=0
116124
<
117125

126+
*'g:OmniSharp_translate_cygwin_wsl'*
127+
Use this option when vim is running in a Cygwin or Windows Subsystem for Linux
128+
environment on Windows, but the omnisharp server is a Windows binary. When set
129+
to 1, omnisharp-vim will translate the cygwin/WSL unix paths into Windows paths
130+
and back.
131+
Default: 0 >
132+
let g:OmniSharp_translate_cygwin_wsl=1
133+
<
134+
118135
===============================================================================
119136
COMMANDS *omnisharp-commands*
120137

plugin/OmniSharp.vim

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,12 @@ if !has('python')
99
finish
1010
endif
1111

12+
" Set default for translating cygwin/WSL unix paths to Windows paths
13+
let g:OmniSharp_translate_cygwin_wsl = get(g:, 'OmniSharp_translate_cygwin_wsl', 0)
14+
1215
"Load python/OmniSharp.py
1316
let s:py_path = OmniSharp#util#path_join('python')
1417
exec "python sys.path.append(r'" . s:py_path . "')"
15-
exec 'pyfile ' . fnameescape(OmniSharp#util#path_join(['python', 'Completion.py']))
1618
exec 'pyfile ' . fnameescape(OmniSharp#util#path_join(['python', 'OmniSharp.py']))
1719

1820
let g:OmniSharp_port = get(g:, 'OmniSharp_port', 2000)

python/Completion.py

Lines changed: 0 additions & 36 deletions
This file was deleted.

python/OmniSharp.py

Lines changed: 64 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
1-
import vim, urllib2, urllib, urlparse, logging, json, os, os.path, cgi, types, threading
2-
import asyncrequest
1+
import json, logging, os.path, platform, re, urllib2, urlparse, vim
32

43
logger = logging.getLogger('omnisharp')
54
logger.setLevel(logging.WARNING)
@@ -13,13 +12,34 @@
1312
formatter = logging.Formatter('%(asctime)s %(levelname)s %(message)s')
1413
hdlr.setFormatter(formatter)
1514

15+
translate_unix_win = bool(int(vim.eval('g:OmniSharp_translate_cygwin_wsl')))
16+
is_cygwin = 'cygwin' in platform.system().lower()
17+
is_wsl = 'linux' in platform.system().lower() and 'microsoft' in platform.release().lower()
18+
19+
# When working in Windows Subsystem for Linux (WSL) or Cygwin, vim uses
20+
# unix-style paths but OmniSharp (with a Windows binary) uses Windows
21+
# paths. This means that filenames returned FROM OmniSharp must be
22+
# translated from e.g. "C:\path\to\file" to "/mnt/c/path/to/file", and
23+
# filenames sent TO OmniSharp must be translated in the other direction.
24+
def formatPathForServer(filepath):
25+
if translate_unix_win and (is_cygwin or is_wsl):
26+
pattern = r'^/cygdrive/([a-zA-Z])/' if is_cygwin else r'^/mnt/([a-zA-Z])/'
27+
return re.sub(pattern, r'\1:\\', filepath).replace('/', '\\')
28+
return filepath
29+
def formatPathForClient(filepath):
30+
if translate_unix_win and (is_cygwin or is_wsl):
31+
def path_replace(matchobj):
32+
prefix = '/cygdrive/{0}/' if is_cygwin else '/mnt/{0}/'
33+
return prefix.format(matchobj.group(1).lower())
34+
return re.sub(r'^([a-zA-Z]):\\', path_replace, filepath).replace('\\', '/')
35+
return filepath
1636

1737
def getResponse(endPoint, additional_parameters=None, timeout=None):
1838
parameters = {}
1939
parameters['line'] = vim.eval('line(".")')
2040
parameters['column'] = vim.eval('col(".")')
2141
parameters['buffer'] = '\r\n'.join(vim.eval("getline(1,'$')")[:])
22-
parameters['filename'] = vim.current.buffer.name
42+
parameters['filename'] = formatPathForServer(vim.current.buffer.name)
2343
if additional_parameters != None:
2444
parameters.update(additional_parameters)
2545

@@ -67,14 +87,47 @@ def findImplementations():
6787
js = getResponse('/findimplementations', parameters)
6888
return get_quickfix_list(js, 'QuickFixes')
6989

90+
def getCompletions(column, partialWord):
91+
parameters = {}
92+
parameters['column'] = vim.eval(column)
93+
parameters['wordToComplete'] = vim.eval(partialWord)
94+
95+
parameters['WantDocumentationForEveryCompletionResult'] = \
96+
bool(int(vim.eval('g:omnicomplete_fetch_full_documentation')))
97+
98+
want_snippet = \
99+
bool(int(vim.eval('g:OmniSharp_want_snippet')))
100+
101+
parameters['WantSnippet'] = want_snippet
102+
parameters['WantMethodHeader'] = want_snippet
103+
parameters['WantReturnType'] = want_snippet
104+
105+
parameters['buffer'] = '\r\n'.join(vim.eval('s:textBuffer')[:])
106+
107+
response = json.loads(getResponse('/autocomplete', parameters))
108+
109+
vim_completions = []
110+
if response != None:
111+
for completion in response:
112+
vim_completions.append({
113+
'snip': completion['Snippet'] or '',
114+
'word': completion['MethodHeader'] or completion['CompletionText'],
115+
'menu': completion['ReturnType'] or completion['DisplayText'],
116+
'info': (completion['Description'] or '').replace('\r\n', '\n'),
117+
'icase': 1,
118+
'dup': 1
119+
})
120+
return vim_completions
121+
70122
def gotoDefinition():
71123
js = getResponse('/gotodefinition');
72-
if(js != ''):
124+
if js != '':
73125
definition = json.loads(js)
74126
if(definition['FileName'] != None):
75-
openFile(definition['FileName'].replace("'","''"), definition['Line'], definition['Column'])
127+
filename = formatPathForClient(definition['FileName'].replace("'","''"))
128+
openFile(filename, definition['Line'], definition['Column'])
76129
else:
77-
print "Not found"
130+
print("Not found")
78131

79132
def openFile(filename, line, column):
80133
vim.command("call OmniSharp#JumpToLocation('%(filename)s', %(line)s, %(column)s)" % locals())
@@ -159,9 +212,9 @@ def build():
159212

160213
success = js["Success"]
161214
if success:
162-
print "Build succeeded"
215+
print("Build succeeded")
163216
else:
164-
print "Build failed"
217+
print("Build failed")
165218

166219
return quickfixes_from_js(js, 'QuickFixes')
167220

@@ -194,7 +247,7 @@ def addReference():
194247
js = getResponse("/addreference", parameters)
195248
if js != '':
196249
message = json.loads(js)['Message']
197-
print message
250+
print(message)
198251

199252
def findSyntaxErrors():
200253
js = getResponse('/syntaxerrors')
@@ -235,6 +288,8 @@ def quickfixes_from_response(response):
235288
filename = quickfix['FileName']
236289
if filename == None:
237290
filename = vim.current.buffer.name
291+
else:
292+
filename = formatPathForClient(filename)
238293

239294
item = {
240295
'filename': filename,

python/asyncrequest.py

Lines changed: 0 additions & 61 deletions
This file was deleted.

python/syncrequest.py

Lines changed: 0 additions & 38 deletions
This file was deleted.

0 commit comments

Comments
 (0)