【LUA】转载github自用二改模版——调节音量、显示七日天气、历史剪贴板、系统信息显示

二改模版笔记

自动重新加载HS

lua 复制代码
function reloadConfig(files)
    doReload = false
    for _,file in pairs(files) do
        if file:sub(-4) == ".lua" then
            doReload = true
        end
    end
    if doReload then
        hs.reload()
    end
end
myWatcher = hs.pathwatcher.new(os.getenv("HOME") .. "/.hammerspoon/", reloadConfig):start()
hs.alert.show("Config loaded")

调节音量

lua 复制代码
function changeVolume(diff)
  return function()
    local current = hs.audiodevice.defaultOutputDevice():volume()
    local new = math.min(100, math.max(0, math.floor(current + diff)))
    if new > 0 then
      hs.audiodevice.defaultOutputDevice():setMuted(false)
    end
    hs.alert.closeAll(0.0)
    hs.alert.show("Volume " .. new .. "%", {}, 0.5)
    hs.audiodevice.defaultOutputDevice():setVolume(new)
  end
end

hs.hotkey.bind({"shift","ctrl",'command'}, 'Down', changeVolume(-3))
hs.hotkey.bind({"shift","ctrl",'command'}, 'Up', changeVolume(3))

显示七日天气

lua 复制代码
local urlApi = 'http://v1.yiketianqi.com/free/api'
local menubar = hs.menubar.new()
local menuData = {}

local weaEmoji = {
   lei = '🌩️',
   qing = '☀️',
   shachen = '😷',
   wu = '🌫',
   xue = '❄️',
   yu = '🌧',
   yujiaxue = '🌨',
   yun = '☁️',
   zhenyu = '🌧',
   yin = '⛅️',
   default = ''
}

function updateMenubar()
	 menubar:setTooltip("Weather Info")
    menubar:setMenu(menuData)
end

function getWeather()
   hs.http.doAsyncRequest(urlApi, "GET", nil,nil, function(code, body, htable)
      if code ~= 200 then
         print('get weather error:'..code)
         return
      end
      rawjson = hs.json.decode(body)
      city = rawjson.city
      menuData = {}
      for k, v in pairs(rawjson.data) do
         if k == 1 then
            menubar:setTitle(weaEmoji[v.wea_img])
                     
            if v.win_speed == "<3级" then
                titlestr = string.format("%s  %s %s  🌡️%s-%s°C", city,weaEmoji[v.wea_img], v.wea, v.tem_night, v.tem_day)
            else
                titlestr = string.format("%s  %s 🌡️%s-%s°C  💨%s %s %s", city,weaEmoji[v.wea_img],v.tem_night, v.tem_day, v.win_speed,  v.win, v.wea)
            end

            
            item = { title = titlestr }
            table.insert(menuData, item)
            table.insert(menuData, {title = '-'})
            

         else
            
            if v.win_speed == "<3级" then
                titlestr = string.format("%s  %s 🌡️%s-%s°C     %s",  v.date, weaEmoji[v.wea_img], v.tem_night, v.tem_day, v.wea)
            else
                titlestr = string.format("%s  %s 🌡️%s-%s°C  💨%s %s %s",  v.date, weaEmoji[v.wea_img],v.tem_night, v.tem_day, v.win_speed, v.win, v.wea)
            end
         
            item = { title = titlestr }
            table.insert(menuData, item)
         end
      end
      updateMenubar()
   end)
end

menubar:setTitle('👀')
getWeather()
updateMenubar()
hs.timer.doEvery(3000, getWeather)

剪贴板

其中设置这个为true的话,可以直接插入
local pasteOnSelect = false -- Auto-type on click

lua 复制代码
--[[
   From https://github.com/victorso/.hammerspoon/blob/master/tools/clipboard.lua
   Modified by Diego Zamboni
]]--

-- Feel free to change those settings
local frequency = 0.8 -- Speed in seconds to check for clipboard changes. If you check too frequently, you will loose performance, if you check sparsely you will loose copies
local hist_size = 100 -- How many items to keep on history
local label_length = 70 -- How wide (in characters) the dropdown menu should be. Copies larger than this will have their label truncated and end with "..." (unicode for elipsis ...)
local honor_clearcontent = false --asmagill request. If any application clears the pasteboard, we also remove it from the history https://groups.google.com/d/msg/hammerspoon/skEeypZHOmM/Tg8QnEj_N68J
local pasteOnSelect = false -- Auto-type on click

-- Don't change anything bellow this line
local jumpcut = hs.menubar.new()
jumpcut:setTooltip("Clipboard history")
local pasteboard = require("hs.pasteboard") -- http://www.hammerspoon.org/docs/hs.pasteboard.html
local settings = require("hs.settings") -- http://www.hammerspoon.org/docs/hs.settings.html
local last_change = pasteboard.changeCount() -- displays how many times the pasteboard owner has changed // Indicates a new copy has been made

--Array to store the clipboard history
local clipboard_history = settings.get("so.victor.hs.jumpcut") or {} --If no history is saved on the system, create an empty history

function subStringUTF8(str, startIndex, endIndex)
    if startIndex < 0 then
        startIndex = subStringGetTotalIndex(str) + startIndex + 1
    end

    if endIndex ~= nil and endIndex < 0 then
        endIndex = subStringGetTotalIndex(str) + endIndex + 1
    end

    if endIndex == nil then 
        return string.sub(str, subStringGetTrueIndex(str, startIndex))
    else
        return string.sub(str, subStringGetTrueIndex(str, startIndex), subStringGetTrueIndex(str, endIndex + 1) - 1)
    end
end

--返回当前截取字符串正确下标
function subStringGetTrueIndex(str, index)
    local curIndex = 0
    local i = 1
    local lastCount = 1
    repeat 
        lastCount = subStringGetByteCount(str, i)
        i = i + lastCount
        curIndex = curIndex + 1
    until(curIndex >= index)
    return i - lastCount
end

--返回当前字符实际占用的字符数
function subStringGetByteCount(str, index)
    local curByte = string.byte(str, index)
    local byteCount = 1
    if curByte == nil then
        byteCount = 0
    elseif curByte > 0 and curByte <= 127 then
        byteCount = 1
    elseif curByte>=192 and curByte<=223 then
        byteCount = 2
    elseif curByte>=224 and curByte<=239 then
        byteCount = 3
    elseif curByte>=240 and curByte<=247 then
        byteCount = 4
    end
    return byteCount
end

-- Append a history counter to the menu
function setTitle()
   if (#clipboard_history == 0) then
      jumpcut:setTitle("✂") -- Unicode magic
   else
      jumpcut:setTitle("✂") -- Unicode magic
      --      jumpcut:setTitle("✂ ("..#clipboard_history..")") -- updates the menu counter
   end
end

function putOnPaste(string,key)
   if (pasteOnSelect) then
      hs.eventtap.keyStrokes(string)
      pasteboard.setContents(string)
      last_change = pasteboard.changeCount()
   else
      if (key.alt == true) then -- If the option/alt key is active when clicking on the menu, perform a "direct paste", without changing the clipboard
         hs.eventtap.keyStrokes(string) -- Defeating paste blocking http://www.hammerspoon.org/go/#pasteblock
      else
         pasteboard.setContents(string)
         last_change = pasteboard.changeCount() -- Updates last_change to prevent item duplication when putting on paste
      end
   end
end

-- Clears the clipboard and history
function clearAll()
   pasteboard.clearContents()
   clipboard_history = {}
   settings.set("so.victor.hs.jumpcut",clipboard_history)
   now = pasteboard.changeCount()
   setTitle()
end

-- Clears the last added to the history
function clearLastItem()
   table.remove(clipboard_history,#clipboard_history)
   settings.set("so.victor.hs.jumpcut",clipboard_history)
   now = pasteboard.changeCount()
   setTitle()
end

function pasteboardToClipboard(item)
   -- Loop to enforce limit on qty of elements in history. Removes the oldest items
   while (#clipboard_history >= hist_size) do
      table.remove(clipboard_history,1)
   end
   table.insert(clipboard_history, item)
   settings.set("so.victor.hs.jumpcut",clipboard_history) -- updates the saved history
   setTitle() -- updates the menu counter
end

-- Dynamic menu by cmsj https://github.com/Hammerspoon/hammerspoon/issues/61#issuecomment-64826257
populateMenu = function(key)
   setTitle() -- Update the counter every time the menu is refreshed
   menuData = {}
   if (#clipboard_history == 0) then
      table.insert(menuData, {title="None", disabled = true}) -- If the history is empty, display "None"
   else
      for k,v in pairs(clipboard_history) do
         if (string.len(v) > label_length) then
            table.insert(menuData,1, {title=subStringUTF8(v,0,label_length).."...", fn = function() putOnPaste(v,key) end }) -- Truncate long strings
         else
            table.insert(menuData,1, {title=v, fn = function() putOnPaste(v,key) end })
         end -- end if else
      end-- end for
   end-- end if else
   -- footer
   table.insert(menuData, {title="-"})
   table.insert(menuData, {title="Clear All", fn = function() clearAll() end })
   if (key.alt == true or pasteOnSelect) then
      table.insert(menuData, {title="Direct Paste Mode ✍", disabled=true})
   end
   return menuData
end

-- If the pasteboard owner has changed, we add the current item to our history and update the counter.
function storeCopy()
   now = pasteboard.changeCount()
   if (now > last_change) then
      current_clipboard = pasteboard.getContents()
      -- asmagill requested this feature. It prevents the history from keeping items removed by password managers
      if (current_clipboard == nil and honor_clearcontent) then
         clearLastItem()
      else
         pasteboardToClipboard(current_clipboard)
      end
      last_change = now
   end
end

--Checks for changes on the pasteboard. Is it possible to replace with eventtap?
timer = hs.timer.new(frequency, storeCopy)
timer:start()

setTitle() --Avoid wrong title if the user already has something on his saved history
jumpcut:setMenu(populateMenu)

hs.hotkey.bind({"cmd", "shift"}, "v", function() jumpcut:popupMenu(hs.mouse.getAbsolutePosition()) end)

系统信息显示

lua 复制代码
--- 显示系统信息
--- 可显示CPU\内存\硬盘\网络等实时信息
--- Created by sugood(https://github.com/sugood).
--- DateTime: 2022/01/14 22:00
---


local menubaritem = hs.menubar.new()
local menuData = {}

-- ipv4Interface ipv6 Interface
local interface = hs.network.primaryInterfaces()

-- 该对象用于存储全局变量,避免每次获取速度都创建新的局部变量
local obj = {}

function init()

    if interface then
        local interface_detail = hs.network.interfaceDetails(interface)
        if interface_detail.IPv4 then
            local ipv4 = interface_detail.IPv4.Addresses[1]
            table.insert(menuData, {
                title = "IPv4:" .. ipv4,
                tooltip = "Copy Ipv4 to clipboard",
                fn = function()
                    hs.pasteboard.setContents(ipv4)
                end
            })
        end
        local mac = hs.execute('ifconfig ' .. interface .. ' | grep ether | awk \'{print $2}\'')
        table.insert(menuData, {
            title = 'MAC:' .. mac,
            tooltip = 'Copy MAC to clipboard',
            fn = function()
                hs.pasteboard.setContents(mac)
            end
        })
        obj.last_down = hs.execute('netstat -ibn | grep -e ' .. interface .. ' -m 1 | awk \'{print $7}\'')
        obj.last_up = hs.execute('netstat -ibn | grep -e ' .. interface .. ' -m 1 | awk \'{print $10}\'')
    else
        obj.last_down =  0
        obj.last_down =  0
    end
    local date=os.date("%Y-%m-%d %a");
    table.insert(menuData, {
        title = 'Date: '..date,
        tooltip = 'Copy Now DateTime',
        fn = function()
            hs.pasteboard.setContents(os.date("%Y-%m-%d %H:%M:%S"))
        end
    })
    table.insert(menuData, {
        title = '打开:监  视  器    (⇧⌃A)',
        tooltip = 'Show Activity Monitor',
        fn = function()
            bindActivityMonitorKey()
        end
    })
    table.insert(menuData, {
        title = '打开:磁盘工具    (⇧⌃D)',
        tooltip = 'Show Disk Utility',
        fn = function()
            bindDiskKey()
        end
    })

    table.insert(menuData, {
        title = '打开:系统日历    (⇧⌃C)',
        tooltip = 'Show calendar',
        fn = function()
            bindCalendarKey()
        end
    })
    menubaritem:setMenu(menuData)
end

function scan()

    if interface then
        obj.current_down = hs.execute('netstat -ibn | grep -e ' .. interface .. ' -m 1 | awk \'{print $7}\'')
        obj.current_up = hs.execute('netstat -ibn | grep -e ' .. interface .. ' -m 1 | awk \'{print $10}\'')
    else
        obj.current_down  = 0
        obj.current_up = 0
    end

    obj.cpu_used = getCpu()
    obj.disk_used = getRootVolumes()
    obj.mem_used = getVmStats()
    obj.down_bytes = obj.current_down - obj.last_down
    obj.up_bytes = obj.current_up - obj.last_up

    obj.down_speed = format_speed(obj.down_bytes)
    obj.up_speed = format_speed(obj.up_bytes)

    obj.display_text = hs.styledtext.new('▲ ' .. obj.up_speed .. '\n'..'▼ ' .. obj.down_speed , {font={size=9}, color={hex='#FFFFFF'}, paragraphStyle={alignment="left", maximumLineHeight=18}})
    obj.display_disk_text = hs.styledtext.new(obj.disk_used ..'\n'.. 'SSD ' , {font={size=9}, color={hex='#FFFFFF'}, paragraphStyle={alignment="left", maximumLineHeight=18}})
    obj.display_mem_text = hs.styledtext.new(obj.mem_used ..'\n'.. 'MEM ' , {font={size=9}, color={hex='#FFFFFF'}, paragraphStyle={alignment="left", maximumLineHeight=18}})
    obj.display_cpu_text = hs.styledtext.new(obj.cpu_used ..'\n'.. 'CPU ' , {font={size=9}, color={hex='#FFFFFF'}, paragraphStyle={alignment="left", maximumLineHeight=18}})

    obj.last_down = obj.current_down
    obj.last_up = obj.current_up

    local canvas = hs.canvas.new{x = 0, y = 0, h = 24, w = 30+30+30+60}
    -- canvas[1] = {type = 'text', text = obj.display_text}
    canvas:appendElements({
        type = "text",
        text = obj.display_cpu_text,
        -- withShadow = true,
        trackMouseEnterExit = true,
        },{
        type = "text",
        text = obj.display_disk_text,
        -- withShadow = true,
        trackMouseEnterExit = true,
        frame = { x = 30, y = "0", h = "1", w = "1", }
        },{
        type = "text",
        text = obj.display_mem_text,
        -- withShadow = true,
        trackMouseEnterExit = true,
        frame = { x = 60, y = "0", h = "1", w = "1", }
        },{
        type = "text",
        text = obj.display_text,
        -- withShadow = true,
        trackMouseEnterExit = true,
        frame = { x = 90, y = "0", h = "1", w = "1", }
        })
    menubaritem:setIcon(canvas:imageFromCanvas())
    canvas:delete()
    canvas = nil
end

function format_speed(bytes)
    -- 单位 Byte/s
    if bytes < 1024 then
        return string.format('%6.0f', bytes) .. ' B/s'
    else
        -- 单位 KB/s
        if bytes < 1048576 then
            -- 因为是每两秒刷新一次,所以要除以 (1024 * 2)
            return string.format('%6.1f', bytes / 2048) .. ' KB/s'
            -- 单位 MB/s
        else
            -- 除以 (1024 * 1024 * 2)
            return string.format('%6.1f', bytes / 2097152) .. ' MB/s'
        end
    end
end

function getCpu()
    local data = hs.host.cpuUsage()
    local cpu = (data["overall"]["active"])
    return formatPercent(cpu)
end

function getVmStats()

    local vmStats = hs.host.vmStat()
    -- --1024^2
    -- local megDiv = 1048576
    -- local megMulti = vmStats.pageSize / megDiv

    -- local totalMegs = vmStats.memSize / megDiv  --总内存
    -- local megsCached = vmStats.fileBackedPages * megMulti   --缓存内存
    -- local freeMegs = vmStats.pagesFree * megMulti   --空闲内存

    -- --第一种方法使用 APP内存+联动内存+被压缩内存 = 已使用内存
    -- --local megsUsed =  vmStats.pagesWiredDown * megMulti -- 联动内存
    -- --megsUsed = megsUsed + vmStats.pagesUsedByVMCompressor * megMulti -- 被压缩内存
    -- --megsUsed = megsUsed + (vmStats.pagesActive +vmStats.pagesSpeculative)* megMulti  -- APP内存

    -- --第二种方法使用 总内存-缓存内存-空闲内存 = 已使用内存
    -- local megsUsed = totalMegs - megsCached - freeMegs

    --第三种方法,由于部分设备pageSize获取不正确,所以只能通过已使用页数+缓存页数+空闲页数计算总页数
    local megsUsed =  vmStats.pagesWiredDown -- 联动内存
    megsUsed = megsUsed + vmStats.pagesUsedByVMCompressor -- 被压缩内存
    megsUsed = megsUsed + vmStats.pagesActive +vmStats.pagesSpeculative -- APP内存

    local megsCached = vmStats.fileBackedPages   --缓存内存
    local freeMegs = vmStats.pagesFree   --空闲内存

    local totalMegs = megsUsed + megsCached + freeMegs

    local usedMem = megsUsed/totalMegs * 100
    return formatPercent(usedMem)
end

function getRootVolumes()

    local vols = hs.fs.volume.allVolumes()
    for key, vol in pairs(vols) do
        local size = vol.NSURLVolumeTotalCapacityKey
        local free = vol.NSURLVolumeAvailableCapacityKey
        local usedSSD = (1-free/size) * 100
        if ( string.find(vol.NSURLVolumeNameKey,'Macintosh') ~= nil) then
            return formatPercent(usedSSD)
        end
    end
    return ' 0%'
end

function formatPercent(percent)

    if ( percent <= 0 ) then
        return "  1%"
    elseif ( percent < 10 ) then
        return "  " .. string.format("%.f", percent) .. "%"
    elseif  (percent > 99 )then
        return "100%"
    else
        return string.format("%.f", percent) .. "%"
    end
end

local setSysInfo= function()


--    if config ~=nil and config[1].showSysInfo ~= 'on' then
    if 1 then
    
        if(menuBarItem ~= nil and menuBarItem:isInMenuBar() == false) then
       
            return
        end
        if (menuBarItem == nil) then
        
            print("设置状态栏:系统信息")
            menuBarItem= hs.menubar.new()
        elseif (menuBarItem:isInMenuBar() == false) then
            menuBarItem:delete()
            menuBarItem= hs.menubar.new()
        end
        init()
        scan()
        if obj.timer then
            obj.timer:stop()
            obj.timer = nil
        end
        -- 三秒刷新一次
        obj.timer = hs.timer.doEvery(3, scan):start()
    end
end


function initData()
    setSysInfo()
    --监听系统信息开关的状态,判断是否要重置
    hs.timer.doEvery(1, setSysInfo)
end

-- 初始化
initData()
相关推荐
懒大王爱吃狼37 分钟前
Python教程:python枚举类定义和使用
开发语言·前端·javascript·python·python基础·python编程·python书籍
小牛itbull2 小时前
ReactPress:重塑内容管理的未来
react.js·github·reactpress
秃头佛爷2 小时前
Python学习大纲总结及注意事项
开发语言·python·学习
待磨的钝刨2 小时前
【格式化查看JSON文件】coco的json文件内容都在一行如何按照json格式查看
开发语言·javascript·json
XiaoLeisj4 小时前
【JavaEE初阶 — 多线程】单例模式 & 指令重排序问题
java·开发语言·java-ee
励志成为嵌入式工程师5 小时前
c语言简单编程练习9
c语言·开发语言·算法·vim
捕鲸叉5 小时前
创建线程时传递参数给线程
开发语言·c++·算法
A charmer5 小时前
【C++】vector 类深度解析:探索动态数组的奥秘
开发语言·c++·算法
Peter_chq5 小时前
【操作系统】基于环形队列的生产消费模型
linux·c语言·开发语言·c++·后端
记录成长java7 小时前
ServletContext,Cookie,HttpSession的使用
java·开发语言·servlet