--- === BrewInfo === --- --- Display pop-up with Homebrew Formula info, or open their URL --- --- Download: [https://github.com/Hammerspoon/Spoons/raw/master/Spoons/BrewInfo.spoon.zip](https://github.com/Hammerspoon/Spoons/raw/master/Spoons/BrewInfo.spoon.zip) --- --- You can bind keys to automatically display the output of `brew --- info` of the currently-selected package name, or to open its --- homepage. I use it to quickly explore new packages from the output --- of `brew update`. local mod={} mod.__index = mod -- Conformance hack, our Travis linter expects the object to be called "obj" local obj=mod -- Metadata mod.name = "BrewInfo" obj.version = "1.1" mod.author = "Diego Zamboni " mod.homepage = "https://github.com/Hammerspoon/Spoons" mod.license = "MIT - https://opensource.org/licenses/MIT" --- BrewInfo.brew_path --- Variable --- A string specifying the path to the `brew` executable. Defaults to `/usr/local/bin/brew` mod.brew_path = "/usr/local/bin/brew" --- BrewInfo.brew_info_delay_sec --- Variable --- An integer specifying how long the alerts generated by BrewInfo will stay onscreen mod.brew_info_delay_sec = 3 --- BrewInfo.brew_info_style --- Variable --- A table in conformance with the [hs.alert.defaultStyle](http://www.hammerspoon.org/docs/hs.alert.html#defaultStyle[]) format that specifies the style used by the alerts. Default value: `{ textFont = "Courier New", textSize = 14, radius = 10 }` mod.brew_info_style = { textFont = "Courier New", textSize = 14, radius = 10 } --- BrewInfo.select_text_if_needed --- Variable --- If `true`, and no text is currently selected in the terminal, issue a double-click to select the text below the cursor, and use that as the input to `brew info`. See also `BrewInfo.select_text_modifiers`. Defaults to `true`. mod.select_text_if_needed = true --- BrewInfo.select_text_modifiers --- Variable --- Table containing the modifiers to be used together with a double-click when `BrewInfo.select_text_if_needed` is true. Defaults to `{cmd = true, shift = true}` to issue a Cmd-Shift-double-click, which will select a continuous non-space string in Terminal and iTerm2. mod.select_text_modifiers = {cmd = true, shift = true} -- Internal function to issue a double click with given modifiers function leftDoubleClick(modifiers) local pos=hs.mouse.absolutePosition() hs.eventtap.event.newMouseEvent(hs.eventtap.event.types.leftMouseDown, pos, modifiers) :setProperty(hs.eventtap.event.properties.mouseEventClickState, 2) :post() hs.eventtap.event.newMouseEvent(hs.eventtap.event.types.leftMouseUp, pos, modifiers) :post() end -- Internal method to get the currently selected text -- If `select_text_if_needed` is true and no text is selected, issue -- a double-click to select, then use that function mod:current_selection() local elem=hs.uielement.focusedElement() if elem then local sel = elem:selectedText() if (sel == nil or sel == "") and self.select_text_if_needed then -- Simulate a double click to select the text under the cursor leftDoubleClick(self.select_text_modifiers) hs.timer.usleep(20000) sel = elem:selectedText() end return sel else return nil end end -- Internal method to show an alert in the configured style function mod:show(text) hs.alert.show(text, self.brew_info_style, self.brew_info_delay_sec) return self end --- BrewInfo:showBrewInfo(pkg, subcommand) --- Method --- Displays an alert with the output of `brew info ` --- --- Parameters: --- * pkg - name of the package to query --- * subcommand - brew subcommand to use for the `info` command. Defaults to an empty string, which results in "brew info " being run. For example, if `subcommand` is "cask", the `brew cask info ` command will be used. --- --- Returns: --- * The Spoon object function mod:showBrewInfo(pkg, subcommand) local info = "No package selected" local st = nil if pkg and pkg ~= "" then local cmd=string.format("%s %s info %s", self.brew_path, subcommand or "", pkg) info, st=hs.execute(cmd) if st == nil then info = "No information found about formula '" .. pkg .. "'!" end end self:show(info) return self end --- BrewInfo:showBrewInfoCurSel(subcommand) --- Method --- Display `brew info` using the selected text as the package name --- --- Parameters: --- * subcommand - brew subcommand to use for the `info` command. Defaults to an empty string, which results in "brew info" being run. For example, if `subcommand` is "cask", the `brew cask info` command will be used. --- --- Returns: --- * The Spoon object function mod:showBrewInfoCurSel(subcommand) return self:showBrewInfo(self:current_selection(), subcommand) end --- BrewInfo:openBrewURL(pkg, subcommand) --- Method --- Opens the homepage for package `pkg`, as obtained from the `homepage` field in `brew cat ` --- --- Parameters: --- * pkg - name of the package to query --- * subcommand - brew subcommand to use for the `cat` command. Defaults to an empty string, which results in "brew cat " being run. For example, if `subcommand` is "cask", the `brew cask cat ` command will be used. --- --- Returns: --- * The Spoon object function mod:openBrewURL(pkg, subcommand) local msg = "No package selected" if pkg and pkg ~= "" then local j, st, t, rc=hs.execute(string.format("%s %s cat %s", self.brew_path, (subcommand or ""), pkg )) if st ~= nil then local url=string.match(j, "\n%s*homepage%s+['\"](.-)['\"]%s*\n") if url and url ~= "" then hs.urlevent.openURLWithBundle(url, hs.urlevent.getDefaultHandler("http")) return self end end msg = "An error occurred obtaining information about '" .. pkg .. "'" end self:show(msg) return self end --- BrewInfo:openBrewURLCurSel(subcommand) --- Method --- Opens the homepage for the currently-selected package, as obtained from the `homepage` field in `brew cat ` --- --- Parameters: --- * subcommand - brew subcommand to use for the `cat` command. Defaults to an empty string, which results in "brew cat " being run. For example, if `subcommand` is "cask", the `brew cask cat ` command will be used. --- --- Returns: --- * The Spoon object function mod:openBrewURLCurSel(subcommand) return self:openBrewURL(self:current_selection(), subcommand) end --- BrewInfo:bindHotkeys(mapping) --- Method --- Binds hotkeys for BrewInfo --- --- Parameters: --- * mapping - A table containing hotkey modifier/key details for the following items: --- * show_brew_info - Show output of `brew info` using the selected text as package name --- * open_brew_url - Open the homepage of the formula whose name is currently selected --- * show_brew_cask_info - Show output of `brew cask info` using the selected text as package name --- * open_brew_cask_url - Open the homepage of the Cask whose name is currently selected function mod:bindHotkeys(mapping) local def = { show_brew_info = function() self:showBrewInfoCurSel() end, open_brew_url = function() self:openBrewURLCurSel() end, } for action, key in pairs(mapping) do local subcommand_show = action:match("show_brew_(.*)_info") if subcommand_show and subcommand_show ~= "" then def[action] = function() self:showBrewInfoCurSel(subcommand_show) end end local subcommand_open = action:match("open_brew_(.*)_url") if subcommand_open and subcommand_open ~= "" then def[action] = function() self:openBrewURLCurSel(subcommand_open) end end end hs.spoons.bindHotkeysToSpec(def, mapping) end return mod