Skip to content

Commit 37ed4e5

Browse files
authored
Merge pull request #8610 from compnerd/swift-format
Swift format
2 parents 6a52cfd + 9c15385 commit 37ed4e5

File tree

2 files changed

+98
-8
lines changed

2 files changed

+98
-8
lines changed

tools/driver/swift_format_main.cpp

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -162,11 +162,6 @@ class SwiftFormatInvocation {
162162
InputFilenames.push_back(A->getValue());
163163
}
164164

165-
if (InputFilenames.empty()) {
166-
Diags.diagnose(SourceLoc(), diag::error_mode_requires_an_input_file);
167-
return 1;
168-
}
169-
170165
if (const Arg *A = ParsedArgs.getLastArg(OPT_o)) {
171166
OutputFilename = A->getValue();
172167
}
@@ -254,7 +249,7 @@ int swift_format_main(ArrayRef<const char *> Args, const char *Argv0,
254249

255250
DiagnosticEngine &Diags = Instance.getDiags();
256251
if (Invocation.parseArgs(Args, Diags) != 0)
257-
return 1;
252+
return EXIT_FAILURE;
258253

259254
std::vector<std::string> InputFiles = Invocation.getInputFilenames();
260255
unsigned NumInputFiles = InputFiles.size();
@@ -268,10 +263,11 @@ int swift_format_main(ArrayRef<const char *> Args, const char *Argv0,
268263
// We don't support formatting file ranges for multiple files.
269264
Instance.getDiags().diagnose(SourceLoc(),
270265
diag::error_formatting_multiple_file_ranges);
271-
return 1;
266+
return EXIT_FAILURE;
272267
}
273268
for (unsigned i = 0; i < NumInputFiles; ++i)
274269
Invocation.format(InputFiles[i], Diags);
275270
}
276-
return 0;
271+
272+
return EXIT_SUCCESS;
277273
}

utils/vim/swift-format.py

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
# This file is a minimal swift-format vim-integration. To install:
2+
# - Change 'binary' if swift-format is not on the path (see below).
3+
# - Add to your .vimrc:
4+
#
5+
# map <C-I> :pyf <path-to-this-file>/swift-format.py<cr>
6+
# imap <C-I> <c-o>:pyf <path-to-this-file>/swift-format.py<cr>
7+
#
8+
# The first line enables swift-format for NORMAL and VISUAL mode, the second
9+
# line adds support for INSERT mode. Change "C-I" to another binding if you
10+
# need swift-format on a different key (C-I stands for Ctrl+i).
11+
#
12+
# With this integration you can press the bound key and swift-format will
13+
# format the current line in NORMAL and INSERT mode or the selected region in
14+
# VISUAL mode. The line or region is extended to the next bigger syntactic
15+
# entity.
16+
#
17+
# You can also pass in the variable "l:lines" to choose the range for
18+
# formatting. This variable can either contain "<start line>:<end line> or
19+
# "all" to format the full file. So, to format the full file, write a function
20+
# like:
21+
#
22+
# :function FormatFile()
23+
# : let l:lines="all"
24+
# : pyf <path-to-this-file>/swift-format.py
25+
# :endfunction
26+
#
27+
# It operates on the current, potentially unsaved buffer and does not create or
28+
# save any files. To revert a formatting, just undo.
29+
30+
from __future__ import print_function
31+
32+
import difflib
33+
import platform
34+
import subprocess
35+
import sys
36+
import vim
37+
38+
binary = 'swift-format'
39+
if vim.eval('exists("g:swift_format_path")') == "1":
40+
binary = vim.eval('g:swift_format_path')
41+
42+
43+
def get_buffer(encoding):
44+
if platform.python_version_tuple()[0] == "3":
45+
return vim.current.buffer
46+
return [line.decode(encoding) for line in vim.current.buffer]
47+
48+
49+
def main(argc, argv):
50+
encoding = vim.eval("&encoding")
51+
buf = get_buffer(encoding)
52+
53+
if vim.eval('exists("l:lines")') == '1':
54+
lines = vim.eval('l:lines')
55+
else:
56+
lines = '%s:%s' % (vim.current.range.start + 1,
57+
vim.current.range.end + 1)
58+
59+
cursor = int(vim.eval('line2byte(line(".")) + col(".")')) - 2
60+
if cursor < 0:
61+
print("Couldn't determine cursor position. Is your file empty?")
62+
return
63+
64+
# avoid the cmd prompt on windows
65+
SI = None
66+
if sys.platform.startswith('win32'):
67+
SI = subprocess.STARTUPINFO()
68+
SI.dwFlags |= subprocess.STARTF_USESHOWWINDOW
69+
SI.wShowWindow = subprocess.SW_HIDE
70+
71+
command = [binary]
72+
if lines != 'all':
73+
command.extend(['-line-range', lines])
74+
75+
p = subprocess.Popen(command,
76+
stdout=subprocess.PIPE, stderr=subprocess.PIPE,
77+
stdin=subprocess.PIPE, startupinfo=SI)
78+
stdout, stderr = p.communicate(input='\n'.join(buf).encode(encoding))
79+
80+
if stderr:
81+
print(stderr)
82+
83+
if not stdout:
84+
print('No output from swift-format (crashed?).')
85+
return
86+
87+
lines = stdout.decode(encoding).split('\n')
88+
sequence = difflib.SequenceMatcher(None, buf, lines)
89+
for op in reversed(sequence.get_opcodes()):
90+
if op[0] is not 'equal':
91+
vim.current.buffer[op[1]:op[2]] = lines[op[3]:op[4]]
92+
93+
if __name__ == '__main__':
94+
main(len(sys.argv), sys.argv)

0 commit comments

Comments
 (0)