Compare commits
6 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8242a64a5d | ||
|
|
355cf0ded1 | ||
|
|
fa5551f272 | ||
|
|
b6eaa8d3c4 | ||
|
|
1af81e5b4a | ||
|
|
05714ef69e |
19
CHANGELOG.md
Normal file
@@ -0,0 +1,19 @@
|
||||
# Changelog
|
||||
All notable changes to this project will be documented in this file.
|
||||
|
||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||
and this project does adhere to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||
|
||||
|
||||
## [1.0.1] – 2026-01-28
|
||||
Fixed:
|
||||
- Crash on macOS 10.13 if path contains space character
|
||||
- Larger status icon glyph
|
||||
|
||||
|
||||
## [1.0.0] – 2026-01-27
|
||||
Initial release
|
||||
|
||||
|
||||
[1.0.1]: https://github.com/relikd/Menuscript/compare/v1.0.0...v1.0.1
|
||||
[1.0.0]: https://github.com/relikd/Menuscript/compare/1eca425c5f453bc0ed47f780d491656549d3ab53...v1.0.0
|
||||
9
Makefile
@@ -11,7 +11,7 @@ HAS_SIGN_IDENTITY=$(shell security find-identity -v -p codesigning | grep -q "Ap
|
||||
|
||||
|
||||
Menuscript.app: SDK_PATH=$(shell xcrun --show-sdk-path --sdk macosx)
|
||||
Menuscript.app: src/* examples/*
|
||||
Menuscript.app: src/* res/**
|
||||
@mkdir -p Menuscript.app/Contents/MacOS/
|
||||
swiftc ${CFLAGS} src/main.swift -target x86_64-apple-macos10.13 \
|
||||
-emit-executable -sdk ${SDK_PATH} -o bin_x64
|
||||
@@ -20,11 +20,10 @@ Menuscript.app: src/* examples/*
|
||||
lipo -create bin_x64 bin_arm64 -o Menuscript.app/Contents/MacOS/Menuscript
|
||||
@rm bin_x64 bin_arm64
|
||||
@echo 'APPL????' > Menuscript.app/Contents/PkgInfo
|
||||
@mkdir -p Menuscript.app/Contents/Resources/
|
||||
@cp src/AppIcon.icns Menuscript.app/Contents/Resources/AppIcon.icns
|
||||
@rm -rf Menuscript.app/Contents/Resources/examples/
|
||||
@cp -R examples/ Menuscript.app/Contents/Resources/examples/
|
||||
@cp src/Info.plist Menuscript.app/Contents/Info.plist
|
||||
@find res -name .DS_Store -delete
|
||||
@rm -rf Menuscript.app/Contents/Resources/
|
||||
@cp -R res/ Menuscript.app/Contents/Resources/
|
||||
@touch Menuscript.app
|
||||
@echo
|
||||
ifeq ($(HAS_SIGN_IDENTITY),1)
|
||||
|
||||
@@ -12,7 +12,7 @@ A menu bar script executor.
|
||||
|
||||
Menuscript adds a status bar menu to call custom (user defined) scripts.
|
||||
The app reads the content of a directory and adds all executable files to the status menu.
|
||||
The screenshot above represents the content of the [examples](examples/) directory.
|
||||
The screenshot above represents the content of the [res/examples](res/examples/) directory.
|
||||
|
||||
|
||||
## Usage
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
<rect id="blue" x="500" width="600" height="470" fill="url(#lg2)"/>
|
||||
<rect id="blue_line" x="500" y="470" width="600" height="30" fill="#2847C5"/>
|
||||
<g transform="translate(562.5,62)scale(0.35)">
|
||||
<path id="_x2318_" d="M335,335m-145,0a145,145,0,1,1,145,-145v620a145,145,0,1,1,-145,-145h620a145,145,0,1,1,-145,145v-620a145,145,0,1,1,145,145Z" stroke="#fff" stroke-width="90" fill="transparent"/>
|
||||
<path id="_x2318_" d="M335,335m-145,0a145,145,0,1,1,145,-145v620a145,145,0,1,1,-145,-145h620a145,145,0,1,1,-145,145v-620a145,145,0,1,1,145,145Z" stroke="#fff" stroke-width="90" fill="none"/>
|
||||
</g>
|
||||
<text x="75" y="840">run.sh</text>
|
||||
</g>
|
||||
|
||||
|
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.3 KiB |
@@ -21,7 +21,7 @@
|
||||
<rect id="blue" x="512" width="402" height="331" fill="url(#lg2)"/>
|
||||
<rect id="blue_line" x="512" y="331" width="402" height="20" fill="#2847C5"/>
|
||||
<g transform="translate(587,40) scale(0.251)">
|
||||
<path id="_x2318_" d="M335,335m-145,0a145,145,0,1,1,145,-145v620a145,145,0,1,1,-145,-145h620a145,145,0,1,1,-145,145v-620a145,145,0,1,1,145,145Z" stroke="#fff" stroke-width="90" fill="transparent"/>
|
||||
<path id="_x2318_" d="M335,335m-145,0a145,145,0,1,1,145,-145v620a145,145,0,1,1,-145,-145h620a145,145,0,1,1,-145,145v-620a145,145,0,1,1,145,145Z" stroke="#fff" stroke-width="90" fill="none"/>
|
||||
</g>
|
||||
<text x="72" y="590">run.sh</text>
|
||||
<rect id="sep" y="672" width="1024" height="20" fill="#ccc"/>
|
||||
|
||||
|
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.5 KiB |
|
Before Width: | Height: | Size: 214 B After Width: | Height: | Size: 214 B |
3
res/status.svg
Normal file
@@ -0,0 +1,3 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1000 1000">
|
||||
<path id="_x2318_" d="M335,335m-145,0a145,145,0,1,1,145,-145v620a145,145,0,1,1,-145,-145h620a145,145,0,1,1,-145,145v-620a145,145,0,1,1,145,145Z" stroke="black" stroke-width="90" fill="none"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 263 B |
@@ -15,9 +15,9 @@
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>1.0.0</string>
|
||||
<string>1.0.1</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1</string>
|
||||
<string>2</string>
|
||||
<key>LSMinimumSystemVersion</key>
|
||||
<string>10.13</string>
|
||||
<key>LSBackgroundOnly</key>
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
#!/usr/bin/env swift
|
||||
import AppKit
|
||||
import Cocoa
|
||||
import SwiftUI
|
||||
|
||||
class FlippedView: NSView {
|
||||
override var isFlipped: Bool { true }
|
||||
@@ -21,12 +20,22 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSMenuDelegate {
|
||||
|
||||
private func initStatusIcon() {
|
||||
self.statusItem = NSStatusBar.system.statusItem(withLength: NSStatusItem.variableLength)
|
||||
self.statusItem.button?.title = "⌘"
|
||||
// self.statusItem.button?.image = NSImage.statusIcon
|
||||
if let img = statusIcon() {
|
||||
self.statusItem.button?.image = img
|
||||
} else {
|
||||
self.statusItem.button?.title = "⌘" // cant load svg (<10.15)
|
||||
}
|
||||
self.statusItem.menu = NSMenu(title: resolvedStorageURL().path)
|
||||
self.statusItem.menu?.delegate = self
|
||||
}
|
||||
|
||||
private func statusIcon() -> NSImage? {
|
||||
let img = NSImage(contentsOf: resFile("status", "svg"))
|
||||
img?.isTemplate = true
|
||||
img?.size = NSMakeSize(14, 14)
|
||||
return img
|
||||
}
|
||||
|
||||
func menuDidClose(_ menu: NSMenu) {
|
||||
if menu == self.statusItem.menu {
|
||||
self.statusItem.menu = NSMenu(title: menu.title)
|
||||
@@ -67,17 +76,19 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSMenuDelegate {
|
||||
(sender.representedObject as! Entry).run()
|
||||
}
|
||||
|
||||
// MARK: - Helper
|
||||
|
||||
private func resFile(_ name: String, _ ext: String?) -> URL {
|
||||
// if run via .app bundle
|
||||
return Bundle.main.url(forResource: name, withExtension: ext)
|
||||
// if calling swift directly
|
||||
?? URL(fileURLWithPath: #file + "/../../res/" + name + (ext == nil ? "" : ("." + ext!)))
|
||||
}
|
||||
|
||||
// MARK: - Manage storage path
|
||||
|
||||
private func resolvedStorageURL() -> URL {
|
||||
userStorageURL()
|
||||
// if run via .app bundle
|
||||
?? Bundle.main.url(forResource: "examples", withExtension: nil)
|
||||
// if calling swift directly
|
||||
?? URL(string: "file://" + FileManager.default.currentDirectoryPath + "/" + #file)!
|
||||
.deletingLastPathComponent()
|
||||
.deletingLastPathComponent()
|
||||
.appendingPathComponent("examples")
|
||||
userStorageURL() ?? resFile("examples", nil)
|
||||
}
|
||||
|
||||
private func userStorageURL() -> URL? {
|
||||
@@ -205,7 +216,7 @@ struct Entry {
|
||||
var rv: [Entry] = []
|
||||
for url
|
||||
in (try? FileManager.default.contentsOfDirectory(
|
||||
at: URL(string: path)!,
|
||||
at: URL(fileURLWithPath: path),
|
||||
includingPropertiesForKeys: [.isDirectoryKey, .isExecutableKey])) ?? []
|
||||
{
|
||||
if url.hasDirectoryPath || FileManager.default.isExecutableFile(atPath: url.path) {
|
||||
@@ -267,7 +278,7 @@ struct Entry {
|
||||
}
|
||||
}
|
||||
|
||||
extension Entry : Comparable {
|
||||
extension Entry: Comparable {
|
||||
static func < (lhs: Entry, rhs: Entry) -> Bool {
|
||||
return (lhs.order, lhs.title) < (rhs.order, rhs.title)
|
||||
}
|
||||
|
||||