mac 桌面全能工具 hammerspoon

介绍

官网地址: http://www.hammerspoon.org/
官网描述

Hammerspoon 是一款强大的macos自动化工具,从本质上讲,Hammerspoon只是操作系统和Lua脚本引擎之间的桥梁. Hammerspoon的强大之处在于 向用户提供了无限扩展性.

让我们可以通过编写 Lua 代码来实现操作应用程序、窗口、鼠标、文本、音频设备、电池、屏幕、剪切板、定位、wifi等。基本囊括了系统的各方面.

安装

很简单 https://github.com/Hammerspoon/hammerspoon/releases/ 点击下载最新的就行

  • 回来 想安装mac 软件一样的方式安装 把app 移到 /Applications 文件夹就行了
  • 打开 Hammerspoon.app 按照提示操作就行, 别忘记打开 电脑设置里面的 安全&隐私/辅助功能

使用

一般是先 配置成开机自启动

打开 配置文件 可以自由发挥了

插件

https://www.hammerspoon.org/Spoons/ 这里面是一些官方提供的插件 称为 spoons
或者 https://github.com/Hammerspoon/Spoons 里面
或者 我们也可以去网上搜一些插件

一个例子 https://www.hammerspoon.org/Spoons/AClock.html

我们 从这个页面把 插件下载下来 是一个 zip 文件
怎么用呢 https://github.com/Hammerspoon/hammerspoon/blob/master/SPOONS.md 这里面是详细的文档
大概就是 解压 zip 文件, 然后双击解压后的文件 这里是 AClock.spoon 就安装 好了 在 ~/.hammerspoon/Spoons/
打开配置文件 输入

local AClock = hs.loadSpoon("AClock")
function toggleShowClock()
  AClock:toggleShow()
end
hs.hotkey.bind({ "cmd", "shift" }, "a", toggleShowClock)

reload config 之后 我们按键盘 cmd + shift + a 桌面就会有一个时钟 显示 4秒后消失, AClock:toggleShow() 是这样的, 更多api 请看AClock文档

非官方的小工具

剪切板工具

用了存储 复制历史的 open config 输入如下的, reload 之后就获得一个剪切板工具

非常方便啊 还能搜

-- Clipboard History

local width = 30
local maxSize = 100

local storePath = os.getenv("HOME") .. "/.clipboard"
local cachePath = storePath .. "/cache.json"
local imagePath = storePath .. "/images"

local UTI_TYPE = {
  IMAGE_TIFF = "public.tiff",
  IMAGE_PNG = "public.png",
  PLAIN_TEXT = "public.utf8-plain-text",
}

local HISTORY_TYPE = {
  IMAGE = "IMAGE",
  TEXT = "TEXT",
}

function readHistoryFromCache()
  hs.fs.mkdir(storePath)
  local cacheFile = io.open(cachePath, "r")
  if cacheFile then
    local content = cacheFile:read("*a")
    if content ~= "" then
      return hs.json.decode(content)
    end
  end

  return {}
end

function saveHistoryIntoCache(history)
  local cacheFile = io.open(cachePath, "w")
  cacheFile:write(hs.json.encode(history))
  cacheFile:close()
end

function saveTemporaryImage(image)
  hs.fs.mkdir(imagePath)
  local imageBase64 = hs.base64.encode(image:encodeAsURLString())
  local startIndex = string.len(imageBase64) / 2
  local endIndex = startIndex + 5;
  local filename = imagePath .. "/" .. string.sub(imageBase64, startIndex, endIndex) .. ".png"
  image:saveToFile(filename)
  return filename
end

function reduceHistorySize()
  while #history >= maxSize do
    table.remove(history, #history)
  end
end

function addHistoryFromPasteboard()
  local contentTypes = hs.pasteboard.contentTypes()

  local item = {}
  for index, uti in ipairs(contentTypes) do
    if uti == UTI_TYPE.IMAGE_TIFF or uti == UTI_TYPE.IMAGE_PNG then
      local image = hs.pasteboard.readImage()
      item.text = "_IMAGE_"
      item.type = HISTORY_TYPE.IMAGE
      item.content = saveTemporaryImage(image)
      break
    elseif uti == UTI_TYPE.PLAIN_TEXT then
      local text = hs.pasteboard.readString()
      if text == nil or utf8.len(text) < 3 then
        return
      end

      item.text = string.gsub(text, "[\r\n]+", " ")
      item.type = HISTORY_TYPE.TEXT;
      item.content = text;
      break
    end
  end

  if item.text then
    for index, el in ipairs(history) do
      if item.content == el.content then
        table.remove(history, index)
      end
    end

    local appname = hs.window.focusedWindow():application():name()
    item.subText = appname .. " / " .. os.date("%Y-%m-%d %H:%M", os.time())

    table.insert(history, 1, item)
    saveHistoryIntoCache(history)
  end
end

function showClipboard()
  local choices = hs.fnutils.map(history, function(item)
    local choice = hs.fnutils.copy(item)
    choice.text = " " .. choice.text
    choice.subText = " " .. choice.subText
    if choice.type == HISTORY_TYPE.IMAGE then
      choice.image = hs.image.imageFromPath(item.content)
    end
    return choice
  end)

  chooser:width(width);
  chooser:choices(choices);
  chooser:show()
end

function choiceClipboard(choice)
  if choice then
    if choice.type == HISTORY_TYPE.IMAGE then
      local image = hs.image.imageFromPath(choice.content)
      hs.pasteboard.writeObjects(image)
    else
      hs.pasteboard.setContents(choice.content)
    end
    hs.eventtap.keyStroke({ "cmd" }, "v")
  end
  if chooser:query() ~= "" then
    chooser:query("")
  end
end

history = readHistoryFromCache()
chooser = hs.chooser.new(choiceClipboard)
preChangeCount = hs.pasteboard.changeCount()
watcher = hs.timer.new(0.5, function()
  local changeCount = hs.pasteboard.changeCount()
  if changeCount ~= preChangeCount then
    pcall(addHistoryFromPasteboard)
    preChangeCount = changeCount
  end
end)
watcher:start()

hs.hotkey.bind({ "cmd", "shift" }, "v", showClipboard)
reduceHistorySize()
posted @   prowayne  阅读(316)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 零经验选手,Compose 一天开发一款小游戏!
· 因为Apifox不支持离线,我果断选择了Apipost!
· 通过 API 将Deepseek响应流式内容输出到前端
点击右上角即可分享
微信分享提示