-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathxcode-clang-format.applescript
executable file
·176 lines (140 loc) · 5.14 KB
/
xcode-clang-format.applescript
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
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
#!/usr/bin/osascript
(*
To use this script, install clang-format (the easiest way is to use Homebrew <https://brew.sh/>)
```bash
# install Homebrew
/usr/bin/ruby -e "$(curl -fsSL \
https://raw.githubusercontent.com/Homebrew/install/master/install)"
# install clang-format
brew install clang-format
```
Then add the script as a behavior in Xcode:
* Xcode->Behaviors->Edit Behaviors...
* Click (+) in lower left corner to add new behavior.
* Name the behavior "clang-format"
* Click on the (command) icon to add a command key (I use F1)
* Click the Run checkbox and the Choose Script... and select this script
Now you can select text in a source document in XCode and hit F1 (or whatever you chose) to format
that selection. You should make sure the code will compile first or your formatting may be wrong.
If you don't like the formatting, you can undo.
This script relies on sending key commands to the app - you must modify the script if your
key commands have been remapped.
*)
on xcode_command(key)
tell application "System Events"
set frontmost of process "Xcode" to true
try
keystroke key using command down
on error message
display dialog message
error
end try
end tell
delay 0.5 -- delay so system events don't cross Xcode events
end xcode_command
on paste(_text)
set the clipboard to _text
my xcode_command("v") -- paste
end paste
on save_document()
my xcode_command("s") -- save
end save_document
on is_blank_line(_line)
repeat with _char in _line
if ((id of _char) is not (id of tab)) and ((id of _char) is not (id of space)) then return false
end repeat
return true
end is_blank_line
on last_blank_line_after(_lines, _index)
if (_index is length of _lines) then return _index
if is_blank_line(item _index of _lines) then return _index
repeat with _index from _index + 1 to length of _lines
if is_blank_line(item _index of _lines) then return _index - 1
end repeat
return length of _lines
end last_blank_line_after
on last_blank_line_before(_lines, _index)
if (_index is 1) then return 1
if is_blank_line(item _index of _lines) then return _index
repeat with _index from _index - 1 to 1 by -1
if is_blank_line(item _index of _lines) then return _index + 1
end repeat
return 1
end last_blank_line_before
on line_count_without_trailing_empty_lines(_source)
set _lines to (length of _source)
if _lines = 0 then return 0
repeat with _index from _lines to 1 by -1
if item _index of _source � "" then
return _index
end if
end repeat
return 1
end line_count_without_trailing_empty_lines
on front_source_document()
tell application "Xcode"
set _window_name to name of front window
repeat with _document in source documents
if _window_name contains name of _document then
return _document
end if
end repeat
return null
end tell
end front_source_document
try
tell application "Xcode"
set _document to my front_source_document()
if _document is null then
display alert "clang-format failed." message �
"Could not find front document." buttons {"OK"} default button "OK"
return
end if
if selected paragraph range of _document is {} then
display alert "clang-format failed." message �
"No selection found in front document." buttons {"OK"} default button "OK"
return
end if
my save_document()
set _source to paragraphs of (get text of _document)
set _range to selected paragraph range of _document
set item 1 of _range to my last_blank_line_before(_source, item 1 of _range)
set item 2 of _range to my last_blank_line_after(_source, item 2 of _range)
-- pin range to ignore empty blank lines
set _source_lines to my line_count_without_trailing_empty_lines(_source)
if item 1 of _range > _source_lines then return -- selection in trailing white space is ambigous
if item 2 of _range > _source_lines then set item 2 of _range to _source_lines
set selected paragraph range of _document to _range
set _path to path of _document
tell me
try
do shell script "eval \"$(/opt/homebrew/bin/brew shellenv)\";" & �
"clang-format " & �
"-lines=" & item 1 of _range & ":" & item 2 of _range & " " & �
quoted form of _path & " > /tmp/xcode-clang-format.tmp"
on error error_message
display alert "clang-format failed" message error_message buttons {"OK"} default button "OK"
return
end try
set _result to paragraphs in (read POSIX file "/tmp/xcode-clang-format.tmp" as �class utf8�)
end tell
set _result_lines to my line_count_without_trailing_empty_lines(_result)
set _f to item 1 of _range
set _l to (item 2 of _range) + (_result_lines - _source_lines)
if _l > length of _result then set _l to length of _result
if _f > _l then return -- selection was in trailing blank lines
set _replace to item _f of _result
if _f � _l then
repeat with _line in items (_f + 1) thru _l of _result
set _replace to _replace & linefeed & _line
end repeat
end if
my paste(_replace as text)
-- Xcode 14.3.1 doesn't set the final range for unknown reasons
set _l to (item 2 of (get selected paragraph range of _document))
set selected paragraph range of _document to {_f, _l}
end tell
on error message
display dialog message
error
end try