chponk

Pomodoro like timer for Mac OS
git clone git://git.konyahin.xyz/chponk
Log | Files | Refs | README

commit 7942399f089e769c7ed3ce520ac42c14a2c76bab
Author: Anton Konyahin <me@konyahin.xyz>
Date:   Fri, 31 Dec 2021 17:15:31 +0300

first commit

Diffstat:
A.gitignore | 5+++++
APackage.swift | 21+++++++++++++++++++++
AREADME.md | 3+++
ASources/chponk/main.swift | 80+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
ATests/LinuxMain.swift | 7+++++++
ATests/chponkTests/XCTestManifests.swift | 9+++++++++
ATests/chponkTests/chponkTests.swift | 47+++++++++++++++++++++++++++++++++++++++++++++++
7 files changed, 172 insertions(+), 0 deletions(-)

diff --git a/.gitignore b/.gitignore @@ -0,0 +1,5 @@ +.DS_Store +/.build +/Packages +/*.xcodeproj +xcuserdata/ diff --git a/Package.swift b/Package.swift @@ -0,0 +1,21 @@ +// swift-tools-version:5.3 +// The swift-tools-version declares the minimum version of Swift required to build this package. + +import PackageDescription + +let package = Package( + name: "chponk", + platforms: [ + .macOS(.v10_12) + ], + dependencies: [ + ], + targets: [ + .target( + name: "chponk", + dependencies: []), + .testTarget( + name: "chponkTests", + dependencies: ["chponk"]), + ] +) diff --git a/README.md b/README.md @@ -0,0 +1,3 @@ +# chponk + +A description of this package. diff --git a/Sources/chponk/main.swift b/Sources/chponk/main.swift @@ -0,0 +1,80 @@ +import AppKit +import Foundation + +if CommandLine.arguments.count < 2 { + print("Usage: chponk minutes [title]") + exit(0) +} +let originalTime = Int(CommandLine.arguments[1])! * 60 +var time = originalTime + +let title = CommandLine.arguments.count > 2 ? CommandLine.arguments[2] : "" + +let app = NSApplication.shared +let statusItem = NSStatusBar.system + .statusItem(withLength: NSStatusItem.variableLength) + +let menu = NSMenu() +menu.addItem( + NSMenuItem( + title: "Repeat \(formatTime(time:originalTime))", + action: #selector(app.again), + keyEquivalent: "")) +menu.addItem( + NSMenuItem( + title: "Stop", + action: #selector(app.reset), + keyEquivalent: "")) +menu.addItem( + NSMenuItem( + title: "Quit", + action: #selector(app.quit), + keyEquivalent: "")) +statusItem.menu = menu + +app.again() +app.setActivationPolicy(.prohibited) +app.run() + +extension NSApplication { + @objc func again() { + time = originalTime + startTimer() + refreshStatusBar() + } + + @objc func reset() { + time = 0 + refreshStatusBar() + } + + @objc func quit() { + exit(0) + } +} + +func refreshStatusBar() { + if (time > 0) { + statusItem.button?.title = "\(title) \(formatTime(time:time)) \u{1F3C3}" + } else { + statusItem.button?.title = "\u{1F6B6}" + } +} + +func startTimer() { + Timer.scheduledTimer(withTimeInterval: 1.0, repeats: true) { + timer in + time -= 1 + refreshStatusBar() + if (time <= 0) { + NSSound(named: NSSound.Name("Purr"))?.play() + timer.invalidate() + } + } +} + +func formatTime(time: Int) -> String { + let minutes = String(format: "%.02d", time / 60) + let seconds = String(format: "%.02d", time % 60) + return "\(minutes):\(seconds)" +} diff --git a/Tests/LinuxMain.swift b/Tests/LinuxMain.swift @@ -0,0 +1,7 @@ +import XCTest + +import chponkTests + +var tests = [XCTestCaseEntry]() +tests += chponkTests.allTests() +XCTMain(tests) diff --git a/Tests/chponkTests/XCTestManifests.swift b/Tests/chponkTests/XCTestManifests.swift @@ -0,0 +1,9 @@ +import XCTest + +#if !canImport(ObjectiveC) +public func allTests() -> [XCTestCaseEntry] { + return [ + testCase(chponkTests.allTests), + ] +} +#endif diff --git a/Tests/chponkTests/chponkTests.swift b/Tests/chponkTests/chponkTests.swift @@ -0,0 +1,47 @@ +import XCTest +import class Foundation.Bundle + +final class chponkTests: XCTestCase { + func testExample() throws { + // This is an example of a functional test case. + // Use XCTAssert and related functions to verify your tests produce the correct + // results. + + // Some of the APIs that we use below are available in macOS 10.13 and above. + guard #available(macOS 10.13, *) else { + return + } + + let fooBinary = productsDirectory.appendingPathComponent("chponk") + + let process = Process() + process.executableURL = fooBinary + + let pipe = Pipe() + process.standardOutput = pipe + + try process.run() + process.waitUntilExit() + + let data = pipe.fileHandleForReading.readDataToEndOfFile() + let output = String(data: data, encoding: .utf8) + + XCTAssertEqual(output, "Hello, world!\n") + } + + /// Returns path to the built products directory. + var productsDirectory: URL { + #if os(macOS) + for bundle in Bundle.allBundles where bundle.bundlePath.hasSuffix(".xctest") { + return bundle.bundleURL.deletingLastPathComponent() + } + fatalError("couldn't find the products directory") + #else + return Bundle.main.bundleURL + #endif + } + + static var allTests = [ + ("testExample", testExample), + ] +}