Compare commits
3 Commits
7868bdc6b7
..
main
| Author | SHA1 | Date | |
|---|---|---|---|
| fd17d81cb9 | |||
| de5f09da95 | |||
| e970b7b04b |
@@ -0,0 +1,8 @@
|
||||
---
|
||||
alwaysApply: true
|
||||
scene: git_message
|
||||
---
|
||||
|
||||
한글로 작성
|
||||
맨위에 한줄요약으로 시작
|
||||
그 아래에 메시지 작성
|
||||
@@ -0,0 +1,113 @@
|
||||
--- === PicsumRandom === -- Lorem Picsum 기반으로 랜덤 배경화면을 적용하는 Spoon 이름을 선언합니다.
|
||||
--- -- Spoon 설명 헤더 구분선입니다.
|
||||
--- Automatically sets a random Lorem Picsum image as your wallpaper periodically. -- Spoon 동작 설명을 문서 헤더에 남깁니다.
|
||||
--- -- Spoon 설명 헤더 구분선입니다.
|
||||
--- Local custom Spoon for Hammerspoon. -- 로컬 사용자 정의 Spoon임을 문서 헤더에 남깁니다.
|
||||
|
||||
local obj = {} -- Spoon 객체 테이블을 생성합니다.
|
||||
obj.__index = obj -- 메서드 조회를 위해 자기 자신을 메타테이블 인덱스로 지정합니다.
|
||||
|
||||
obj.name = "PicsumRandom" -- Spoon 이름을 정의합니다.
|
||||
obj.version = "1.0" -- Spoon 버전을 정의합니다.
|
||||
obj.author = "OpenAI" -- 현재 로컬 Spoon 작성자를 기록합니다.
|
||||
obj.homepage = "https://picsum.photos/" -- 사용 중인 오픈소스 이미지 서비스 홈페이지를 기록합니다.
|
||||
obj.license = "MIT" -- 로컬 Spoon 라이선스 표기를 남깁니다.
|
||||
|
||||
obj.maxPixelDimension = 4096 -- Picsum이 안정적으로 처리할 수 있도록 요청 최대 한 변 길이를 제한합니다.
|
||||
obj.refreshIntervalSeconds = 3 * 60 * 60 -- 배경화면 자동 갱신 주기를 3시간으로 설정합니다.
|
||||
obj.firstRefreshDelaySeconds = 5 -- 설정 로드 후 첫 갱신까지의 지연 시간을 5초로 설정합니다.
|
||||
obj.cacheRootDirectory = hs.configdir .. "/cache" -- 다운로드 캐시의 상위 디렉터리 경로를 정의합니다.
|
||||
obj.cacheDirectory = hs.configdir .. "/cache/PicsumRandom" -- 다운로드 이미지를 저장할 캐시 디렉터리 경로를 정의합니다.
|
||||
obj.currentDownloadPath = nil -- 현재 다운로드 대상 파일 경로를 저장할 변수를 초기화합니다.
|
||||
obj.task = nil -- 현재 실행 중인 다운로드 태스크를 저장할 변수를 초기화합니다.
|
||||
obj.timer = nil -- 주기 실행 타이머 객체를 저장할 변수를 초기화합니다.
|
||||
|
||||
local function ensureCacheDirectory() -- 캐시 디렉터리가 없으면 생성하는 보조 함수를 정의합니다.
|
||||
if hs.fs.attributes(obj.cacheRootDirectory) == nil then -- 상위 cache 디렉터리 존재 여부를 먼저 확인합니다.
|
||||
hs.fs.mkdir(obj.cacheRootDirectory) -- 상위 cache 디렉터리가 없을 때 먼저 생성합니다.
|
||||
end -- 상위 cache 디렉터리 생성 분기를 마칩니다.
|
||||
if hs.fs.attributes(obj.cacheDirectory) == nil then -- 캐시 디렉터리 존재 여부를 먼저 확인합니다.
|
||||
hs.fs.mkdir(obj.cacheDirectory) -- 캐시 디렉터리가 없을 때 생성합니다.
|
||||
end -- 캐시 디렉터리 생성 분기를 마칩니다.
|
||||
end -- 캐시 디렉터리 보장 함수 정의를 마칩니다.
|
||||
|
||||
local function buildImageRequest() -- 현재 메인 화면 크기에 맞는 Picsum 요청 정보를 생성하는 함수를 정의합니다.
|
||||
local screenObject = hs.screen.mainScreen() -- 현재 메인 화면 객체를 가져옵니다.
|
||||
local screenMode = screenObject:currentMode() -- 메인 화면의 현재 해상도와 배율 정보를 읽습니다.
|
||||
local rawPixelWidth = math.floor(screenMode.w * screenMode.scale) -- 실제 픽셀 기준 원본 가로 길이를 계산합니다.
|
||||
local rawPixelHeight = math.floor(screenMode.h * screenMode.scale) -- 실제 픽셀 기준 원본 세로 길이를 계산합니다.
|
||||
local maxDimension = math.max(rawPixelWidth, rawPixelHeight) -- 원본 해상도에서 가장 긴 한 변 길이를 계산합니다.
|
||||
local resizeRatio = 1 -- 기본적으로는 축소 없이 원본 비율을 유지하도록 배율을 초기화합니다.
|
||||
if maxDimension > obj.maxPixelDimension then -- 요청 크기가 허용 상한을 넘는 경우를 처리합니다.
|
||||
resizeRatio = obj.maxPixelDimension / maxDimension -- 가장 긴 변이 상한에 맞도록 축소 배율을 계산합니다.
|
||||
end -- 요청 크기 상한 초과 여부 분기를 마칩니다.
|
||||
local pixelWidth = math.max(1, math.floor(rawPixelWidth * resizeRatio)) -- 축소 배율을 반영한 최종 가로 길이를 계산합니다.
|
||||
local pixelHeight = math.max(1, math.floor(rawPixelHeight * resizeRatio)) -- 축소 배율을 반영한 최종 세로 길이를 계산합니다.
|
||||
local seedValue = tostring(hs.timer.absoluteTime()) -- 매번 다른 이미지를 받기 위해 현재 시간을 문자열 시드로 변환합니다.
|
||||
local imageUrl = "https://picsum.photos/seed/" .. seedValue .. "/" .. tostring(pixelWidth) .. "/" .. tostring(pixelHeight) .. ".jpg" -- 화면 크기와 시드를 반영한 Picsum 이미지 URL을 생성합니다.
|
||||
local filePath = obj.cacheDirectory .. "/wallpaper-" .. seedValue .. ".jpg" -- macOS 캐시를 피하기 위해 매 요청마다 고유한 저장 경로를 생성합니다.
|
||||
return screenObject, imageUrl, filePath -- 화면 객체와 이미지 URL과 저장 경로를 함께 반환합니다.
|
||||
end -- 이미지 요청 정보 생성 함수 정의를 마칩니다.
|
||||
|
||||
local function applyDownloadedWallpaper() -- 다운로드된 이미지를 배경화면으로 적용하는 보조 함수를 정의합니다.
|
||||
if obj.currentDownloadPath == nil then -- 현재 다운로드 파일 경로가 없는 비정상 상태를 먼저 처리합니다.
|
||||
hs.printf("PicsumRandom: download path is missing") -- 디버깅을 위해 경로 누락 상태를 콘솔에 기록합니다.
|
||||
return -- 적용할 파일이 없으므로 함수를 종료합니다.
|
||||
end -- 다운로드 경로 존재 여부 검사 분기를 마칩니다.
|
||||
if hs.fs.attributes(obj.currentDownloadPath) == nil then -- 파일이 실제로 존재하는지 다시 확인합니다.
|
||||
hs.printf("PicsumRandom: downloaded file not found at %s", obj.currentDownloadPath) -- 누락된 파일 경로를 콘솔에 기록합니다.
|
||||
return -- 파일이 없으면 배경화면 적용을 중단합니다.
|
||||
end -- 파일 존재 여부 검사 분기를 마칩니다.
|
||||
hs.screen.mainScreen():desktopImageURL("file://" .. obj.currentDownloadPath) -- 다운로드된 이미지를 현재 메인 화면의 배경화면으로 적용합니다.
|
||||
end -- 배경화면 적용 함수 정의를 마칩니다.
|
||||
|
||||
local function downloadCallback(exitCode, standardOutput, standardError) -- 다운로드 태스크 완료 후 호출될 콜백 함수를 정의합니다.
|
||||
obj.task = nil -- 다운로드 완료 시 실행 중 태스크 참조를 먼저 정리합니다.
|
||||
if exitCode == 0 then -- curl 실행이 성공한 경우를 처리합니다.
|
||||
applyDownloadedWallpaper() -- 성공적으로 저장된 이미지를 배경화면으로 적용합니다.
|
||||
else -- curl 실행이 실패한 경우를 처리합니다.
|
||||
hs.printf("PicsumRandom download failed: %s %s", tostring(standardOutput), tostring(standardError)) -- 실패 원인을 콘솔에 기록합니다.
|
||||
end -- 다운로드 성공 여부 분기를 마칩니다.
|
||||
end -- 다운로드 완료 콜백 함수 정의를 마칩니다.
|
||||
|
||||
function obj:refresh() -- 새 랜덤 이미지를 즉시 받아 적용하는 공개 메서드를 정의합니다.
|
||||
ensureCacheDirectory() -- 다운로드 전에 캐시 디렉터리가 준비되도록 보장합니다.
|
||||
if self.task ~= nil then -- 기존 다운로드 태스크가 아직 실행 중인 경우를 처리합니다.
|
||||
self.task:terminate() -- 중복 다운로드를 막기 위해 이전 태스크를 종료합니다.
|
||||
self.task = nil -- 종료한 이전 태스크 참조를 정리합니다.
|
||||
end -- 중복 다운로드 방지 분기를 마칩니다.
|
||||
local _, imageUrl, filePath = buildImageRequest() -- 현재 화면에 맞는 이미지 URL과 저장 경로를 계산합니다.
|
||||
self.currentDownloadPath = filePath -- 이번 다운로드의 저장 경로를 객체 상태에 보관합니다.
|
||||
self.task = hs.task.new("/usr/bin/curl", downloadCallback, { "-L", "-f", "-sS", imageUrl, "-o", filePath }) -- 실패를 감지할 수 있도록 curl 다운로드 태스크를 생성합니다.
|
||||
if self.task == nil then -- 태스크 생성 자체가 실패한 경우를 처리합니다.
|
||||
hs.printf("PicsumRandom: failed to create curl task") -- 태스크 생성 실패를 콘솔에 기록합니다.
|
||||
return -- 더 진행할 수 없으므로 함수를 종료합니다.
|
||||
end -- 태스크 생성 성공 여부 분기를 마칩니다.
|
||||
self.task:start() -- 생성된 다운로드 태스크를 즉시 시작합니다.
|
||||
end -- 수동 새로고침 메서드 정의를 마칩니다.
|
||||
|
||||
function obj:start() -- 주기적 랜덤 배경화면 갱신을 시작하는 메서드를 정의합니다.
|
||||
ensureCacheDirectory() -- 시작 전에 캐시 디렉터리가 존재하도록 보장합니다.
|
||||
if self.timer == nil then -- 아직 타이머가 만들어지지 않은 첫 시작 상황을 처리합니다.
|
||||
self.timer = hs.timer.doEvery(self.refreshIntervalSeconds, function() self:refresh() end) -- 설정한 주기마다 새 배경화면을 받는 타이머를 생성합니다.
|
||||
else -- 이미 타이머가 존재하는 경우를 처리합니다.
|
||||
self.timer:start() -- 기존 타이머를 다시 시작합니다.
|
||||
end -- 타이머 생성 여부 분기를 마칩니다.
|
||||
self.timer:setNextTrigger(self.firstRefreshDelaySeconds) -- 첫 배경화면 갱신 시점을 짧게 앞당겨 설정합니다.
|
||||
end -- 자동 갱신 시작 메서드 정의를 마칩니다.
|
||||
|
||||
function obj:stop() -- 자동 갱신을 중단하는 메서드를 정의합니다.
|
||||
if self.timer ~= nil then -- 생성된 타이머가 있는 경우만 처리합니다.
|
||||
self.timer:stop() -- 주기 실행 타이머를 중지합니다.
|
||||
end -- 타이머 중지 분기를 마칩니다.
|
||||
if self.task ~= nil then -- 실행 중인 다운로드 태스크가 있는 경우를 처리합니다.
|
||||
self.task:terminate() -- 진행 중 다운로드를 안전하게 중단합니다.
|
||||
self.task = nil -- 종료한 태스크 참조를 정리합니다.
|
||||
end -- 다운로드 태스크 정리 분기를 마칩니다.
|
||||
end -- 자동 갱신 중지 메서드 정의를 마칩니다.
|
||||
|
||||
function obj:init() -- Spoon 로드 직후 초기화 메서드를 정의합니다.
|
||||
self:start() -- Spoon이 로드되면 자동 갱신을 바로 시작합니다.
|
||||
end -- Spoon 초기화 메서드 정의를 마칩니다.
|
||||
|
||||
return obj -- 완성된 Spoon 객체를 반환합니다.
|
||||
Vendored
BIN
Binary file not shown.
|
After Width: | Height: | Size: 283 KiB |
BIN
Binary file not shown.
|
After Width: | Height: | Size: 936 KiB |
BIN
Binary file not shown.
|
After Width: | Height: | Size: 214 KiB |
BIN
Binary file not shown.
|
After Width: | Height: | Size: 531 KiB |
BIN
Binary file not shown.
|
After Width: | Height: | Size: 118 KiB |
BIN
Binary file not shown.
|
After Width: | Height: | Size: 558 KiB |
@@ -188,6 +188,122 @@ hs.keycodes.inputSourceChanged(function() -- 입력기 전환이 일어날 때
|
||||
showInputSourceHud() -- 한글과 영문 전환 결과에 맞는 중앙 표시를 즉시 띄웁니다.
|
||||
end) -- 입력기 변경 콜백 등록을 마칩니다.
|
||||
|
||||
-- `cmd`+`b`로 클립보드 문자열에서 하이픈을 제거한 뒤 연속 자동 입력하는 기능 설정을 시작합니다.
|
||||
local clipboardTypeHotkeyModifiers = { "cmd" } -- 자동 입력 기능에 사용할 수정 키 조합을 정의합니다.
|
||||
local clipboardTypeHotkeyKey = "b" -- 자동 입력 기능에 사용할 기본 키를 정의합니다.
|
||||
local clipboardTypeInterval = 0.12 -- 각 문자 입력 사이에 둘 짧은 지연 시간을 초 단위로 정의합니다.
|
||||
local clipboardTypingInProgress = false -- 자동 입력이 이미 진행 중인지 추적해 중복 실행을 막습니다.
|
||||
local clipboardTypeHotkey = nil -- 충돌 검사 후 실제로 바인딩된 단축키 객체를 저장합니다.
|
||||
|
||||
-- 문자열의 각 문자를 순서대로 담은 큐 테이블을 만드는 함수를 정의합니다.
|
||||
local function buildCharacterQueue(text) -- 하이픈 제거 후 남은 모든 문자를 순차 전송하기 위한 준비 함수입니다.
|
||||
local queue = {} -- 순서대로 전송할 문자 목록을 빈 테이블로 초기화합니다.
|
||||
for _, codepoint in utf8.codes(text) do -- UTF-8 문자열을 코드포인트 단위로 안전하게 순회합니다.
|
||||
queue[#queue + 1] = utf8.char(codepoint) -- 읽어온 문자를 그대로 큐 뒤에 추가합니다.
|
||||
end -- 문자열 전체를 큐로 변환하는 반복을 마칩니다.
|
||||
return queue -- 완성된 문자 큐를 호출한 곳에 반환합니다.
|
||||
end -- 문자 큐 생성 함수 정의를 마칩니다.
|
||||
|
||||
-- 현재 환경에서 자동 키 입력을 수행할 수 있는지 선검사하는 함수를 정의합니다.
|
||||
local function ensureClipboardTypingPrerequisites() -- 권한과 보안 입력 상태를 미리 확인해 실패를 줄입니다.
|
||||
if not hs.accessibilityState() then -- 손쉬운 사용 권한이 없으면 키 이벤트 전송이 불가능하므로 먼저 처리합니다.
|
||||
hs.accessibilityState(true) -- macOS 권한 허용 안내를 띄워 사용자가 바로 승인할 수 있게 돕습니다.
|
||||
hs.alert.show("Hammerspoon 손쉬운 사용 권한이 필요합니다") -- 권한 필요 안내를 화면에 표시합니다.
|
||||
return false -- 아직 자동 입력을 진행할 수 없으므로 실패를 반환합니다.
|
||||
end -- 손쉬운 사용 권한 검사 분기 종료입니다.
|
||||
|
||||
if hs.eventtap.isSecureInputEnabled() then -- 보안 입력이 활성화된 앱에서는 키 이벤트 주입이 막힐 수 있으므로 점검합니다.
|
||||
hs.alert.show("보안 입력이 켜져 있어 자동 입력을 실행할 수 없습니다") -- 현재 상태를 사용자에게 즉시 알립니다.
|
||||
return false -- 안전하지 않은 상태에서는 자동 입력을 중단합니다.
|
||||
end -- 보안 입력 상태 검사 분기 종료입니다.
|
||||
|
||||
return true -- 필요한 선행 조건이 모두 충족됐음을 반환합니다.
|
||||
end -- 자동 입력 선행 조건 검사 함수 정의를 마칩니다.
|
||||
|
||||
-- 한 글자를 현재 포커스된 앱으로 전송하는 함수를 정의합니다.
|
||||
local function postClipboardCharacter(character) -- 남아 있는 문자를 현재 포커스된 앱에 한 글자씩 안전하게 전송합니다.
|
||||
hs.eventtap.keyStrokes(character, 0) -- 현재 포커스된 앱에 해당 문자를 한 글자씩 전달합니다.
|
||||
end -- 단일 문자 전송 함수 정의를 마칩니다.
|
||||
|
||||
-- 문자 큐를 타이머 기반으로 순차 입력하는 함수를 정의합니다.
|
||||
local function typeClipboardQueue(queue, index) -- 긴 입력 중에도 설정 전체가 멈추지 않도록 비동기식으로 처리합니다.
|
||||
if not clipboardTypingInProgress then -- 외부 오류나 상태 변경으로 이미 종료됐다면 즉시 빠져나옵니다.
|
||||
return -- 종료된 작업을 더 진행하지 않도록 여기서 함수를 마칩니다.
|
||||
end -- 실행 상태 검사 분기 종료입니다.
|
||||
|
||||
if index > #queue then -- 마지막 문자까지 모두 전송했다면 정상 완료 처리를 진행합니다.
|
||||
clipboardTypingInProgress = false -- 다음 실행을 위해 진행 중 상태를 해제합니다.
|
||||
return -- 더 이상 전송할 문자가 없으므로 함수를 종료합니다.
|
||||
end -- 입력 완료 여부 검사 분기 종료입니다.
|
||||
|
||||
local ok, errorMessage = pcall(postClipboardCharacter, queue[index]) -- 현재 문자를 안전하게 전송하고 예외를 가로챕니다.
|
||||
if not ok then -- 문자 전송 중 런타임 오류가 발생한 경우를 처리합니다.
|
||||
clipboardTypingInProgress = false -- 오류 발생 시에도 다음 실행을 위해 상태를 정상적으로 복구합니다.
|
||||
hs.alert.show("자동 입력 중 오류가 발생했습니다") -- 사용자에게 실패 사실을 화면으로 알려줍니다.
|
||||
hs.printf("Clipboard typing failed: %s", tostring(errorMessage)) -- 디버깅을 위해 콘솔에 구체적인 오류를 기록합니다.
|
||||
return -- 오류 이후 추가 입력이 이어지지 않도록 즉시 종료합니다.
|
||||
end -- 문자 전송 예외 처리 분기 종료입니다.
|
||||
|
||||
hs.timer.doAfter(clipboardTypeInterval, function() -- 다음 문자 입력을 짧은 지연 뒤 예약해 앱이 입력을 안정적으로 받게 합니다.
|
||||
typeClipboardQueue(queue, index + 1) -- 다음 위치의 문자를 계속 순차적으로 전송합니다.
|
||||
end) -- 다음 문자 예약 콜백 정의를 마칩니다.
|
||||
end -- 문자 큐 순차 입력 함수 정의를 마칩니다.
|
||||
|
||||
-- 클립보드 내용을 읽어 하이픈 제거 후 연속 자동 입력 작업을 시작하는 함수를 정의합니다.
|
||||
local function typeClipboardAsContinuousSequence() -- 실제 단축키가 눌렸을 때 호출될 메인 작업 함수입니다.
|
||||
if clipboardTypingInProgress then -- 이전 자동 입력이 아직 끝나지 않았다면 중복 실행을 막습니다.
|
||||
hs.alert.show("자동 입력이 이미 진행 중입니다") -- 재진입이 거부된 이유를 사용자에게 알려줍니다.
|
||||
return -- 중복 실행은 허용하지 않고 함수를 종료합니다.
|
||||
end -- 재진입 방지 분기 종료입니다.
|
||||
|
||||
if not ensureClipboardTypingPrerequisites() then -- 권한이나 보안 입력 상태가 적절한지 먼저 확인합니다.
|
||||
return -- 선행 조건이 맞지 않으면 작업을 시작하지 않습니다.
|
||||
end -- 선행 조건 검사 분기 종료입니다.
|
||||
|
||||
local clipboardReadOk, clipboardText = pcall(hs.pasteboard.getContents) -- 클립보드 문자열 읽기를 예외 안전하게 시도합니다.
|
||||
if not clipboardReadOk then -- 클립보드 접근 자체에서 오류가 발생한 경우를 처리합니다.
|
||||
hs.alert.show("클립보드 내용을 읽는 중 오류가 발생했습니다") -- 읽기 실패를 사용자에게 알립니다.
|
||||
hs.printf("Clipboard read failed: %s", tostring(clipboardText)) -- 콘솔에 구체적인 오류 정보를 남깁니다.
|
||||
return -- 읽기에 실패했으므로 자동 입력을 시작하지 않습니다.
|
||||
end -- 클립보드 읽기 예외 처리 분기 종료입니다.
|
||||
|
||||
if type(clipboardText) ~= "string" or clipboardText == "" then -- 빈 문자열이거나 문자열이 아닌 경우는 유효한 입력 원본이 아닙니다.
|
||||
hs.alert.show("클립보드에 입력할 텍스트가 없습니다") -- 사용자가 먼저 텍스트를 복사하도록 안내합니다.
|
||||
return -- 유효한 내용이 없으므로 여기서 종료합니다.
|
||||
end -- 클립보드 내용 유효성 검사 분기 종료입니다.
|
||||
|
||||
local transformedText = clipboardText:gsub("%-", "") -- 자동 포커스 이동을 활용할 수 있도록 모든 하이픈을 제거합니다.
|
||||
local queue = buildCharacterQueue(transformedText) -- 하이픈이 제거된 문자열을 문자 단위 큐로 만들어 순차 입력 준비를 합니다.
|
||||
if #queue == 0 then -- 하이픈 제거 후 결과가 실질적으로 비어 있으면 입력할 것이 없으므로 막습니다.
|
||||
hs.alert.show("하이픈 제거 후 입력할 문자가 없습니다") -- 의미 없는 실행이 되지 않도록 사용자에게 알려줍니다.
|
||||
return -- 입력 큐가 비어 있으므로 종료합니다.
|
||||
end -- 하이픈 제거 결과 유효성 검사 분기 종료입니다.
|
||||
|
||||
clipboardTypingInProgress = true -- 실제 입력을 시작하기 전에 진행 중 상태를 활성화합니다.
|
||||
local typingStartOk, typingStartError = pcall(typeClipboardQueue, queue, 1) -- 순차 입력 시작 자체도 예외 안전하게 감쌉니다.
|
||||
if not typingStartOk then -- 시작 단계에서 예상치 못한 오류가 발생한 경우를 처리합니다.
|
||||
clipboardTypingInProgress = false -- 시작 실패 시 진행 상태를 즉시 되돌립니다.
|
||||
hs.alert.show("자동 입력 시작에 실패했습니다") -- 사용자에게 시작 실패를 알립니다.
|
||||
hs.printf("Clipboard typing start failed: %s", tostring(typingStartError)) -- 콘솔에 실패 원인을 기록합니다.
|
||||
end -- 자동 입력 시작 예외 처리 분기 종료입니다.
|
||||
end -- 클립보드 연속 자동 입력 메인 함수 정의를 마칩니다.
|
||||
|
||||
-- 시스템 레벨에 이미 예약된 단축키와 충돌하는지 검사합니다.
|
||||
local clipboardTypeSystemConflict = hs.hotkey.systemAssigned(clipboardTypeHotkeyModifiers, clipboardTypeHotkeyKey) -- macOS가 점유한 조합이면 바인딩을 피하기 위해 조회합니다.
|
||||
if clipboardTypeSystemConflict then -- 시스템이 이미 이 단축키를 사용 중인 경우를 처리합니다.
|
||||
hs.alert.show("cmd-b 단축키가 시스템에 이미 할당되어 있어 등록하지 않았습니다") -- 충돌 사실을 화면에 알립니다.
|
||||
hs.printf("Skipped binding cmd-b due to system conflict: %s", hs.inspect(clipboardTypeSystemConflict)) -- 콘솔에 충돌 세부 정보를 남깁니다.
|
||||
else -- 시스템 충돌이 없을 때만 안전하게 단축키를 등록합니다.
|
||||
clipboardTypeHotkey = hs.hotkey.bind(clipboardTypeHotkeyModifiers, clipboardTypeHotkeyKey, function() -- 전역 단축키를 눌렀을 때 메인 작업을 실행합니다.
|
||||
local hotkeyOk, hotkeyError = pcall(typeClipboardAsContinuousSequence) -- 단축키 콜백 전체를 예외 안전하게 감싸 강제 종료를 막습니다.
|
||||
if not hotkeyOk then -- 콜백 바깥쪽에서 예상치 못한 오류가 터진 경우를 처리합니다.
|
||||
clipboardTypingInProgress = false -- 오류 뒤 다음 실행이 가능하도록 상태를 정리합니다.
|
||||
hs.alert.show("cmd-b 자동 입력 실행에 실패했습니다") -- 사용자에게 실행 실패를 알려줍니다.
|
||||
hs.printf("cmd-b clipboard hotkey failed: %s", tostring(hotkeyError)) -- 콘솔에 실제 오류 메시지를 기록합니다.
|
||||
end -- 단축키 콜백 예외 처리 분기 종료입니다.
|
||||
end) -- 전역 단축키 바인딩 정의를 마칩니다.
|
||||
end -- 시스템 단축키 충돌 여부에 따른 등록 분기를 마칩니다.
|
||||
|
||||
overrideOtherMouseDown:start() -- 보조 버튼 눌림 감시를 시작합니다.
|
||||
overrideOtherMouseUp:start() -- 보조 버튼 떼기 감시를 시작합니다.
|
||||
dragOtherToScroll:start() -- 보조 버튼 드래그 스크롤 감시를 시작합니다.
|
||||
@@ -210,3 +326,26 @@ else -- Caffeine Spoon 로드에 실패한 경우 사용자에게 원인을 알
|
||||
hs.alert.show("Caffeine.spoon 설치가 필요합니다") -- 누락된 Spoon 설치 필요 안내를 표시합니다.
|
||||
hs.printf("Failed to load Caffeine spoon: %s", tostring(caffeineError)) -- 콘솔에 로드 실패 원인을 기록합니다.
|
||||
end -- Caffeine Spoon 로드 예외 처리 분기를 마칩니다.
|
||||
|
||||
-- 공식 UnsplashRandom 대신 PicsumRandom Spoon을 로드해 다른 오픈소스 이미지 소스로 배경화면을 갱신합니다.
|
||||
local picsumRandomRefreshHotkeyModifiers = { "ctrl", "alt", "cmd" } -- 즉시 새 배경화면을 받는 단축키의 수정 키 조합을 정의합니다.
|
||||
local picsumRandomRefreshHotkeyKey = "w" -- 즉시 새 배경화면을 받는 단축키의 기본 키를 정의합니다.
|
||||
local picsumRandomRefreshHotkey = nil -- 실제로 등록된 즉시 새로고침 단축키 객체를 저장할 변수를 초기화합니다.
|
||||
|
||||
local picsumRandomLoaded, picsumRandomError = pcall(hs.loadSpoon, "PicsumRandom") -- PicsumRandom Spoon 로드와 초기화를 예외 안전하게 시도합니다.
|
||||
if picsumRandomLoaded then -- PicsumRandom Spoon 로드에 성공한 경우를 처리합니다.
|
||||
local picsumRandomRefreshSystemConflict = hs.hotkey.systemAssigned(picsumRandomRefreshHotkeyModifiers, picsumRandomRefreshHotkeyKey) -- 시스템이 같은 단축키를 이미 점유하고 있는지 먼저 확인합니다.
|
||||
if picsumRandomRefreshSystemConflict then -- 시스템 단축키 충돌이 있는 경우를 처리합니다.
|
||||
hs.alert.show("ctrl-alt-cmd-w 단축키가 시스템에 이미 할당되어 등록하지 않았습니다") -- 단축키 충돌 사실을 사용자에게 화면으로 알립니다.
|
||||
hs.printf("Skipped binding PicsumRandom refresh hotkey due to system conflict: %s", hs.inspect(picsumRandomRefreshSystemConflict)) -- 충돌 세부 정보를 콘솔에 남겨 원인 파악을 돕습니다.
|
||||
else -- 시스템 단축키 충돌이 없는 경우를 처리합니다.
|
||||
picsumRandomRefreshHotkey = hs.hotkey.bind(picsumRandomRefreshHotkeyModifiers, picsumRandomRefreshHotkeyKey, function() -- 전역 단축키를 눌렀을 때 즉시 새 배경화면 갱신을 실행합니다.
|
||||
hs.alert.show("새 배경화면을 가져오는 중입니다") -- 단축키가 정상 인식됐음을 사용자에게 즉시 알려 줍니다.
|
||||
spoon.PicsumRandom:refresh() -- 현재 화면 크기에 맞는 새 랜덤 배경화면 다운로드를 바로 시작합니다.
|
||||
end) -- 즉시 새 배경화면 갱신 단축키 바인딩 정의를 마칩니다.
|
||||
end -- 시스템 단축키 충돌 여부에 따른 등록 분기를 마칩니다.
|
||||
hs.printf("PicsumRandom spoon loaded successfully") -- 콘솔에 성공 로그를 남겨 정상 로드를 확인할 수 있게 합니다.
|
||||
else -- PicsumRandom Spoon 로드에 실패한 경우 사용자에게 원인을 알립니다.
|
||||
hs.alert.show("PicsumRandom.spoon 설치를 확인해 주세요") -- 누락되었거나 손상된 Spoon 설치 상태를 사용자에게 안내합니다.
|
||||
hs.printf("Failed to load PicsumRandom spoon: %s", tostring(picsumRandomError)) -- 콘솔에 로드 실패 원인을 기록합니다.
|
||||
end -- PicsumRandom Spoon 로드 예외 처리 분기를 마칩니다.
|
||||
|
||||
Reference in New Issue
Block a user