-
Notifications
You must be signed in to change notification settings - Fork 1
/
PopupTranslateSelection.lua
158 lines (143 loc) · 6.76 KB
/
PopupTranslateSelection.lua
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
--- === PopupTranslateSelection ===
---
--- Show a popup window with the translation of the currently selected (or other) text
---
--- Supported language codes are listed at https://cloud.google.com/translate/docs/languages
---
--- Download: [https://github.com/Hammerspoon/Spoons/raw/master/Spoons/PopupTranslateSelection.spoon.zip](https://github.com/Hammerspoon/Spoons/raw/master/Spoons/PopupTranslateSelection.spoon.zip)
local util = require('util')
local keyUpDown = util.keyUpDown
local obj={}
obj.__index = obj
-- Metadata
obj.name = "PopupTranslateSelection"
obj.version = "0.1"
obj.author = "Diego Zamboni <[email protected]>"
obj.homepage = "https://github.com/Hammerspoon/Spoons"
obj.license = "MIT - https://opensource.org/licenses/MIT"
-- User-configurable variables
--- PopupTranslateSelection.popup_size
--- Variable
--- `hs.geometry` object representing the size to use for the translation popup window. Defaults to `hs.geometry.size(770, 610)`.
obj.popup_size = hs.geometry.size(770, 610)
--- PopupTranslateSelection.popup_style
--- Variable
--- Value representing the window style to be used for the translation popup window. This value needs to be a valid argument to [`hs.webview.setStyle()`](http://www.hammerspoon.org/docs/hs.webview.html#windowStyle) (i.e. a combination of values from [`hs.webview.windowMasks`](http://www.hammerspoon.org/docs/hs.webview.html#windowMasks[]). Default value: `hs.webview.windowMasks.utility|hs.webview.windowMasks.HUD|hs.webview.windowMasks.titled|hs.webview.windowMasks.closable`
obj.popup_style = hs.webview.windowMasks.utility|hs.webview.windowMasks.HUD|hs.webview.windowMasks.titled|hs.webview.windowMasks.closable
--- PopupTranslateSelection.popup_close_on_escape
--- Variable
--- If true, pressing ESC on the popup window will close it. Defaults to `true`
obj.popup_close_on_escape = true
--- PopupTranslateSelection.logger
--- Variable
--- Logger object used within the Spoon. Can be accessed to set the default log level for the messages coming from the Spoon.
obj.logger = hs.logger.new('PopupTranslateSelection', 'error')
----------------------------------------------------------------------
-- Internal variable - the hs.webview object for the popup
obj.webview = nil
--- PopupTranslateSelection:translatePopup(text, to, from)
--- Method
--- Display a translation popup with the translation of the given text between the specified languages
---
--- Parameters:
--- * text - string containing the text to translate
--- * to - two-letter code for destination language. If `nil`, Google Translate will use your most recent selection, or default to English
--- * from - two-letter code for source language. If `nil`, Google Translate will try to auto-detect it
---
--- Returns:
--- * The PopupTranslateSelection object
function obj:translatePopup(text, to, from)
local query=hs.http.encodeForQuery(text)
local url = "http://translate.google.com/translate_t?" ..
(from and ("sl=" .. from .. "&") or "") ..
(to and ("tl=" .. to .. "&") or "") ..
"text=" .. query
-- Persist the window between calls to reduce startup time on subsequent calls
if self.webview == nil then
local rect = hs.geometry.rect(0, 0, self.popup_size.w, self.popup_size.h)
rect.center = hs.screen.mainScreen():frame().center
self.webview=hs.webview.new(rect)
:allowTextEntry(true)
:windowStyle(self.popup_style)
:closeOnEscape(self.popup_close_on_escape)
end
self.webview:url(url)
:bringToFront()
:show()
self.webview:hswindow():focus()
return self
end
--- PopupTranslateSelection:translateSelectionPopup(to, from)
--- Method
--- Get the current selected text in the frontmost window and display a translation popup with the translation between the specified languages
---
--- Parameters:
--- * to - two-letter code for destination language. If `nil`, Google Translate will use your most recent selection, or default to English
--- * from - two-letter code for source language. If `nil`, Google Translate will try to auto-detect it
---
--- Returns:
--- * The PopupTranslateSelection object
function obj:translateSelectionPopup(to,from)
-- Preserve the current contents of the system clipboard
local originalClipboardContents = hs.pasteboard.getContents()
-- Copy the currently-selected text to the system clipboard
keyUpDown('cmd', 'c')
-- Allow some time for the command+c keystroke to fire asynchronously before
-- we try to read from the clipboard
hs.timer.doAfter(0.1, function()
-- Construct the transformed output and paste it over top of the
-- currently-selected text
local text = hs.pasteboard.getContents()
hs.timer.doAfter(0.1, function()
hs.pasteboard.setContents(originalClipboardContents)
end)
self:translatePopup(text,to,from)
end)
end
--- PopupTranslateSelection:bindHotkeys(mapping)
--- Method
--- Binds hotkeys for PopupTranslateSelection
---
--- Parameters:
--- * mapping - A table containing hotkey modifier/key details for the following items:
--- * `translate` - translate the selected text without specifying source/destination languages (source defaults to auto-detect, destination defaults to your last choice or to English)
--- * `translate_to_<lang>` - translate the selected text to the given destination language. Source language will be auto-detected.
--- * `translate_from_<lang>` - translate the selected text from the given destination language. Destination language will default to your last choice, or to English.
--- * `translate_<from>_<to>` - translate the selected text between the given languages.
---
--- Sample value for `mapping`:
--- ```
--- {
--- translate_to_en = { { "ctrl", "alt", "cmd" }, "e" },
--- translate_to_de = { { "ctrl", "alt", "cmd" }, "d" },
--- translate_to_es = { { "ctrl", "alt", "cmd" }, "s" },
--- translate_de_en = { { "shift", "ctrl", "alt", "cmd" }, "e" },
--- translate_en_de = { { "shift", "ctrl", "alt", "cmd" }, "d" },
--- }
--- ```
function obj:bindHotkeys(mapping)
local def = {}
for action,key in pairs(mapping) do
if action == "translate" then
def.translate = hs.fnutils.partial(self.translateSelectionPopup, self)
elseif action:match("^translate[-_](.*)[-_](.*)$") then
local from,to = nil,nil
local l1,l2 = action:match("^translate[-_](.*)[-_](.*)$")
if l1 == 'from' then
-- "translate_from_<lang>"
from=l2
elseif l1 == 'to' then
-- "translate_to_<lang>"
to=l2
else
-- "translate_<from>_<to>"
from,to = l1,l2
end
def[action] = hs.fnutils.partial(self.translateSelectionPopup, self, to, from)
else
self.logger.ef("Invalid hotkey action '%s'", action)
end
end
hs.spoons.bindHotkeysToSpec(def, mapping)
end
return obj