Showing preview only (960K chars total). Download the full file or copy to clipboard to get everything.
Repository: DevToys-app/DevToysMac
Branch: main
Commit: 38d416083872
Files: 282
Total size: 22.5 MB
Directory structure:
gitextract_01cekmvj/
├── .gitignore
├── CoreUtil/
│ ├── CoreUtil/
│ │ ├── Class/
│ │ │ ├── Action.swift
│ │ │ ├── Delta.swift
│ │ │ ├── NS+OnAwake.swift
│ │ │ ├── NSColorView.swift
│ │ │ ├── NSViewController+ChainObject.swift
│ │ │ ├── NSViewController+StateObject.swift
│ │ │ ├── Observable.swift
│ │ │ ├── PipeOperator.swift
│ │ │ ├── Query.swift
│ │ │ ├── Reachability+Publisher.swift
│ │ │ ├── Reachability.swift
│ │ │ ├── RestorableData.swift
│ │ │ ├── RestorableState.swift
│ │ │ ├── Terminal.swift
│ │ │ ├── ViewPlaceholder.swift
│ │ │ └── Zip3Sequence.swift
│ │ ├── CoreUtil.h
│ │ ├── ExceptionHanlder/
│ │ │ ├── ExceptionHandler.swift
│ │ │ ├── ExceptionHanlder.h
│ │ │ └── ExceptionHanlder.m
│ │ ├── Export.swift
│ │ ├── Extensions/
│ │ │ ├── Combine/
│ │ │ │ ├── Combine+ObjectBag.swift
│ │ │ │ ├── Combine+Peek.swift
│ │ │ │ ├── NSControl+Combine.swift
│ │ │ │ └── NSTextField+Combine.swift
│ │ │ ├── CoreGraphics/
│ │ │ │ ├── Ex+CGPoint.swift
│ │ │ │ ├── Ex+CGRect.swift
│ │ │ │ └── Ex+CGSize.swift
│ │ │ ├── Swift/
│ │ │ │ ├── Ex+Array.swift
│ │ │ │ ├── Ex+Clamp.swift
│ │ │ │ ├── Ex+Localize.swift
│ │ │ │ ├── Ex+Number.swift
│ │ │ │ └── Ex+OptionSet.swift
│ │ │ └── UI/
│ │ │ ├── Ex+CALayer.swift
│ │ │ ├── Ex+Image.swift
│ │ │ ├── Ex+NSColor.swift
│ │ │ ├── Ex+NSControl.swift
│ │ │ ├── Ex+NSEdgeInsets.swift
│ │ │ ├── Ex+NSEvent.swift
│ │ │ ├── Ex+NSMenuItem.swift
│ │ │ ├── Ex+NSPopover.swift
│ │ │ ├── Ex+NSTableView.swift
│ │ │ └── Ex+UI.swift
│ │ ├── HotKey/
│ │ │ ├── HotKey.swift
│ │ │ ├── Key.swift
│ │ │ └── NSEvent+HotKey.swift
│ │ └── Info.plist
│ └── CoreUtil.xcodeproj/
│ ├── project.pbxproj
│ └── project.xcworkspace/
│ ├── contents.xcworkspacedata
│ └── xcshareddata/
│ └── IDEWorkspaceChecks.plist
├── DevToys/
│ ├── DevToys/
│ │ ├── App/
│ │ │ ├── AppViewController.swift
│ │ │ └── AppWindowController.swift
│ │ ├── AppDelegate.swift
│ │ ├── Body/
│ │ │ ├── BodyViewController.swift
│ │ │ ├── Coder/
│ │ │ │ ├── Base64DecoderView+.swift
│ │ │ │ ├── HTMLDecoderView+.swift
│ │ │ │ ├── JWTDecoderView+.swift
│ │ │ │ └── URLDecoderView+.swift
│ │ │ ├── Convert/
│ │ │ │ ├── DateConverterView+.swift
│ │ │ │ ├── JSONYamlConverterView+.swift
│ │ │ │ └── NumberBaseConverterView+.swift
│ │ │ ├── Format/
│ │ │ │ ├── JSONFormatterView+.swift
│ │ │ │ ├── SQLFormatterView+.swift
│ │ │ │ └── XMLFormatterView+.swift
│ │ │ ├── Generator/
│ │ │ │ ├── ChecksumGeneratorView+.swift
│ │ │ │ ├── HashGeneratorView+.swift
│ │ │ │ ├── LoremIpsumGeneratorView+.swift
│ │ │ │ ├── QRCodeGeneratorView+.swift
│ │ │ │ └── UUIDGeneratorView+.swift
│ │ │ ├── Graphic/
│ │ │ │ ├── Icon Generator/
│ │ │ │ │ ├── Generators/
│ │ │ │ │ │ ├── AndroidIconGenerator.swift
│ │ │ │ │ │ ├── IOSIconGenerator.swift
│ │ │ │ │ │ ├── IcnsGenerator.swift
│ │ │ │ │ │ ├── IcoGenerator.swift
│ │ │ │ │ │ ├── IconFolderGenerator.swift
│ │ │ │ │ │ ├── IconGenerator+Model.swift
│ │ │ │ │ │ ├── IconsetGenerator.swift
│ │ │ │ │ │ ├── IosIconGenerator.swift
│ │ │ │ │ │ └── PngIconGenerator.swift
│ │ │ │ │ ├── Icon Templete/
│ │ │ │ │ │ ├── IconImageManager.swift
│ │ │ │ │ │ ├── IconSet.swift
│ │ │ │ │ │ ├── IconTemplete+.swift
│ │ │ │ │ │ └── IconTemplete.swift
│ │ │ │ │ └── IconGeneratorView+.swift
│ │ │ │ ├── Image Converter/
│ │ │ │ │ ├── Exporters/
│ │ │ │ │ │ ├── DefaultImageExporter.swift
│ │ │ │ │ │ ├── HeicImageExporter.swift
│ │ │ │ │ │ ├── WebpImageExporter.swift
│ │ │ │ │ │ └── cwebp
│ │ │ │ │ ├── ImageConverter.swift
│ │ │ │ │ └── ImageConverterView+.swift
│ │ │ │ ├── Image Optimizer/
│ │ │ │ │ ├── ImageOptimaizerView.swift
│ │ │ │ │ ├── ImageOptimizer.swift
│ │ │ │ │ ├── jpegoptim
│ │ │ │ │ └── optipng
│ │ │ │ ├── PDFGeneratorView+.swift
│ │ │ │ └── QRCodeReaderView+.swift
│ │ │ ├── HomeView+.swift
│ │ │ ├── Media/
│ │ │ │ ├── Audio Converter/
│ │ │ │ │ ├── AudioConverter.swift
│ │ │ │ │ ├── AudioConverterView+.swift
│ │ │ │ │ └── AudioFileScanner.swift
│ │ │ │ ├── Color Picker/
│ │ │ │ │ ├── Color.swift
│ │ │ │ │ ├── ColorPickerView+.swift
│ │ │ │ │ ├── Components/
│ │ │ │ │ │ ├── BoxHSBColorPicker.swift
│ │ │ │ │ │ ├── BrightnessBarView.swift
│ │ │ │ │ │ ├── CircleBarsHSBColorPicker.swift
│ │ │ │ │ │ ├── CircleBoxHSBColorPicker.swift
│ │ │ │ │ │ ├── CircleHueBarView.swift
│ │ │ │ │ │ ├── ColorBoxView.swift
│ │ │ │ │ │ ├── ColorPickerHandleLayer.swift
│ │ │ │ │ │ ├── ColorSampleView.swift
│ │ │ │ │ │ ├── HueBarView.swift
│ │ │ │ │ │ ├── OpacityBarView.swift
│ │ │ │ │ │ └── SaturationBarView.swift
│ │ │ │ │ ├── Pixel Picker/
│ │ │ │ │ │ ├── ACOverlayController.swift
│ │ │ │ │ │ ├── ACOverlayController.xib
│ │ │ │ │ │ ├── ACOverlayPanel.swift
│ │ │ │ │ │ ├── ACOverlayPreview.swift
│ │ │ │ │ │ ├── ACOverlayWrapper.swift
│ │ │ │ │ │ ├── ACPixelPicker.swift
│ │ │ │ │ │ └── Utils/
│ │ │ │ │ │ ├── Ex+CGImage.swift
│ │ │ │ │ │ ├── Ex+NSBezierPath.swift
│ │ │ │ │ │ ├── Ex+NSColor.swift
│ │ │ │ │ │ ├── ShowAndHideCursor.h
│ │ │ │ │ │ ├── ShowAndHideCursor.m
│ │ │ │ │ │ ├── ShowAndHideCursor.swift
│ │ │ │ │ │ └── Util+PixelPicker.swift
│ │ │ │ │ └── R+ColorPicker.swift
│ │ │ │ └── Movie to Gif/
│ │ │ │ ├── GifConverter.swift
│ │ │ │ └── GifConverterView+.swift
│ │ │ ├── SettingView+.swift
│ │ │ ├── Text/
│ │ │ │ ├── HyphenationRemoverView+.swift
│ │ │ │ ├── JSON Search/
│ │ │ │ │ ├── JSONNormalSearchView.swift
│ │ │ │ │ └── JSONSearchView+.swift
│ │ │ │ ├── RegexTesterView+.swift
│ │ │ │ ├── TextDiffView+.swift
│ │ │ │ └── TextInspectorView+.swift
│ │ │ └── Utils/
│ │ │ ├── CameraViewController.swift
│ │ │ ├── FileConflictAvoider.swift
│ │ │ ├── Identifier.swift
│ │ │ ├── ImageDropper.swift
│ │ │ ├── Slugify.swift
│ │ │ └── ffmpeg/
│ │ │ ├── FFMpegExecutor.swift
│ │ │ ├── FFProgressReport.swift
│ │ │ ├── FFTask.swift
│ │ │ ├── FFThumnailGenerator.swift
│ │ │ ├── FFTime.swift
│ │ │ └── ffmpeg
│ │ ├── Bridging-Header.h
│ │ ├── Component/
│ │ │ ├── Area.swift
│ │ │ ├── Button.swift
│ │ │ ├── CodeTextView.swift
│ │ │ ├── ControlBackgroundLayer.swift
│ │ │ ├── ControlContainer.swift
│ │ │ ├── DatePicker.swift
│ │ │ ├── DragImageView.swift
│ │ │ ├── EmptyImageTableView.swift
│ │ │ ├── FileDrop.swift
│ │ │ ├── ImageDropView.swift
│ │ │ ├── NumberField.swift
│ │ │ ├── Page.swift
│ │ │ ├── PopupButton.swift
│ │ │ ├── RegexTextView.swift
│ │ │ ├── Section.swift
│ │ │ ├── SectionButton+.swift
│ │ │ ├── SectionButton.swift
│ │ │ ├── TagCloudView.swift
│ │ │ ├── TextField.swift
│ │ │ ├── TextFieldSection.swift
│ │ │ ├── TextView.swift
│ │ │ ├── TextViewSection.swift
│ │ │ └── Toast.swift
│ │ ├── DevToys.entitlements
│ │ ├── Info.plist
│ │ ├── Model/
│ │ │ ├── AppModel.swift
│ │ │ ├── Settings.swift
│ │ │ ├── Tool+Default.swift
│ │ │ ├── ToolCategory+Default.swift
│ │ │ └── ToolManager+.swift
│ │ ├── Resource/
│ │ │ ├── Assets.xcassets/
│ │ │ │ ├── AccentColor.colorset/
│ │ │ │ │ └── Contents.json
│ │ │ │ ├── AppIcon.appiconset/
│ │ │ │ │ └── Contents.json
│ │ │ │ ├── Contents.json
│ │ │ │ ├── applewatch.imageset/
│ │ │ │ │ └── Contents.json
│ │ │ │ ├── carplay.imageset/
│ │ │ │ │ └── Contents.json
│ │ │ │ ├── check.imageset/
│ │ │ │ │ └── Contents.json
│ │ │ │ ├── clear.imageset/
│ │ │ │ │ └── Contents.json
│ │ │ │ ├── convert.imageset/
│ │ │ │ │ └── Contents.json
│ │ │ │ ├── copy.imageset/
│ │ │ │ │ └── Contents.json
│ │ │ │ ├── drop.imageset/
│ │ │ │ │ └── Contents.json
│ │ │ │ ├── error.imageset/
│ │ │ │ │ └── Contents.json
│ │ │ │ ├── export.imageset/
│ │ │ │ │ └── Contents.json
│ │ │ │ ├── format.imageset/
│ │ │ │ │ └── Contents.json
│ │ │ │ ├── hyphen.imageset/
│ │ │ │ │ └── Contents.json
│ │ │ │ ├── ipad.imageset/
│ │ │ │ │ └── Contents.json
│ │ │ │ ├── ipaddress.imageset/
│ │ │ │ │ └── Contents.json
│ │ │ │ ├── iphone.imageset/
│ │ │ │ │ └── Contents.json
│ │ │ │ ├── mac.imageset/
│ │ │ │ │ └── Contents.json
│ │ │ │ ├── network.status.imageset/
│ │ │ │ │ └── Contents.json
│ │ │ │ ├── number.imageset/
│ │ │ │ │ └── Contents.json
│ │ │ │ ├── open.imageset/
│ │ │ │ │ └── Contents.json
│ │ │ │ ├── paramators.imageset/
│ │ │ │ │ └── Contents.json
│ │ │ │ ├── paste.imageset/
│ │ │ │ │ └── Contents.json
│ │ │ │ ├── pulldown.indicator.imageset/
│ │ │ │ │ └── Contents.json
│ │ │ │ ├── search.imageset/
│ │ │ │ │ └── Contents.json
│ │ │ │ ├── settings.imageset/
│ │ │ │ │ └── Contents.json
│ │ │ │ ├── sidebar.disclosure.imageset/
│ │ │ │ │ └── Contents.json
│ │ │ │ ├── spacing.imageset/
│ │ │ │ │ └── Contents.json
│ │ │ │ ├── speed.imageset/
│ │ │ │ │ └── Contents.json
│ │ │ │ ├── spuit.imageset/
│ │ │ │ │ └── Contents.json
│ │ │ │ ├── stepper.down.imageset/
│ │ │ │ │ └── Contents.json
│ │ │ │ ├── stepper.up.imageset/
│ │ │ │ │ └── Contents.json
│ │ │ │ ├── text.imageset/
│ │ │ │ │ └── Contents.json
│ │ │ │ ├── tool/
│ │ │ │ │ ├── Contents.json
│ │ │ │ │ ├── api.imageset/
│ │ │ │ │ │ └── Contents.json
│ │ │ │ │ ├── audio.convert.imageset/
│ │ │ │ │ │ └── Contents.json
│ │ │ │ │ ├── base64.coder.imageset/
│ │ │ │ │ │ └── Contents.json
│ │ │ │ │ ├── color.blindness.simulator.imageset/
│ │ │ │ │ │ └── Contents.json
│ │ │ │ │ ├── color.picker.imageset/
│ │ │ │ │ │ └── Contents.json
│ │ │ │ │ ├── convert.imageset/
│ │ │ │ │ │ └── Contents.json
│ │ │ │ │ ├── date.convert.imageset/
│ │ │ │ │ │ └── Contents.json
│ │ │ │ │ ├── encoder.decoder.imageset/
│ │ │ │ │ │ └── Contents.json
│ │ │ │ │ ├── formatter.imageset/
│ │ │ │ │ │ └── Contents.json
│ │ │ │ │ ├── generator.imageset/
│ │ │ │ │ │ └── Contents.json
│ │ │ │ │ ├── gif.imageset/
│ │ │ │ │ │ └── Contents.json
│ │ │ │ │ ├── graphic.imageset/
│ │ │ │ │ │ └── Contents.json
│ │ │ │ │ ├── hash.generator.imageset/
│ │ │ │ │ │ └── Contents.json
│ │ │ │ │ ├── home.imageset/
│ │ │ │ │ │ └── Contents.json
│ │ │ │ │ ├── html.coder.imageset/
│ │ │ │ │ │ └── Contents.json
│ │ │ │ │ ├── icon.generator.imageset/
│ │ │ │ │ │ └── Contents.json
│ │ │ │ │ ├── image.compressor.imageset/
│ │ │ │ │ │ └── Contents.json
│ │ │ │ │ ├── image.converter.imageset/
│ │ │ │ │ │ └── Contents.json
│ │ │ │ │ ├── json.convert.imageset/
│ │ │ │ │ │ └── Contents.json
│ │ │ │ │ ├── json.formatter.imageset/
│ │ │ │ │ │ └── Contents.json
│ │ │ │ │ ├── json.search.imageset/
│ │ │ │ │ │ └── Contents.json
│ │ │ │ │ ├── jwt.coder.imageset/
│ │ │ │ │ │ └── Contents.json
│ │ │ │ │ ├── lorem.ipsum.generator.imageset/
│ │ │ │ │ │ └── Contents.json
│ │ │ │ │ ├── markdown.preview.imageset/
│ │ │ │ │ │ └── Contents.json
│ │ │ │ │ ├── media.imageset/
│ │ │ │ │ │ └── Contents.json
│ │ │ │ │ ├── network.imageset/
│ │ │ │ │ │ └── Contents.json
│ │ │ │ │ ├── number.base.convert.imageset/
│ │ │ │ │ │ └── Contents.json
│ │ │ │ │ ├── pdf.imageset/
│ │ │ │ │ │ └── Contents.json
│ │ │ │ │ ├── qr.generator.imageset/
│ │ │ │ │ │ └── Contents.json
│ │ │ │ │ ├── regex.tester.imageset/
│ │ │ │ │ │ └── Contents.json
│ │ │ │ │ ├── settings.imageset/
│ │ │ │ │ │ └── Contents.json
│ │ │ │ │ ├── sql.formatter.imageset/
│ │ │ │ │ │ └── Contents.json
│ │ │ │ │ ├── text.diff.imageset/
│ │ │ │ │ │ └── Contents.json
│ │ │ │ │ ├── text.imageset/
│ │ │ │ │ │ └── Contents.json
│ │ │ │ │ ├── text.inspector.imageset/
│ │ │ │ │ │ └── Contents.json
│ │ │ │ │ ├── url.coder.imageset/
│ │ │ │ │ │ └── Contents.json
│ │ │ │ │ ├── uuid.generator.imageset/
│ │ │ │ │ │ └── Contents.json
│ │ │ │ │ └── xml.formatter.imageset/
│ │ │ │ │ └── Contents.json
│ │ │ │ └── transparent_background.imageset/
│ │ │ │ └── Contents.json
│ │ │ ├── Base.lproj/
│ │ │ │ └── Main.storyboard
│ │ │ ├── R.swift
│ │ │ ├── de.lproj/
│ │ │ │ ├── Localizable.strings
│ │ │ │ └── Main.strings
│ │ │ ├── en.lproj/
│ │ │ │ ├── Localizable.strings
│ │ │ │ └── Main.strings
│ │ │ ├── es.lproj/
│ │ │ │ ├── Localizable.strings
│ │ │ │ └── Main.strings
│ │ │ ├── ja.lproj/
│ │ │ │ ├── Localizable.strings
│ │ │ │ └── Main.strings
│ │ │ ├── pt-BR.lproj/
│ │ │ │ ├── Localizable.strings
│ │ │ │ └── Main.strings
│ │ │ └── zh-Hans.lproj/
│ │ │ ├── Localizable.strings
│ │ │ └── Main.strings
│ │ └── Sidebar/
│ │ ├── SearchCell.swift
│ │ ├── SidebarView+.swift
│ │ ├── ToolCategoryCell.swift
│ │ ├── ToolMenuCell.swift
│ │ └── View/
│ │ └── Separator.swift
│ └── DevToys.xcodeproj/
│ ├── project.pbxproj
│ ├── project.xcworkspace/
│ │ ├── contents.xcworkspacedata
│ │ └── xcshareddata/
│ │ └── IDEWorkspaceChecks.plist
│ └── xcshareddata/
│ └── xcschemes/
│ └── DevToys.xcscheme
├── DevToys.xcworkspace/
│ ├── contents.xcworkspacedata
│ └── xcshareddata/
│ ├── IDEWorkspaceChecks.plist
│ └── swiftpm/
│ └── Package.resolved
├── LICENSE
├── README.md
├── Release Checklist.md
└── docs/
├── index.html
└── sparkle/
└── appcast.xml
================================================
FILE CONTENTS
================================================
================================================
FILE: .gitignore
================================================
# Mac
.DS_Store
# Xcode
#
# gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore
## User settings
xcuserdata/
## compatibility with Xcode 8 and earlier (ignoring not required starting Xcode 9)
*.xcscmblueprint
*.xccheckout
## compatibility with Xcode 3 and earlier (ignoring not required starting Xcode 4)
build/
DerivedData/
*.moved-aside
*.pbxuser
!default.pbxuser
*.mode1v3
!default.mode1v3
*.mode2v3
!default.mode2v3
*.perspectivev3
!default.perspectivev3
## Obj-C/Swift specific
*.hmap
## App packaging
*.ipa
*.dSYM.zip
*.dSYM
## Playgrounds
timeline.xctimeline
playground.xcworkspace
# Swift Package Manager
#
# Add this line if you want to avoid checking in source code from Swift Package Manager dependencies.
# Packages/
# Package.pins
# Package.resolved
# *.xcodeproj
#
# Xcode automatically generates this directory with a .xcworkspacedata file and xcuserdata
# hence it is not needed unless you have added a package configuration file to your project
# .swiftpm
.build/
# CocoaPods
#
# We recommend against adding the Pods directory to your .gitignore. However
# you should judge for yourself, the pros and cons are mentioned at:
# https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
#
# Pods/
#
# Add this line if you want to avoid checking in source code from the Xcode workspace
# *.xcworkspace
# Carthage
#
# Add this line if you want to avoid checking in source code from Carthage dependencies.
# Carthage/Checkouts
Carthage/Build/
# Accio dependency management
Dependencies/
.accio/
# fastlane
#
# It is recommended to not store the screenshots in the git repo.
# Instead, use fastlane to re-generate the screenshots whenever they are needed.
# For more information about the recommended setup visit:
# https://docs.fastlane.tools/best-practices/source-control/#source-control
fastlane/report.xml
fastlane/Preview.html
fastlane/screenshots/**/*.png
fastlane/test_output
# Code Injection
#
# After new code Injection tools there's a generated folder /iOSInjectionProject
# https://github.com/johnno1962/injectionforxcode
iOSInjectionProject/
================================================
FILE: CoreUtil/CoreUtil/Class/Action.swift
================================================
//
// Action.swift
// CoreUtil
//
// Created by yuki on 2022/01/16.
// Copyright © 2022 yuki. All rights reserved.
//
public struct Action {
public let title: String
public let action: () -> ()
public init(title: String, action: @escaping () -> ()) {
self.title = title
self.action = action
}
}
================================================
FILE: CoreUtil/CoreUtil/Class/Delta.swift
================================================
//
// Delta.swift
// CoreUtil
//
// Created by yuki on 2020/05/14.
// Copyright © 2020 yuki. All rights reserved.
//
public enum Delta<Value> {
case to(Value)
case by(Value)
}
extension Delta {
@inlinable public func map<T>(_ tranceform: (Value) throws -> T) rethrows -> Delta<T> {
switch self {
case .to(let value): return .to(try tranceform(value))
case .by(let value): return .by(try tranceform(value))
}
}
@inlinable public func reduce(_ initialValue: Value, _ tranceform: (Value, Value) throws -> Value) rethrows -> Value {
switch self {
case .to(let value): return value
case .by(let value): return try tranceform(initialValue, value)
}
}
@inlinable public func takeValue() -> Value {
switch self {
case .to(let value): return value
case .by(let value): return value
}
}
@inlinable public func apply(_ initialValue: inout Value, _ tranceform: (Value, Value) throws -> Value) rethrows {
initialValue = try reduce(initialValue, tranceform)
}
}
extension Delta where Value: AdditiveArithmetic {
@inlinable public func reduce(_ initialValue: Value) -> Value {
reduce(initialValue, +)
}
@inlinable public func apply(_ initialValue: inout Value) {
apply(&initialValue, +)
}
@inlinable public static func += (_ initialValue: inout Value, delta: Delta<Value>) {
delta.apply(&initialValue)
}
}
extension Delta where Value: RangeReplaceableCollection {
@inlinable public func reduce(_ initialValue: Value) -> Value {
reduce(initialValue, +)
}
@inlinable public func apply(_ initialValue: inout Value) {
apply(&initialValue, +)
}
@inlinable public static func += (_ initialValue: inout Value, delta: Delta<Value>) {
delta.apply(&initialValue)
}
}
extension Delta: Encodable where Value: Encodable {
public func encode(to encoder: Encoder) throws {
var container = encoder.singleValueContainer()
switch self {
case .by(let value): try container.encode(["by": value])
case .to(let value): try container.encode(["to": value])
}
}
}
extension Delta: Decodable where Value: Decodable {
public init(from decoder: Decoder) throws {
let container = try decoder.singleValueContainer()
let content = try container.decode([String: Value].self)
guard let (key, value) = content.first else {
throw DecodingError.dataCorruptedError(in: container, debugDescription: "Empty container")
}
switch key {
case "by": self = .by(value)
case "to": self = .to(value)
default: throw DecodingError.dataCorruptedError(in: container, debugDescription: "Unkown key '\(key)'")
}
}
}
================================================
FILE: CoreUtil/CoreUtil/Class/NS+OnAwake.swift
================================================
//
// NSLoadView.swift
// CoreUtil
//
// Created by yuki on 2020/08/31.
// Copyright © 2020 yuki. All rights reserved.
//
import Cocoa
open class NSLoadView: NSView {
open func onAwake() {}
public override init(frame frameRect: NSRect) {
super.init(frame: frameRect)
onAwake()
}
public required init?(coder: NSCoder) {
super.init(coder: coder)
onAwake()
}
}
open class NSLoadTextView: NSTextView {
open func onAwake() {}
public override init(frame frameRect: NSRect) {
super.init(frame: frameRect)
onAwake()
}
public required init?(coder: NSCoder) {
super.init(coder: coder)
onAwake()
}
}
open class NSLoadTableRowView: NSTableRowView {
open func onAwake() {}
public override init(frame frameRect: NSRect) {
super.init(frame: frameRect)
onAwake()
}
public required init?(coder: NSCoder) {
super.init(coder: coder)
onAwake()
}
}
open class NSLoadVisualEffectView: NSVisualEffectView {
open func onAwake() {}
public override init(frame frameRect: NSRect) {
super.init(frame: frameRect)
onAwake()
}
public required init?(coder: NSCoder) {
super.init(coder: coder)
onAwake()
}
}
open class NSLoadImageView: NSImageView {
open func onAwake() {}
public override init(frame frameRect: NSRect) {
super.init(frame: frameRect)
onAwake()
}
public required init?(coder: NSCoder) {
super.init(coder: coder)
onAwake()
}
}
open class NSLoadStackView: NSStackView {
open func onAwake() {}
public override init(frame frameRect: NSRect) {
super.init(frame: frameRect)
onAwake()
}
public required init?(coder: NSCoder) {
super.init(coder: coder)
onAwake()
}
}
open class NSLoadTextField: NSTextField {
open func onAwake() {}
public override init(frame frameRect: NSRect) {
super.init(frame: frameRect)
onAwake()
}
public required init?(coder: NSCoder) {
super.init(coder: coder)
onAwake()
}
}
open class NSLoadTokenField: NSTokenField {
open func onAwake() {}
public override init(frame frameRect: NSRect) {
super.init(frame: frameRect)
onAwake()
}
public required init?(coder: NSCoder) {
super.init(coder: coder)
onAwake()
}
}
open class NSLoadSearchField: NSSearchField {
open func onAwake() {}
public override init(frame frameRect: NSRect) {
super.init(frame: frameRect)
onAwake()
}
public required init?(coder: NSCoder) {
super.init(coder: coder)
onAwake()
}
}
open class NSLoadScrollView: NSScrollView {
open func onAwake() {}
public override init(frame frameRect: NSRect) {
super.init(frame: frameRect)
onAwake()
}
public required init?(coder: NSCoder) {
super.init(coder: coder)
onAwake()
}
}
open class NSLoadTableView: NSTableView {
open func onAwake() {}
public override init(frame frameRect: NSRect) {
super.init(frame: frameRect)
onAwake()
}
public required init?(coder: NSCoder) {
super.init(coder: coder)
onAwake()
}
}
open class NSLoadSplitView: NSSplitView {
open func onAwake() {}
public override init(frame frameRect: NSRect) {
super.init(frame: frameRect)
onAwake()
}
public required init?(coder: NSCoder) {
super.init(coder: coder)
onAwake()
}
}
open class NSLoadControl: NSControl {
open func onAwake() {}
public override init(frame frameRect: NSRect) {
super.init(frame: frameRect)
onAwake()
}
public required init?(coder: NSCoder) {
super.init(coder: coder)
onAwake()
}
}
open class NSLoadButton: NSButton {
open func onAwake() {}
public override init(frame frameRect: NSRect) {
super.init(frame: frameRect)
onAwake()
}
public required init?(coder: NSCoder) {
super.init(coder: coder)
onAwake()
}
}
open class NSLoadCollectionView: NSCollectionView {
open func onAwake() {}
public override init(frame frameRect: NSRect) {
super.init(frame: frameRect)
onAwake()
}
public required init?(coder: NSCoder) {
super.init(coder: coder)
onAwake()
}
}
open class CALoadLayer: CALayer {
open func onAwake() {}
public override init() {
super.init()
onAwake()
}
public required init?(coder: NSCoder) {
super.init(coder: coder)
onAwake()
}
public override init(layer: Any) {
super.init(layer: layer)
onAwake()
}
}
open class CALoadShapeLayer: CAShapeLayer {
open func onAwake() {}
public override init() {
super.init()
onAwake()
}
public required init?(coder: NSCoder) {
super.init(coder: coder)
onAwake()
}
public override init(layer: Any) {
super.init(layer: layer)
onAwake()
}
}
open class CALoadTextLayer: CATextLayer {
open func onAwake() {}
public override init() {
super.init()
onAwake()
}
public required init?(coder: NSCoder) {
super.init(coder: coder)
onAwake()
}
public override init(layer: Any) {
super.init(layer: layer)
onAwake()
}
}
open class CALoadGradientLayer: CAGradientLayer {
open func onAwake() {}
public override init() {
super.init()
onAwake()
}
public required init?(coder: NSCoder) {
super.init(coder: coder)
onAwake()
}
public override init(layer: Any) {
super.init(layer: layer)
onAwake()
}
}
================================================
FILE: CoreUtil/CoreUtil/Class/NSColorView.swift
================================================
//
// NSColorView.swift
// CoreUtil
//
// Created by yuki on 2021/10/05.
// Copyright © 2021 yuki. All rights reserved.
//
import Cocoa
open class NSColorView: NSLoadView {
open var borderWidth: CGFloat = 1 { didSet { setNeedsDisplay(bounds) } }
open var borderColor: NSColor? { didSet { setNeedsDisplay(bounds) } }
open var backgroundColor: NSColor? { didSet { setNeedsDisplay(bounds) } }
open override func draw(_ dirtyRect: NSRect) {
if let backgroundColor = self.backgroundColor {
backgroundColor.setFill()
dirtyRect.fill()
}
if let borderColor = self.borderColor {
borderColor.setStroke()
let path = NSBezierPath(rect: dirtyRect)
path.lineWidth = borderWidth
path.stroke()
}
}
}
================================================
FILE: CoreUtil/CoreUtil/Class/NSViewController+ChainObject.swift
================================================
//
// NSViewController.swift
// CoreUtil
//
// Created by yuki on 2021/07/19.
// Copyright © 2021 yuki. All rights reserved.
//
import Cocoa
private var chainObjectKey = 0
private var chainObjectFlagKey = 0
extension NSViewController {
public var isChainObjectLoaded: Bool {
get { objc_getAssociatedObject(self, &chainObjectFlagKey) as? Bool ?? false }
set { objc_setAssociatedObject(self, &chainObjectFlagKey, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC) }
}
public var chainObject: Any? {
get { objc_getAssociatedObject(self, &chainObjectKey) }
set {
guard let chainObject = newValue else { return }
if self.isChainObjectLoaded { return }; self.isChainObjectLoaded = true
objc_setAssociatedObject(self, &chainObjectKey, chainObject, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
Self.activateObjectChain
for child in children { child.chainObject = chainObject }
self.chainObjectDidLoad()
}
}
@objc open func chainObjectDidLoad() {}
static let activateObjectChain: () = method_exchangeImplementations(
class_getInstanceMethod(NSViewController.self, #selector(addChild))!,
class_getInstanceMethod(NSViewController.self, #selector(chain_addChild))!
)
@objc private dynamic func chain_addChild(_ childViewController: NSViewController) {
childViewController.chainObject = chainObject
self.chain_addChild(childViewController)
}
}
================================================
FILE: CoreUtil/CoreUtil/Class/NSViewController+StateObject.swift
================================================
//
// NSViewController+StateObject.swift
// CoreUtil
//
// Created by yuki on 2021/06/24.
// Copyright © 2021 yuki. All rights reserved.
//
import Cocoa
import Combine
public struct StateChannel<Value> {
let rawValue: String
public init(_ rawValue: String) {
self.rawValue = rawValue
}
}
extension NSViewController {
public func getState<Value>(for channel: StateChannel<Value?>) -> Value? {
getState(for: channel).flatMap{ $0 }
}
public func getState<Value>(for channel: StateChannel<Value>) -> Value? {
publisher(for: channel.rawValue).value as? Value
}
public func setState<Value>(_ value: Value?, for channel: StateChannel<Value>) {
Self.activateStateObject()
_setState(value, for: channel.rawValue)
}
public func getStatePublisher<Value>(for channel: StateChannel<Value>) -> AnyPublisher<Value?, Never> {
publisher(for: channel.rawValue).map{ $0 as? Value }.eraseToAnyPublisher()
}
public func getStatePublisher<Value>(for channel: StateChannel<Value>) -> AnyPublisher<Value?, Never> where Value: AnyObject {
publisher(for: channel.rawValue).map{ $0 as? Value }.removeDuplicates(by: ===).eraseToAnyPublisher()
}
public func getStatePublisher<Value>(for channel: StateChannel<Value?>) -> AnyPublisher<Value?, Never> where Value: AnyObject {
publisher(for: channel.rawValue).map{ $0 as? Value }.removeDuplicates(by: ===).eraseToAnyPublisher()
}
public func linkState<Value>(for channel: StateChannel<Value>, to viewController: NSViewController) {
getStatePublisher(for: channel).sink{ viewController.setState($0, for: channel) }.store(in: &self.objectBag)
}
}
extension NSViewController {
private static func activateStateObject() {
enum __ {
static let __: () = method_exchangeImplementations(
class_getInstanceMethod(NSViewController.self, #selector(addChild))!,
class_getInstanceMethod(NSViewController.self, #selector(_addChild))!
)
}
__.__
}
private func _setState(_ value: Any?, for channel: String) {
publisher(for: channel).send(value)
for child in children {
child._setState(value, for: channel)
}
}
private static var envContainerKey = 0
private var envContainer: [String: CurrentValueSubject<Any?, Never>] {
get { objc_getAssociatedObject(self, &Self.envContainerKey) as? [String: CurrentValueSubject<Any?, Never>] ?? [:] }
set { objc_setAssociatedObject(self, &Self.envContainerKey, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC) }
}
private func publisher(for channel: String) -> CurrentValueSubject<Any?, Never> {
return envContainer[channel] ?? CurrentValueSubject(nil) => { envContainer[channel] = $0 }
}
@objc private dynamic func _addChild(_ childViewController: NSViewController) {
for channel in envContainer.keys {
guard let value = publisher(for: channel).value else { continue }
childViewController._setState(value, for: channel)
}
self._addChild(childViewController)
}
}
================================================
FILE: CoreUtil/CoreUtil/Class/Observable.swift
================================================
//
// Property.swift
// CoreUtil
//
// Created by yuki on 2020/07/06.
// Copyright © 2020 yuki. All rights reserved.
//
import Combine
/// Publishedの10倍軽いPropertyWrapper
@propertyWrapper
public struct Observable<Value> {
public struct Publisher: Combine.Publisher {
public typealias Output = Value
public typealias Failure = Never
@usableFromInline let subject: CurrentValueSubject<Value, Never>
@inlinable init(_ value: Value) { self.subject = CurrentValueSubject(value) }
@inlinable public func receive<S: Subscriber>(subscriber: S) where S.Failure == Self.Failure, S.Input == Self.Output {
self.subject.receive(subscriber: subscriber)
}
}
public let projectedValue: Publisher
@inlinable public var wrappedValue: Value {
@inlinable get { projectedValue.subject.value }
@inlinable set { projectedValue.subject.send(newValue) }
}
@inlinable public init(wrappedValue value: Value) {
self.projectedValue = Publisher(value)
}
}
================================================
FILE: CoreUtil/CoreUtil/Class/PipeOperator.swift
================================================
//
// +Functions.swift
// CoreUtil
//
// Created by yuki on 2020/10/01.
// Copyright © 2020 yuki. All rights reserved.
//
precedencegroup PipePrecedence {
higherThan: NilCoalescingPrecedence
associativity: left
}
infix operator =>: PipePrecedence
infix operator |>: PipePrecedence
infix operator <=>: PipePrecedence
@discardableResult
@inlinable public func => <T>(lhs: T, rhs: (T) throws -> Void) rethrows -> T {
try rhs(lhs)
return lhs
}
@discardableResult
@inlinable public func |> <T, U>(lhs: T, rhs: (T) throws -> U) rethrows -> U {
try rhs(lhs)
}
@discardableResult
@inlinable public func <=> <T>(lhs: T, rhs: (inout T) throws -> Void) rethrows -> T {
var lhs = lhs
try rhs(&lhs)
return lhs
}
================================================
FILE: CoreUtil/CoreUtil/Class/Query.swift
================================================
//
// Query.swift
// CoreUtil
//
// Created by yuki on 2020/01/13.
// Copyright © 2020 yuki. All rights reserved.
//
/// 検索時のクエリを表す。検索時の処理を一般化することが目的
///
/// # 大まかな仕様
/// - 空クエリは全てにマッチ
/// - 大文字小文字を考慮せずに検索を行う
/// - 空白文字で区切った文字の全てにマッチするときにマッチする
///
/// # サンプル
/// ```
/// let query = Query("Hello World")
///
/// query.matches(to: "") // true
/// query.matches(to: "Hello whole new world.") // true
/// query.matches(to: "Hello swift.") // false
/// ```
public struct Query {
/// 検索を行う要素
let components: [String]
/// 文字列で初期化
public init(_ query: String) {
self.components = query.components(separatedBy: .whitespaces)
.map{ $0.lowercased() }
.filter{ !$0.isEmpty }
}
/// 空クエリで初期化
public init() {
self.components = []
}
public var isEmpty: Bool { self.components.isEmpty }
/// マッチ判定を行う。詳細は`Query`のDiscussionを参照。
public func matches(to contents: String...) -> Bool {
if self.components.isEmpty { return true }
let contents = contents.map{ $0.lowercased() }
return components.allSatisfy{ component in
contents.contains{ $0.contains(component) }
}
}
}
================================================
FILE: CoreUtil/CoreUtil/Class/Reachability+Publisher.swift
================================================
//
// Reachability+Ex.swift
// CoreUtil
//
// Created by yuki on 2021/09/14.
// Copyright © 2021 yuki. All rights reserved.
//
import Foundation
import Combine
extension Reachability {
public struct Publisher: Combine.Publisher {
public typealias Output = Reachability
public typealias Failure = Never
let subject: CurrentValueSubject<Reachability, Never>
init(_ reachability: Reachability) {
self.subject = CurrentValueSubject(reachability)
reachability.whenReachable = {[subject] in subject.send($0) }
reachability.whenUnreachable = {[subject] in subject.send($0) }
try? reachability.startNotifier()
}
public func receive<S: Subscriber>(subscriber: S) where S.Failure == Self.Failure, S.Input == Self.Output {
self.subject.receive(subscriber: subscriber)
}
}
}
================================================
FILE: CoreUtil/CoreUtil/Class/Reachability.swift
================================================
/*
Copyright (c) 2014, Ashley Mills
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
import SystemConfiguration
import Foundation
public enum ReachabilityError: Error {
case failedToCreateWithAddress(sockaddr, Int32)
case failedToCreateWithHostname(String, Int32)
case unableToSetCallback(Int32)
case unableToSetDispatchQueue(Int32)
case unableToGetFlags(Int32)
}
@available(*, unavailable, renamed: "Notification.Name.reachabilityChanged")
public let ReachabilityChangedNotification = NSNotification.Name("ReachabilityChangedNotification")
public extension Notification.Name {
static let reachabilityChanged = Notification.Name("reachabilityChanged")
}
public class Reachability {
public typealias NetworkReachable = (Reachability) -> ()
public typealias NetworkUnreachable = (Reachability) -> ()
public private(set) lazy var publisher = Publisher(self)
public enum Connection: CustomStringConvertible {
case unavailable, wifi, cellular
public var description: String {
switch self {
case .cellular: return "Cellular"
case .wifi: return "WiFi"
case .unavailable: return "No Connection"
}
}
}
public var whenReachable: NetworkReachable?
public var whenUnreachable: NetworkUnreachable?
/// Set to `false` to force Reachability.connection to .none when on cellular connection (default value `true`)
public var allowsCellularConnection: Bool
// The notification center on which "reachability changed" events are being posted
public var notificationCenter: NotificationCenter = NotificationCenter.default
public var connection: Connection {
if flags == nil {
try? setReachabilityFlags()
}
switch flags?.connection {
case .unavailable?, nil: return .unavailable
case .cellular?: return allowsCellularConnection ? .cellular : .unavailable
case .wifi?: return .wifi
}
}
fileprivate var isRunningOnDevice: Bool = {
#if targetEnvironment(simulator)
return false
#else
return true
#endif
}()
fileprivate(set) var notifierRunning = false
fileprivate let reachabilityRef: SCNetworkReachability
fileprivate let reachabilitySerialQueue: DispatchQueue
fileprivate let notificationQueue: DispatchQueue?
fileprivate(set) var flags: SCNetworkReachabilityFlags? {
didSet {
guard flags != oldValue else { return }
notifyReachabilityChanged()
}
}
required public init(reachabilityRef: SCNetworkReachability,
queueQoS: DispatchQoS = .default,
targetQueue: DispatchQueue? = nil,
notificationQueue: DispatchQueue? = .main) {
self.allowsCellularConnection = true
self.reachabilityRef = reachabilityRef
self.reachabilitySerialQueue = DispatchQueue(label: "uk.co.ashleymills.reachability", qos: queueQoS, target: targetQueue)
self.notificationQueue = notificationQueue
}
public convenience init(hostname: String,
queueQoS: DispatchQoS = .default,
targetQueue: DispatchQueue? = nil,
notificationQueue: DispatchQueue? = .main) throws {
guard let ref = SCNetworkReachabilityCreateWithName(nil, hostname) else {
throw ReachabilityError.failedToCreateWithHostname(hostname, SCError())
}
self.init(reachabilityRef: ref, queueQoS: queueQoS, targetQueue: targetQueue, notificationQueue: notificationQueue)
}
public convenience init(queueQoS: DispatchQoS = .default,
targetQueue: DispatchQueue? = nil,
notificationQueue: DispatchQueue? = .main) throws {
var zeroAddress = sockaddr()
zeroAddress.sa_len = UInt8(MemoryLayout<sockaddr>.size)
zeroAddress.sa_family = sa_family_t(AF_INET)
guard let ref = SCNetworkReachabilityCreateWithAddress(nil, &zeroAddress) else {
throw ReachabilityError.failedToCreateWithAddress(zeroAddress, SCError())
}
self.init(reachabilityRef: ref, queueQoS: queueQoS, targetQueue: targetQueue, notificationQueue: notificationQueue)
}
deinit {
stopNotifier()
}
}
public extension Reachability {
// MARK: - *** Notifier methods ***
func startNotifier() throws {
guard !notifierRunning else { return }
let callback: SCNetworkReachabilityCallBack = { (reachability, flags, info) in
guard let info = info else { return }
// `weakifiedReachability` is guaranteed to exist by virtue of our
// retain/release callbacks which we provided to the `SCNetworkReachabilityContext`.
let weakifiedReachability = Unmanaged<ReachabilityWeakifier>.fromOpaque(info).takeUnretainedValue()
// The weak `reachability` _may_ no longer exist if the `Reachability`
// object has since been deallocated but a callback was already in flight.
weakifiedReachability.reachability?.flags = flags
}
let weakifiedReachability = ReachabilityWeakifier(reachability: self)
let opaqueWeakifiedReachability = Unmanaged<ReachabilityWeakifier>.passUnretained(weakifiedReachability).toOpaque()
var context = SCNetworkReachabilityContext(
version: 0,
info: UnsafeMutableRawPointer(opaqueWeakifiedReachability),
retain: { (info: UnsafeRawPointer) -> UnsafeRawPointer in
let unmanagedWeakifiedReachability = Unmanaged<ReachabilityWeakifier>.fromOpaque(info)
_ = unmanagedWeakifiedReachability.retain()
return UnsafeRawPointer(unmanagedWeakifiedReachability.toOpaque())
},
release: { (info: UnsafeRawPointer) -> Void in
let unmanagedWeakifiedReachability = Unmanaged<ReachabilityWeakifier>.fromOpaque(info)
unmanagedWeakifiedReachability.release()
},
copyDescription: { (info: UnsafeRawPointer) -> Unmanaged<CFString> in
let unmanagedWeakifiedReachability = Unmanaged<ReachabilityWeakifier>.fromOpaque(info)
let weakifiedReachability = unmanagedWeakifiedReachability.takeUnretainedValue()
let description = weakifiedReachability.reachability?.description ?? "nil"
return Unmanaged.passRetained(description as CFString)
}
)
if !SCNetworkReachabilitySetCallback(reachabilityRef, callback, &context) {
stopNotifier()
throw ReachabilityError.unableToSetCallback(SCError())
}
if !SCNetworkReachabilitySetDispatchQueue(reachabilityRef, reachabilitySerialQueue) {
stopNotifier()
throw ReachabilityError.unableToSetDispatchQueue(SCError())
}
// Perform an initial check
try setReachabilityFlags()
notifierRunning = true
}
func stopNotifier() {
defer { notifierRunning = false }
SCNetworkReachabilitySetCallback(reachabilityRef, nil, nil)
SCNetworkReachabilitySetDispatchQueue(reachabilityRef, nil)
}
var description: String {
return flags?.description ?? "unavailable flags"
}
}
fileprivate extension Reachability {
func setReachabilityFlags() throws {
try reachabilitySerialQueue.sync { [unowned self] in
var flags = SCNetworkReachabilityFlags()
if !SCNetworkReachabilityGetFlags(self.reachabilityRef, &flags) {
self.stopNotifier()
throw ReachabilityError.unableToGetFlags(SCError())
}
self.flags = flags
}
}
func notifyReachabilityChanged() {
let notify = { [weak self] in
guard let self = self else { return }
self.connection != .unavailable ? self.whenReachable?(self) : self.whenUnreachable?(self)
self.notificationCenter.post(name: .reachabilityChanged, object: self)
}
// notify on the configured `notificationQueue`, or the caller's (i.e. `reachabilitySerialQueue`)
notificationQueue?.async(execute: notify) ?? notify()
}
}
extension SCNetworkReachabilityFlags {
typealias Connection = Reachability.Connection
var connection: Connection {
guard isReachableFlagSet else { return .unavailable }
// If we're reachable, but not on an iOS device (i.e. simulator), we must be on WiFi
#if targetEnvironment(simulator)
return .wifi
#else
var connection = Connection.unavailable
if !isConnectionRequiredFlagSet {
connection = .wifi
}
if isConnectionOnTrafficOrDemandFlagSet {
if !isInterventionRequiredFlagSet {
connection = .wifi
}
}
if isOnWWANFlagSet {
connection = .cellular
}
return connection
#endif
}
var isOnWWANFlagSet: Bool {
#if os(iOS)
return contains(.isWWAN)
#else
return false
#endif
}
var isReachableFlagSet: Bool {
return contains(.reachable)
}
var isConnectionRequiredFlagSet: Bool {
return contains(.connectionRequired)
}
var isInterventionRequiredFlagSet: Bool {
return contains(.interventionRequired)
}
var isConnectionOnTrafficFlagSet: Bool {
return contains(.connectionOnTraffic)
}
var isConnectionOnDemandFlagSet: Bool {
return contains(.connectionOnDemand)
}
var isConnectionOnTrafficOrDemandFlagSet: Bool {
return !intersection([.connectionOnTraffic, .connectionOnDemand]).isEmpty
}
var isTransientConnectionFlagSet: Bool {
return contains(.transientConnection)
}
var isLocalAddressFlagSet: Bool {
return contains(.isLocalAddress)
}
var isDirectFlagSet: Bool {
return contains(.isDirect)
}
var isConnectionRequiredAndTransientFlagSet: Bool {
return intersection([.connectionRequired, .transientConnection]) == [.connectionRequired, .transientConnection]
}
var description: String {
let W = isOnWWANFlagSet ? "W" : "-"
let R = isReachableFlagSet ? "R" : "-"
let c = isConnectionRequiredFlagSet ? "c" : "-"
let t = isTransientConnectionFlagSet ? "t" : "-"
let i = isInterventionRequiredFlagSet ? "i" : "-"
let C = isConnectionOnTrafficFlagSet ? "C" : "-"
let D = isConnectionOnDemandFlagSet ? "D" : "-"
let l = isLocalAddressFlagSet ? "l" : "-"
let d = isDirectFlagSet ? "d" : "-"
return "\(W)\(R) \(c)\(t)\(i)\(C)\(D)\(l)\(d)"
}
}
/**
`ReachabilityWeakifier` weakly wraps the `Reachability` class
in order to break retain cycles when interacting with CoreFoundation.
CoreFoundation callbacks expect a pair of retain/release whenever an
opaque `info` parameter is provided. These callbacks exist to guard
against memory management race conditions when invoking the callbacks.
#### Race Condition
If we passed `SCNetworkReachabilitySetCallback` a direct reference to our
`Reachability` class without also providing corresponding retain/release
callbacks, then a race condition can lead to crashes when:
- `Reachability` is deallocated on thread X
- A `SCNetworkReachability` callback(s) is already in flight on thread Y
#### Retain Cycle
If we pass `Reachability` to CoreFoundtion while also providing retain/
release callbacks, we would create a retain cycle once CoreFoundation
retains our `Reachability` class. This fixes the crashes and his how
CoreFoundation expects the API to be used, but doesn't play nicely with
Swift/ARC. This cycle would only be broken after manually calling
`stopNotifier()` — `deinit` would never be called.
#### ReachabilityWeakifier
By providing both retain/release callbacks and wrapping `Reachability` in
a weak wrapper, we:
- interact correctly with CoreFoundation, thereby avoiding a crash.
See "Memory Management Programming Guide for Core Foundation".
- don't alter the public API of `Reachability.swift` in any way
- still allow for automatic stopping of the notifier on `deinit`.
*/
private class ReachabilityWeakifier {
weak var reachability: Reachability?
init(reachability: Reachability) {
self.reachability = reachability
}
}
================================================
FILE: CoreUtil/CoreUtil/Class/RestorableData.swift
================================================
//
// RestorableData.swift
// CoreUtil
//
// Created by yuki on 2022/02/03.
//
import Cocoa
extension FileManager {
public static let temporaryDirectoryURL = URL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent(Bundle.main.bundleIdentifier ?? "com.noname.app")
}
private let encoder = JSONEncoder()
private let decoder = JSONDecoder()
private let restorableDataURL = FileManager.temporaryDirectoryURL.appendingPathComponent("RestorableData") => {
try? FileManager.default.createDirectory(at: $0, withIntermediateDirectories: true, attributes: nil)
}
@propertyWrapper
public struct RestorableData<Value: Codable> {
public struct Publisher: Combine.Publisher {
public typealias Output = Value
public typealias Failure = Never
let subject: CurrentValueSubject<Value, Never>
init(_ value: Value) { self.subject = CurrentValueSubject(value) }
public func receive<S: Subscriber>(subscriber: S) where S.Failure == Self.Failure, S.Input == Self.Output {
self.subject.receive(subscriber: subscriber)
}
}
public let projectedValue: Publisher
public let key: String
public let fileURL: URL
public var wrappedValue: Value {
get { projectedValue.subject.value }
set {
projectedValue.subject.send(newValue)
do { try encoder.encode(newValue).write(to: fileURL) } catch {}
}
}
public init(wrappedValue initialValue: Value, _ key: String) {
self.key = key
self.fileURL = restorableDataURL.appendingPathComponent(key + ".json")
let wrappedValue: Value
do {
wrappedValue = try decoder.decode(Value.self, from: Data(contentsOf: fileURL))
} catch {
wrappedValue = initialValue
}
self.projectedValue = Publisher(wrappedValue)
}
}
final public class NSImageContainer: Codable {
static let dataDirectoryURL = FileManager.temporaryDirectoryURL.appendingPathComponent("NSImageContainer") => {
try? FileManager.default.createDirectory(at: $0, withIntermediateDirectories: true, attributes: nil)
}
public let image: NSImage
public let id: String
public init(_ image: NSImage) {
self.image = image
self.id = UUID().uuidString
}
public static func wrap(_ image: NSImage) -> NSImageContainer { NSImageContainer(image) }
public func encode(to encoder: Encoder) throws {
var container = encoder.singleValueContainer()
try container.encode(id)
let fileURL = NSImageContainer.dataDirectoryURL.appendingPathComponent(id)
if !FileManager.default.fileExists(atPath: fileURL.path) {
try image.tiffRepresentation?.write(to: fileURL)
}
}
public init(from decoder: Decoder) throws {
let container = try decoder.singleValueContainer()
let id = try container.decode(String.self)
let fileURL = NSImageContainer.dataDirectoryURL.appendingPathComponent(id)
guard let image = NSImage(contentsOf: fileURL) else {
throw DecodingError.dataCorrupted(DecodingError.Context(codingPath: [], debugDescription: "No image"))
}
self.image = image
self.id = id
}
}
================================================
FILE: CoreUtil/CoreUtil/Class/RestorableState.swift
================================================
//
// RestorableState.swift
// CoreUtil
//
// Created by yuki on 2022/02/03.
//
import Foundation
@propertyWrapper
public struct RestorableState<Value: RawRepresentable> {
public struct Publisher: Combine.Publisher {
public typealias Output = Value
public typealias Failure = Never
let subject: CurrentValueSubject<Value, Never>
init(_ value: Value) { self.subject = CurrentValueSubject(value) }
public func receive<S: Subscriber>(subscriber: S) where S.Failure == Self.Failure, S.Input == Self.Output {
self.subject.receive(subscriber: subscriber)
}
}
public let projectedValue: Publisher
public let key: String
public var wrappedValue: Value {
get { projectedValue.subject.value }
set {
projectedValue.subject.send(newValue)
UserDefaults.standard.set(newValue.rawValue, forKey: key)
}
}
public init(wrappedValue initialValue: Value, _ key: String) {
let wrappedValue: Value
if let rawValue = UserDefaults.standard.object(forKey: key) as? Value.RawValue, let value = Value(rawValue: rawValue) {
wrappedValue = value
} else {
wrappedValue = initialValue
}
self.projectedValue = Publisher(wrappedValue)
self.key = key
}
}
extension String: RawRepresentable {
public var rawValue: Self { self }
public init(rawValue: Self) { self = rawValue }
}
extension Bool: RawRepresentable {
public var rawValue: Self { self }
public init(rawValue: Self) { self = rawValue }
}
extension Optional: RawRepresentable {
public var rawValue: Self { self }
public init(rawValue: Self) { self = rawValue }
}
extension Int: RawRepresentable {
public var rawValue: Self { self }
public init(rawValue: Self) { self = rawValue }
}
extension CGFloat: RawRepresentable {
public var rawValue: Self { self }
public init(rawValue: Self) { self = rawValue }
}
extension Double: RawRepresentable {
public var rawValue: Self { self }
public init(rawValue: Self) { self = rawValue }
}
================================================
FILE: CoreUtil/CoreUtil/Class/Terminal.swift
================================================
//
// Terminal.swift
// CoreUtil
//
// Created by yuki on 2022/02/11.
//
import Foundation
public enum TerminalError: Error, CustomStringConvertible {
case nonZeroExit(String)
public var description: String {
switch self {
case .nonZeroExit(let string): return string
}
}
}
public enum Terminal {
public struct ExecuteOption: OptionSet {
public let rawValue: UInt64
public init(rawValue: UInt64) { self.rawValue = rawValue }
public static let standardOutput = ExecuteOption(rawValue: 1 << 0)
public static let standardError = ExecuteOption(rawValue: 1 << 1)
}
public static func run(_ executableURL: URL, arguments: [String], queue: DispatchQueue = .global(), options: ExecuteOption = .all) -> Promise<String, Error> {
let task = Process()
let outputPipe = Pipe()
let errorPipe = Pipe()
task.executableURL = executableURL
task.arguments = arguments
if options.contains(.standardOutput) {
task.standardOutput = outputPipe
}
if options.contains(.standardError) {
task.standardError = errorPipe
}
return Promise<String, Error>.tryAsync(on: queue) { resolve, reject in
try task.run()
task.waitUntilExit()
if task.terminationStatus != 0 {
reject(TerminalError.nonZeroExit(errorPipe.readStringToEndOfFile ?? "[binary]"))
} else {
resolve(outputPipe.readStringToEndOfFile ?? "[binary]")
}
}
}
}
extension Pipe {
public var readStringToEndOfFile: String? {
String(data: self.fileHandleForReading.readDataToEndOfFile(), encoding: .utf8)
}
}
================================================
FILE: CoreUtil/CoreUtil/Class/ViewPlaceholder.swift
================================================
//
// ViewPlaceholder.swift
// CoreUtil
//
// Created by yuki on 2021/06/03.
// Copyright © 2021 yuki. All rights reserved.
//
import Cocoa
import Combine
open class NSPlaceholderView<View: NSView>: NSLoadView {
public var contentView: View? {
didSet {
oldValue?.removeFromSuperview()
if let contentView = contentView {
self.addSubview(contentView)
contentView.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
contentView.rightAnchor.constraint(equalTo: self.rightAnchor),
contentView.leftAnchor.constraint(equalTo: self.leftAnchor),
contentView.topAnchor.constraint(equalTo: self.topAnchor),
contentView.bottomAnchor.constraint(equalTo: self.bottomAnchor),
])
}
}
}
}
================================================
FILE: CoreUtil/CoreUtil/Class/Zip3Sequence.swift
================================================
//
// Zip3Sequence.swift
// CoreUtil
//
// Created by yuki on 2022/01/22.
// Copyright © 2022 yuki. All rights reserved.
//
public func zip<A: Sequence, B: Sequence, C: Sequence>(_ a: A, _ b: B, _ c: C) -> Zip3Sequence<A, B, C> {
Zip3Sequence(a, b, c)
}
public func zip<A: Sequence, B: Sequence, C: Sequence, D: Sequence>(_ a: A, _ b: B, _ c: C, _ d: D) -> Zip4Sequence<A, B, C, D> {
Zip4Sequence(a, b, c, d)
}
public struct Zip3Sequence<A: Sequence, B: Sequence, C: Sequence>: Sequence {
public typealias Element = (A.Element, B.Element, C.Element)
public let a: A
public let b: B
public let c: C
public struct Iterator: IteratorProtocol {
var a: A.Iterator
var b: B.Iterator
var c: C.Iterator
mutating public func next() -> Element? {
if let a = a.next(), let b = b.next(), let c = c.next() { return (a, b, c) }; return nil
}
}
public func makeIterator() -> Iterator { Iterator(a: a.makeIterator(), b: b.makeIterator(), c: c.makeIterator()) }
init(_ a: A, _ b: B, _ c: C) {
self.a = a
self.b = b
self.c = c
}
}
public struct Zip4Sequence<A: Sequence, B: Sequence, C: Sequence, D: Sequence>: Sequence {
public typealias Element = (A.Element, B.Element, C.Element, D.Element)
public let a: A
public let b: B
public let c: C
public let d: D
public struct Iterator: IteratorProtocol {
var a: A.Iterator
var b: B.Iterator
var c: C.Iterator
var d: D.Iterator
mutating public func next() -> Element? {
if let a = a.next(), let b = b.next(), let c = c.next(), let d = d.next() { return (a, b, c, d) }; return nil
}
}
public func makeIterator() -> Iterator { Iterator(a: a.makeIterator(), b: b.makeIterator(), c: c.makeIterator(), d: d.makeIterator()) }
init(_ a: A, _ b: B, _ c: C, _ d: D) {
self.a = a
self.b = b
self.c = c
self.d = d
}
}
================================================
FILE: CoreUtil/CoreUtil/CoreUtil.h
================================================
//
// CoreUtil.h
// CoreUtil
//
// Created by yuki on 2022/01/29.
//
#import <Foundation/Foundation.h>
#import "ExceptionHanlder.h"
//! Project version number for CoreUtil.
FOUNDATION_EXPORT double CoreUtilVersionNumber;
//! Project version string for CoreUtil.
FOUNDATION_EXPORT const unsigned char CoreUtilVersionString[];
// In this header, you should import all the public headers of your framework using statements like #import <CoreUtil/PublicHeader.h>
================================================
FILE: CoreUtil/CoreUtil/ExceptionHanlder/ExceptionHandler.swift
================================================
//
// ExceptionHandler.swift
// CoreUtil
//
// Created by yuki on 2021/06/26.
// Copyright © 2021 yuki. All rights reserved.
//
@inlinable public func objc_try(_ tryBlock: () -> ()) throws {
var error: NSError?
_ExceptionHandler.objc_try(tryBlock, objc_catch: {
error = NSError(domain: "NSException", code: 999, userInfo: $0.userInfo?.reduce(into: [:]) { $0["\($1.key)"] = $1.value })
}, objc_finally: {})
if let error = error { throw error }
}
@inlinable public func objc_try<T>(_ tryBlock: () -> T) throws -> T {
var value: T?
var error: NSError?
_ExceptionHandler.objc_try({
value = tryBlock()
}, objc_catch: {
error = NSError(domain: "NSException", code: 999, userInfo: $0.userInfo?.reduce(into: [:]) { $0["\($1.key)"] = $1.value })
}, objc_finally: {})
if let error = error { throw error }
return value!
}
@inlinable public func objc_try(_ tryBlock: () -> (), catch catchBlock: (NSException) -> (), finally finallyBlock: () -> () = {}) {
_ExceptionHandler.objc_try(tryBlock, objc_catch: catchBlock, objc_finally: finallyBlock)
}
@inlinable public func objc_try<T>(_ tryBlock: () -> T, catch catchBlock: (NSException) -> T, finally finallyBlock: () -> () = {}) -> T {
var value: T!
_ExceptionHandler.objc_try({
value = tryBlock()
}, objc_catch: {
value = catchBlock($0)
}, objc_finally: finallyBlock)
return value
}
================================================
FILE: CoreUtil/CoreUtil/ExceptionHanlder/ExceptionHanlder.h
================================================
//
// ExceptionHanlder.h
// CoreUtil
//
// Created by yuki on 2021/06/26.
// Copyright © 2021 yuki. All rights reserved.
//
#import <Foundation/Foundation.h>
@interface _ExceptionHandler : NSObject
+ (void)objc_try: (nonnull __attribute__((noescape)) void(^)(void))objc_try
objc_catch: (nonnull __attribute__((noescape)) void(^)(NSException* _Nonnull))objc_catch
objc_finally: (nullable __attribute__((noescape)) void(^)(void))objc_finally;
@end
================================================
FILE: CoreUtil/CoreUtil/ExceptionHanlder/ExceptionHanlder.m
================================================
//
// ExceptionHanlder.m
// CoreUtil
//
// Created by yuki on 2021/06/26.
// Copyright © 2021 yuki. All rights reserved.
//
#import <Foundation/Foundation.h>
#import <ExceptionHanlder.h>
@implementation _ExceptionHandler : NSObject
+ (void)objc_try: (nonnull __attribute__((noescape)) void(^)(void)) objc_try
objc_catch: (nonnull __attribute__((noescape)) void(^)(NSException* _Nonnull)) objc_catch
objc_finally: (nullable __attribute__((noescape)) void(^)(void)) objc_finally {
@try {
objc_try();
} @catch (NSException* exception) {
objc_catch(exception);
} @finally {
if (objc_finally) { objc_finally(); }
}
}
@end
================================================
FILE: CoreUtil/CoreUtil/Export.swift
================================================
//
// Export.swift
// CoreUtil
//
// Created by yuki on 2022/01/29.
//
@_exported import Promise
@_exported import SnapKit
@_exported import Cocoa
@_exported import Combine
================================================
FILE: CoreUtil/CoreUtil/Extensions/Combine/Combine+ObjectBag.swift
================================================
//
// NSObject+Combine.swift
// CoreUtil
//
// Created by yuki on 2020/05/22.
// Copyright © 2020 yuki. All rights reserved.
//
import Foundation
import Combine
private var bagKey: UInt8 = 0
extension NSObject {
public var objectBag: Set<AnyCancellable> {
get { bagContainer.value } set { bagContainer.value = newValue }
}
private class BagContainer {
var value = Set<AnyCancellable>()
}
private var bagContainer: BagContainer {
if let container = objc_getAssociatedObject(self, &bagKey) as? BagContainer { return container }
let container = BagContainer()
objc_setAssociatedObject(self, &bagKey, container, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
return container
}
}
================================================
FILE: CoreUtil/CoreUtil/Extensions/Combine/Combine+Peek.swift
================================================
//
// Combine+Peek.swift
// CoreUtil
//
// Created by yuki on 2022/02/01.
//
import Combine
extension Publisher {
public func peekError(_ block: @escaping (Failure) -> Void) -> Publishers.MapError<Self, Failure> {
self.mapError { f -> Failure in block(f); return f }
}
public func peek(_ block: @escaping (Output) -> Void) -> Publishers.Map<Self, Output> {
self.map { block($0); return $0 }
}
}
================================================
FILE: CoreUtil/CoreUtil/Extensions/Combine/NSControl+Combine.swift
================================================
//
// NSButton+Combine.swift
// CoreUtil
//
// Created by yuki on 2021/07/23.
// Copyright © 2021 yuki. All rights reserved.
//
import Cocoa
import Combine
private var actionPublisherKey = 0
extension NSControl {
final public class Publisher: Combine.Publisher {
public typealias Output = Void
public typealias Failure = Never
final class Target: NSObject {
let subject = PassthroughSubject<Void, Never>()
@objc func action(_ sender: NSControl) { self.subject.send() }
}
let target: Target
init(control: NSControl) {
let target = Target()
control.target = target
control.action = #selector(Target.action)
self.target = target
}
public func receive<S: Subscriber>(subscriber: S) where S.Failure == Failure, S.Input == Output {
self.target.subject.receive(subscriber: subscriber)
}
}
// actionとtargetを設定してpublisherとして出力できるようにします。
public var actionPublisher: Publisher {
if let publisher = objc_getAssociatedObject(self, &actionPublisherKey) as? Publisher { return publisher }
let publisher = Publisher(control: self)
objc_setAssociatedObject(self, &actionPublisherKey, publisher, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
return publisher
}
}
================================================
FILE: CoreUtil/CoreUtil/Extensions/Combine/NSTextField+Combine.swift
================================================
//
// Combine+TextField.swift
// CoreUtil
//
// Created by yuki on 2021/01/03.
// Copyright © 2021 yuki. All rights reserved.
//
import Cocoa
import Combine
private var delegateKey = 0
extension NSTextField {
public var endEditingStringPublisher: AnyPublisher<String, Never> { pubilsherDelegate.endEditingPublisher.map{ $0.stringValue }.eraseToAnyPublisher() }
public var changeStringPublisher: AnyPublisher<String, Never> { pubilsherDelegate.changePublisher.map{ $0.stringValue }.eraseToAnyPublisher() }
public var beginEditingStringPublisher: AnyPublisher<String, Never> { pubilsherDelegate.beginEditingPublisher.map{ $0.stringValue }.eraseToAnyPublisher() }
public var endEditingPublisher: AnyPublisher<NSTextField, Never> { pubilsherDelegate.endEditingPublisher.eraseToAnyPublisher() }
public var changePublisher: AnyPublisher<NSTextField, Never> { pubilsherDelegate.changePublisher.eraseToAnyPublisher() }
public var beginEditingPublisher: AnyPublisher<NSTextField, Never> { pubilsherDelegate.beginEditingPublisher.eraseToAnyPublisher() }
final private class PublisherDelegate: NSObject, NSTextFieldDelegate {
let endEditingPublisher = PassthroughSubject<NSTextField, Never>()
let changePublisher = PassthroughSubject<NSTextField, Never>()
let beginEditingPublisher = PassthroughSubject<NSTextField, Never>()
func controlTextDidBeginEditing(_ obj: Notification) {
guard let textField = obj.object as? NSTextField else { return }
beginEditingPublisher.send(textField)
}
func controlTextDidChange(_ obj: Notification) {
guard let textField = obj.object as? NSTextField else { return }
changePublisher.send(textField)
}
func controlTextDidEndEditing(_ obj: Notification) {
guard let textField = obj.object as? NSTextField else { return }
endEditingPublisher.send(textField)
}
}
private var pubilsherDelegate: PublisherDelegate {
if let delegate = objc_getAssociatedObject(self, &delegateKey) as? PublisherDelegate { return delegate }
let delegate = PublisherDelegate()
objc_setAssociatedObject(self, &delegateKey, delegate, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
assert(self.delegate == nil, "Publisher delegate is not averable. \(delegate)")
self.delegate = delegate
return delegate
}
}
================================================
FILE: CoreUtil/CoreUtil/Extensions/CoreGraphics/Ex+CGPoint.swift
================================================
//
// Ex+CGPoint.swift
// Topica
//
// Created by yuki on 2019/10/27.
// Copyright © 2019 yuki. All rights reserved.
//
import CoreGraphics
@inlinable public func round(_ point: CGPoint) -> CGPoint {
CGPoint(x: round(point.x), y: round(point.y))
}
@inlinable public func ceil(_ point: CGPoint) -> CGPoint {
CGPoint(x: ceil(point.x), y: ceil(point.y))
}
@inlinable public func floor(_ point: CGPoint) -> CGPoint {
CGPoint(x: floor(point.x), y: floor(point.y))
}
@inlinable public func sign(_ point: CGPoint) -> CGPoint {
CGPoint(x: sign(point.x), y: sign(point.y))
}
@inlinable public func min(_ point0: CGPoint, _ point1: CGPoint) -> CGPoint {
CGPoint(x: min(point0.x, point1.x), y: min(point0.y, point1.y))
}
@inlinable public func max(_ point0: CGPoint, _ point1: CGPoint) -> CGPoint {
CGPoint(x: max(point0.x, point1.x), y: max(point0.y, point1.y))
}
@inlinable public func abs(_ point: CGPoint) -> CGFloat {
sqrt(point.x * point.x + point.y * point.y)
}
@inlinable public func abs2(_ point: CGPoint) -> CGFloat {
point.x * point.x + point.y * point.y
}
@inlinable public func clamp(_ point: CGPoint, in rect: CGRect) -> CGPoint {
CGPoint(x: clamp(point.x, into: rect.minX...rect.maxX), y: clamp(point.y, into: rect.minY...rect.maxY))
}
@inlinable public func dot(_ point0: CGPoint, _ point1: CGPoint) -> CGFloat {
point0.x * point1.x + point0.y * point1.y
}
extension CGPoint {
public static let infinity = CGSize(width: CGFloat.infinity, height: .infinity)
@inlinable public func convertToSize() -> CGSize {
CGSize(width: x, height: y)
}
@inlinable public var unitVector: CGPoint {
let absValue = abs(self)
if absValue == 0 { return .zero }
return self / absValue
}
@inlinable public var isFinite: Bool {
x.isFinite && y.isFinite
}
}
extension CGPoint {
@inlinable public func map(_ tranceform: (CGFloat) -> (CGFloat)) -> CGPoint {
mapX(tranceform).mapY(tranceform)
}
@inlinable public func mapX(_ tranceform: (CGFloat) -> (CGFloat)) -> CGPoint {
CGPoint(x: tranceform(x), y: y)
}
@inlinable public func mapY(_ tranceform: (CGFloat) -> (CGFloat)) -> CGPoint {
CGPoint(x: x, y: tranceform(y))
}
}
extension CGPoint: ExpressibleByArrayLiteral {
@inlinable public init(arrayLiteral elements: CGFloat...) {
assert(elements.count == 2)
self.init(x: elements[0], y: elements[1])
}
}
extension CGPoint: Hashable {
@inlinable public func hash(into hasher: inout Hasher) {
hasher.combine(x)
hasher.combine(y)
}
}
extension CGPoint: AdditiveArithmetic {
@inlinable public static func + (lhs: CGPoint, rhs: CGPoint) -> CGPoint {
CGPoint(x: lhs.x + rhs.x, y: lhs.y + rhs.y)
}
@inlinable public static func - (lhs: CGPoint, rhs: CGPoint) -> CGPoint {
CGPoint(x: lhs.x - rhs.x, y: lhs.y - rhs.y)
}
@inlinable public static prefix func - (lhs: CGPoint) -> CGPoint {
CGPoint(x: -lhs.x, y: -lhs.y)
}
@inlinable public static func += (lhs: inout CGPoint, rhs: CGPoint) {
lhs = CGPoint(x: lhs.x + rhs.x, y: lhs.y + rhs.y)
}
@inlinable public static func -= (lhs: inout CGPoint, rhs: CGPoint) {
lhs = CGPoint(x: lhs.x - rhs.x, y: lhs.y - rhs.y)
}
}
extension CGPoint {
@inlinable public static func * (lhs: CGPoint, rhs: CGFloat) -> CGPoint {
return CGPoint(x: lhs.x * rhs, y: lhs.y * rhs)
}
@inlinable public static func * (lhs: CGPoint, rhs: CGPoint) -> CGPoint {
return CGPoint(x: lhs.x * rhs.x, y: lhs.y * rhs.y)
}
@inlinable public static func / (lhs: CGPoint, rhs: CGFloat) -> CGPoint {
return CGPoint(x: lhs.x / rhs, y: lhs.y / rhs)
}
@inlinable public static func / (lhs: CGPoint, rhs: CGPoint) -> CGPoint {
return CGPoint(x: lhs.x / rhs.x, y: lhs.y / rhs.y)
}
@inlinable public static func *= (lhs: inout CGPoint, rhs: CGFloat) {
lhs = CGPoint(x: lhs.x * rhs, y: lhs.y * rhs)
}
@inlinable public static func /= (lhs: inout CGPoint, rhs: CGFloat) {
lhs = CGPoint(x: lhs.x / rhs, y: lhs.y / rhs)
}
}
================================================
FILE: CoreUtil/CoreUtil/Extensions/CoreGraphics/Ex+CGRect.swift
================================================
//
// Ex+CGRect.swift
// CoreUtil
//
// Created by yuki on 2020/02/03.
// Copyright © 2020 yuki. All rights reserved.
//
import Foundation
@inlinable public func round(_ rect: CGRect) -> CGRect {
CGRect(origin: round(rect.origin), end: round(rect.end))
}
extension CGRect {
@inlinable public var center: CGPoint {
@inlinable get { CGPoint(x: midX, y: midY) }
@inlinable set { self.origin = CGPoint(x: newValue.x - width/2, y: newValue.y - height/2) }
}
@inlinable public var end: CGPoint {
@inlinable get { CGPoint(x: maxX, y: maxY) }
@inlinable set { self.origin = CGPoint(x: newValue.x - width, y: newValue.y - height) }
}
@inlinable public func fattened(by inset: CGFloat) -> CGRect {
CGRect(origin: self.origin - [inset, inset], size: self.size + [inset, inset]*2)
}
@inlinable public func slimmed(by inset: CGFloat) -> CGRect {
CGRect(origin: self.origin + [inset, inset], size: self.size - [inset, inset]*2)
}
@inlinable public func fattened(by edgeInsets: NSEdgeInsets) -> CGRect {
CGRect(origin: self.origin - [edgeInsets.left, edgeInsets.bottom],
size: self.size + [edgeInsets.left + edgeInsets.right, edgeInsets.top + edgeInsets.bottom])
}
@inlinable public func slimmed(by edgeInsets: NSEdgeInsets) -> CGRect {
CGRect(origin: self.origin + [edgeInsets.left, edgeInsets.bottom],
size: self.size - [edgeInsets.left + edgeInsets.right, edgeInsets.top + edgeInsets.bottom])
}
}
extension CGRect {
@inlinable public func mapOrigin(_ tranceform: (CGPoint) -> (CGPoint)) -> CGRect {
CGRect(origin: tranceform(origin), size: size)
}
@inlinable public func mapCenter(_ tranceform: (CGPoint) -> (CGPoint)) -> CGRect {
CGRect(center: tranceform(center), size: size)
}
@inlinable public func mapEnd(_ tranceform: (CGPoint) -> (CGPoint)) -> CGRect {
CGRect(end: tranceform(end), size: size)
}
@inlinable public func mapSizePreservingOrigin(_ tranceform: (CGSize) -> (CGSize)) -> CGRect {
CGRect(origin: origin, size: tranceform(size))
}
@inlinable public func mapSizePreservingCenter(_ tranceform: (CGSize) -> (CGSize)) -> CGRect {
CGRect(center: center, size: tranceform(size))
}
@inlinable public func mapSizePreservingEnd(_ tranceform: (CGSize) -> (CGSize)) -> CGRect {
CGRect(end: end, size: tranceform(size))
}
}
extension CGRect {
@inlinable public init(origin: CGPoint) {
self.init(origin: origin, size: .zero)
}
@inlinable public init(size: CGSize) {
self.init(origin: .zero, size: size)
}
@inlinable public init(origin: CGPoint, end: CGPoint) {
self.init(origin: origin, size: (end - origin).convertToSize())
}
@inlinable public init(center: CGPoint, size: CGSize) {
self.init(origin: center - size.convertToPoint() / 2, size: size)
}
@inlinable public init(end: CGPoint, size: CGSize) {
self.init(origin: end - size.convertToPoint(), size: size)
}
@inlinable public init(originX: CGFloat, centerY: CGFloat, size: CGSize) {
self.init(origin: [originX, centerY - size.height/2], size: size)
}
@inlinable public init(centerX: CGFloat, originY: CGFloat, size: CGSize) {
self.init(origin: [centerX - size.width/2, originY], size: size)
}
@inlinable public var isFinite: Bool {
size.isFinite && origin.isFinite
}
}
extension CGRect {
@inlinable public static func + (lhs: CGRect, rhs: CGRect) -> CGRect {
CGRect(origin: lhs.origin + rhs.origin, size: lhs.size + rhs.size)
}
@inlinable public static func - (lhs: CGRect, rhs: CGRect) -> CGRect {
CGRect(origin: lhs.origin - rhs.origin, size: lhs.size - rhs.size)
}
}
extension CGRect: Hashable {
@inlinable public func hash(into hasher: inout Hasher) {
hasher.combine(size)
hasher.combine(origin)
}
}
extension Collection where Element == CGRect {
@inlinable public var enclosingRect: CGRect {
if self.isEmpty { return .zero }
var minX: CGFloat = .infinity
var minY: CGFloat = .infinity
var maxX: CGFloat = -.infinity
var maxY: CGFloat = -.infinity
for rect in self {
if minX > rect.origin.x { minX = rect.origin.x }
if minY > rect.origin.y { minY = rect.origin.y }
let _maxX = rect.origin.x + rect.size.width
if maxX < _maxX { maxX = _maxX }
let _maxY = rect.origin.y + rect.size.height
if maxY < _maxY { maxY = _maxY }
}
let rect = CGRect(origin: [minX, minY], end: [maxX, maxY])
return rect
}
}
extension FloatingPoint {
@inlinable public func isFiniteOrZero() -> Self { isFinite ? self : .zero }
}
extension CGPoint {
@inlinable public func isFiniteOrZero() -> CGPoint { isFinite ? self : .zero }
}
extension CGSize {
@inlinable public func isFiniteOrZero() -> CGSize { isFinite ? self : .zero }
}
extension CGRect {
@inlinable public func isFiniteOrZero() -> CGRect { isFinite ? self : .zero }
}
================================================
FILE: CoreUtil/CoreUtil/Extensions/CoreGraphics/Ex+CGSize.swift
================================================
import CoreGraphics
@inlinable public func round(_ size: CGSize) -> CGSize {
CGSize(width: round(size.width), height: round(size.height))
}
@inlinable public func abs(_ size: CGSize) -> CGSize {
CGSize(width: abs(size.width), height: abs(size.height))
}
@inlinable public func sign(_ size: CGSize) -> CGSize {
CGSize(width: sign(size.width), height: sign(size.height))
}
@inlinable public func min(_ size0: CGSize, _ size1: CGSize) -> CGSize {
CGSize(width: min(size0.width, size1.width), height: min(size0.height, size1.height))
}
@inlinable public func max(_ size0: CGSize, _ size1: CGSize) -> CGSize {
CGSize(width: max(size0.width, size1.width), height: max(size0.height, size1.height))
}
extension CGSize {
@inlinable public func convertToPoint() -> CGPoint {
CGPoint(x: width, y: height)
}
@inlinable public var minElement: CGFloat {
min(abs(self.width), abs(self.height))
}
@inlinable public var maxElement: CGFloat {
max(abs(self.width), abs(self.height))
}
@inlinable public var isFinite: Bool {
width.isFinite && height.isFinite
}
public static let infinity = CGSize(width: CGFloat.infinity, height: .infinity)
}
extension CGSize {
@inlinable public func mapWidth(_ tranceform: (CGFloat) -> (CGFloat)) -> CGSize {
CGSize(width: tranceform(width), height: height)
}
@inlinable public func mapHeight(_ tranceform: (CGFloat) -> (CGFloat)) -> CGSize {
CGSize(width: width, height: tranceform(height))
}
}
extension CGSize: ExpressibleByArrayLiteral {
public init(arrayLiteral elements: CGFloat...) {
assert(elements.count == 2)
self.init(width: elements[0], height: elements[1])
}
}
extension CGSize: AdditiveArithmetic {
@inlinable public static func + (lhs: CGSize, rhs: CGSize) -> CGSize {
CGSize(width: lhs.width + rhs.width, height: lhs.height + rhs.height)
}
@inlinable public static func - (lhs: CGSize, rhs: CGSize) -> CGSize {
CGSize(width: lhs.width - rhs.width, height: lhs.height - rhs.height)
}
@inlinable public static prefix func - (lhs: CGSize) -> CGSize {
CGSize(width: -lhs.width, height: -lhs.height)
}
}
extension CGSize {
@inlinable public static func * (lhs: CGSize, rhs: CGFloat) -> CGSize {
return CGSize(width: lhs.width * rhs, height: lhs.height * rhs)
}
@inlinable public static func * (lhs: CGSize, rhs: CGSize) -> CGSize {
return CGSize(width: lhs.width * rhs.width, height: lhs.height * rhs.height)
}
@inlinable public static func / (lhs: CGSize, rhs: CGFloat) -> CGSize {
return CGSize(width: lhs.width / rhs, height: lhs.height / rhs)
}
@inlinable public static func / (lhs: CGSize, rhs: CGSize) -> CGSize {
return CGSize(width: lhs.width / rhs.width, height: lhs.height / rhs.height)
}
@inlinable public static func *= (lhs: inout CGSize, rhs: CGFloat) {
lhs.width *= rhs
lhs.height *= rhs
}
@inlinable public static func /= (lhs: inout CGSize, rhs: CGFloat) {
lhs.width /= rhs
lhs.height /= rhs
}
}
extension CGSize: Hashable {
@inlinable public func hash(into hasher: inout Hasher) {
hasher.combine(width)
hasher.combine(height)
}
}
extension CGSize {
/// boundingBoxにアスペクトフィットするのに必要な変換レートを返します。
@inlinable public func aspectFitRatio(fitInside boundingBox: CGSize) -> CGFloat {
let mW = boundingBox.width / self.width
let mH = boundingBox.height / self.height
if mH > mW {
return boundingBox.width / self.width
} else {
return boundingBox.height / self.height
}
}
/// boundingBoxにアスペクトフィルするのに必要な変換レートを返します。
@inlinable public func aspectFillRatio(fillInside boundingBox: CGSize) -> CGFloat {
let mW = boundingBox.width / self.width
let mH = boundingBox.height / self.height
if mH < mW {
return boundingBox.width / self.width
} else {
return boundingBox.height / self.height
}
}
}
================================================
FILE: CoreUtil/CoreUtil/Extensions/Swift/Ex+Array.swift
================================================
//
// Extensions.swift
// DANMAKER
//
// Created by yuki on 2015/06/24.
// Copyright © 2015 yuki. All rights reserved.
//
extension RandomAccessCollection {
@inlinable public func at(_ index: Self.Index) -> Element? {
self.indices.contains(index) ? self[index] : nil
}
}
extension Sequence {
@inlinable public func count(where condition: (Element) throws -> Bool) rethrows -> Int {
try self.lazy.filter(condition).count
}
@inlinable public func count(while condition: (Element) throws -> Bool) rethrows -> Int {
var count = 0
for element in self {
if try !condition(element) { return count }
count += 1
}
return count
}
@inlinable public func firstSome<T>(where condition: (Element) throws -> T?) rethrows -> T? {
try self.lazy.compactMap(condition).first
}
@inlinable public func allSome<T>(_ tranceform: (Element) throws -> T?) rethrows -> [T]? {
var values = [T]()
for element in self {
guard let element = try tranceform(element) else { return nil }
values.append(element)
}
return values
}
}
extension Array {
public mutating func move(fromIndex: Int, toIndex: Int) {
assert(indices.contains(fromIndex), "fromIndex '\(fromIndex)' is out of bounds.")
if fromIndex == toIndex { return }
let removed = self.remove(at: fromIndex)
if fromIndex < toIndex {
self.insert(removed, at: toIndex - 1)
} else {
self.insert(removed, at: toIndex)
}
}
public mutating func move<Range: RangeExpression>(fromRange: Range, toIndex: Int) where Range.Bound == Int {
assert(indices.contains(toIndex), "toIndex '\(toIndex)' is out of bounds.")
let range = fromRange.relative(to: self)
if range.contains(toIndex) { return }
let removed = self[range]
self.removeSubrange(range)
if range.upperBound < toIndex + range.count - 1 {
self.insert(contentsOf: removed, at: toIndex - range.count + 1)
} else {
self.insert(contentsOf: removed, at: toIndex)
}
}
}
extension Array {
@discardableResult
@inlinable public mutating func removeFirst(where condition: (Element) throws -> Bool) rethrows -> Element? {
for i in 0..<self.count {
if try condition(self[i]) { return remove(at: i) }
}
return nil
}
}
// MARK: - Equatable Array Extensions
extension Array where Element: Equatable {
@inlinable @discardableResult public mutating func removeFirst(_ element: Element) -> Element? {
for index in 0..<count where self[index] == element {
return remove(at: index)
}
return nil
}
}
extension Sequence where Element: Comparable {
@inlinable public func max(_ replace: Element) -> Element { self.max() ?? replace }
@inlinable public func min(_ replace: Element) -> Element { self.min() ?? replace }
}
extension Dictionary {
public mutating func arrayAppend<T>(_ value: T, forKey key: Key) where Self.Value == Array<T> {
if self[key] == nil { self[key] = [] }
self[key]!.append(value)
}
public mutating func arrayAppend<T, S: Sequence>(contentsOf newElements: S, forKey key: Key) where Self.Value == Array<T>, S.Element == T {
if self[key] == nil { self[key] = [] }
self[key]!.append(contentsOf: newElements)
}
}
================================================
FILE: CoreUtil/CoreUtil/Extensions/Swift/Ex+Clamp.swift
================================================
//
// Ex+Comparable.swift
// CoreUtil
//
// Created by yuki on 2020/04/01.
// Copyright © 2020 yuki. All rights reserved.
//
public func clamp<Target: Comparable>(_ x: Target, into range: ClosedRange<Target>) -> Target {
max(range.lowerBound, min(x, range.upperBound))
}
public func clamp<Target: Comparable>(_ x: Target, into range: PartialRangeFrom<Target>) -> Target {
max(range.lowerBound, x)
}
public func clamp<Target: Comparable>(_ x: Target, into range: PartialRangeThrough<Target>) -> Target {
min(range.upperBound, x)
}
extension Strideable {
public func clamped(_ range: Range<Self>) -> Self {
max(range.lowerBound, min(self, range.upperBound.advanced(by: -1)))
}
}
extension Comparable {
public func clamped(_ range: ClosedRange<Self>) -> Self {
clamp(self, into: range)
}
public func clamped(_ range: PartialRangeFrom<Self>) -> Self {
clamp(self, into: range)
}
public func clamped(_ range: PartialRangeThrough<Self>) -> Self {
clamp(self, into: range)
}
}
================================================
FILE: CoreUtil/CoreUtil/Extensions/Swift/Ex+Localize.swift
================================================
//
// Ex+Localize.swift
// CoreUtil
//
// Created by yuki on 2022/02/13.
//
import Foundation
extension String {
public func localized() -> String {
NSLocalizedString(self, comment: self)
}
}
================================================
FILE: CoreUtil/CoreUtil/Extensions/Swift/Ex+Number.swift
================================================
//
// Ex+NUmber.swift
// CoreUtil
//
// Created by yuki on 2020/06/24.
// Copyright © 2020 yuki. All rights reserved.
//
/// Returns `1` when the value greater than or equals to `0`. And returns `-1` when the value smaller than `0`
@inlinable public func sign<T: SignedNumeric & Comparable>(_ value: T) -> T {
if value >= T.zero {
return 1
} else {
return -1
}
}
extension Double {
@inlinable public func rounded(toDecimal fractionDigits: Int) -> Self {
let multiplier = pow(10, Self(fractionDigits))
return Darwin.round(self * multiplier) / multiplier
}
}
extension Float {
@inlinable public func rounded(toDecimal fractionDigits: Int) -> Self {
let multiplier = pow(10, Self(fractionDigits))
return Darwin.round(self * multiplier) / multiplier
}
}
extension CGFloat {
@inlinable public func rounded(toDecimal fractionDigits: Int) -> Self {
let multiplier = pow(10, Self(fractionDigits))
return Darwin.round(self * multiplier) / multiplier
}
}
================================================
FILE: CoreUtil/CoreUtil/Extensions/Swift/Ex+OptionSet.swift
================================================
//
// Ex+OptionSet.swift
// CoreUtil
//
// Created by yuki on 2020/04/13.
// Copyright © 2020 yuki. All rights reserved.
//
extension OptionSet where RawValue: FixedWidthInteger {
public static var all: Self { Self(rawValue: RawValue.max) }
public static var none: Self { [] }
}
================================================
FILE: CoreUtil/CoreUtil/Extensions/UI/Ex+CALayer.swift
================================================
//
// Ex+CALayer.swift
// CoreUtil
//
// Created by yuki on 2020/06/23.
// Copyright © 2020 yuki. All rights reserved.
//
import Cocoa
extension CALayer {
public static func animationDisabled() -> Self {
let layer = Self.init()
layer.areAnimationsEnabled = false
return layer
}
}
extension CALayer {
@objc public var areAnimationsEnabled: Bool {
get { delegate === CALayerAnimationsDisablingDelegate.shared }
set { delegate = newValue ? nil : CALayerAnimationsDisablingDelegate.shared }
}
}
private class CALayerAnimationsDisablingDelegate: NSObject, CALayerDelegate {
public static let shared = CALayerAnimationsDisablingDelegate()
let null = NSNull()
func action(for layer: CALayer, forKey event: String) -> CAAction? { null }
}
================================================
FILE: CoreUtil/CoreUtil/Extensions/UI/Ex+Image.swift
================================================
//
// Ex+Image.swift
// CoreUtil
//
// Created by yuki on 2020/03/10.
// Copyright © 2020 yuki. All rights reserved.
//
import Cocoa
extension NSImage {
public var cgImage: CGImage? {
var imageRect = CGRect(size: self.size)
return cgImage(forProposedRect: &imageRect, context: nil, hints: nil)
}
}
extension CGImage {
public func convertToGrayscale() -> CGImage {
let imageRect = CGRect(size: CGSize(width: width, height: height))
let context = CGContext(
data: nil, width: self.width, height: self.height,
bitsPerComponent: 8, bytesPerRow: 0,
space: CGColorSpaceCreateDeviceGray(), bitmapInfo: CGImageAlphaInfo.none.rawValue
)!
context.draw(self, in: imageRect)
return context.makeImage()!
}
}
================================================
FILE: CoreUtil/CoreUtil/Extensions/UI/Ex+NSColor.swift
================================================
import Cocoa
// MARK: - Extension for Color
extension NSColor {
public convenience init(colorSpace: NSColorSpace = .current, hex: Int, alpha: CGFloat = 1.0) {
let red = CGFloat((hex & 0xff_00_00) >> 16) / 255
let green = CGFloat((hex & 0x00_ff_00) >> 8) / 255
let blue = CGFloat((hex & 0x00_00_ff) >> 0) / 255
self.init(colorSpace: colorSpace, red: red, green: green, blue: blue, alpha: alpha)
}
public convenience init(colorSpace: NSColorSpace = .current, red: CGFloat, green: CGFloat, blue: CGFloat, alpha: CGFloat) {
var rgba = [red, green, blue, alpha]
self.init(colorSpace: colorSpace, components: &rgba, count: rgba.count)
}
}
extension NSColorSpace {
public static let current: NSColorSpace = NSScreen.main?.colorSpace ?? NSColorSpace.deviceRGB
}
extension CGColorSpace {
public static let current: CGColorSpace = NSColorSpace.current.cgColorSpace ?? CGColorSpaceCreateDeviceRGB()
}
================================================
FILE: CoreUtil/CoreUtil/Extensions/UI/Ex+NSControl.swift
================================================
//
// Ex+NSControl.swift
// CoreUtil
//
// Created by yuki on 2021/10/28.
// Copyright © 2021 yuki. All rights reserved.
//
import Cocoa
extension NSControl {
public func setTarget(_ target: AnyObject, action: Selector) {
self.target = target
self.action = action
}
public func executeAction() {
guard let object = (target as? NSObject), let action = self.action else { return NSSound.beep() }
if object.responds(to: action) {
object.perform(action, with: self)
}
}
}
================================================
FILE: CoreUtil/CoreUtil/Extensions/UI/Ex+NSEdgeInsets.swift
================================================
//
// Ex+NSEdgeInsets.swift
// CoreUtil
//
// Created by yuki on 2022/01/29.
//
import Cocoa
extension NSEdgeInsets: Equatable {
public static let zero = NSEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)
public static func == (lhs: NSEdgeInsets, rhs: NSEdgeInsets) -> Bool {
lhs.top == rhs.top && lhs.left == rhs.left && lhs.bottom == rhs.bottom && lhs.right == rhs.right
}
public static func each(top: CGFloat = 0, left: CGFloat = 0, bottom: CGFloat = 0, right: CGFloat = 0) -> NSEdgeInsets {
NSEdgeInsets(top: top, left: left, bottom: bottom, right: right)
}
public init(repeating element: CGFloat) {
self.init(top: element, left: element, bottom: element, right: element)
}
public init(x: CGFloat=0, y: CGFloat=0) {
self.init(top: y, left: x, bottom: y, right: x)
}
}
================================================
FILE: CoreUtil/CoreUtil/Extensions/UI/Ex+NSEvent.swift
================================================
//
// NSEvent+Location.swift
// CoreUtil
//
// Created by yuki on 2021/11/11.
// Copyright © 2021 yuki. All rights reserved.
//
import Cocoa
extension NSEvent {
@inlinable public func location(in view: NSView) -> CGPoint {
view.convert(self.locationInWindow, from: nil)
}
}
================================================
FILE: CoreUtil/CoreUtil/Extensions/UI/Ex+NSMenuItem.swift
================================================
//
// Ex+NSMenuItem.swift
// CoreUtil
//
// Created by yuki on 2020/08/20.
// Copyright © 2020 yuki. All rights reserved.
//
import Cocoa
import Combine
private var actionHandlerKey = 0
private var actionPublisherKey = 0
extension NSMenuItem {
public convenience init(title: String, image: NSImage? = nil, isSelected: Bool = false, isEnabled: Bool = true, action: (() -> Void)? = nil) {
self.init()
self.title = title
self.image = image
self.isSelected = isSelected
if let action = action { self.setAction(action) }
}
public var isSelected: Bool {
get { self.state == .on } set { self.state = newValue ? .on : .off }
}
public func setAction(_ block: @escaping () -> ()) {
self.actionHandler.action = block
}
private var actionHandler: ActionHandler {
if let handler = objc_getAssociatedObject(self, &actionHandlerKey) as? ActionHandler { return handler }
let handler = ActionHandler()
self.target = handler
self.action = #selector(ActionHandler.run)
objc_setAssociatedObject(self, &actionHandlerKey, handler, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
return handler
}
final private class ActionHandler {
var action: (() -> ())?
@objc func run(_ sender: Any?) { self.action?() }
}
}
extension NSMenu {
public func addItem(title: String, image: NSImage? = nil, isSelected: Bool = false, isEnabled: Bool = true, action: (() -> Void)?) {
let item = NSMenuItem(title: title, image: image, isSelected: isSelected, isEnabled: isEnabled, action: action)
self.addItem(item)
}
}
================================================
FILE: CoreUtil/CoreUtil/Extensions/UI/Ex+NSPopover.swift
================================================
//
// Ex+NSPopover.swift
// CoreUtil
//
// Created by yuki on 2021/05/31.
// Copyright © 2021 yuki. All rights reserved.
//
import Cocoa
import Combine
extension NSPopover {
public var willClosePublisher: AnyPublisher<Void, Never> { publisherDelegate.willClosePublisher.eraseToAnyPublisher() }
public var willShowPublisher: AnyPublisher<Void, Never> { publisherDelegate.willShowPublisher.eraseToAnyPublisher() }
public var didClosePublisher: AnyPublisher<Void, Never> { publisherDelegate.didClosePublisher.eraseToAnyPublisher() }
public var didShowPublisher: AnyPublisher<Void, Never> { publisherDelegate.didShowPublisher.eraseToAnyPublisher() }
public var didDetachPublisher: AnyPublisher<Void, Never> { publisherDelegate.didDetachPublisher.eraseToAnyPublisher() }
private static var delegateKey = 0
private var publisherDelegate: PublisherDelegate {
if let delegate = objc_getAssociatedObject(self, &Self.delegateKey) as? PublisherDelegate { return delegate }
let delegate = PublisherDelegate()
self.delegate = delegate
objc_setAssociatedObject(self, &Self.delegateKey, delegate, .OBJC_ASSOCIATION_RETAIN)
return delegate
}
final private class PublisherDelegate: NSObject, NSPopoverDelegate {
let willClosePublisher = PassthroughSubject<Void, Never>()
let willShowPublisher = PassthroughSubject<Void, Never>()
let didClosePublisher = PassthroughSubject<Void, Never>()
let didShowPublisher = PassthroughSubject<Void, Never>()
let didDetachPublisher = PassthroughSubject<Void, Never>()
func popoverWillClose(_ notification: Notification) { willClosePublisher.send() }
func popoverWillShow(_ notification: Notification) { willShowPublisher.send() }
func popoverDidDetach(_ popover: NSPopover) { didDetachPublisher.send() }
func popoverDidShow(_ notification: Notification) { didShowPublisher.send() }
func popoverDidClose(_ notification: Notification) { didClosePublisher.send() }
}
}
================================================
FILE: CoreUtil/CoreUtil/Extensions/UI/Ex+NSTableView.swift
================================================
//
// Ex+NSTableView.swift
// CoreUtil
//
// Created by yuki on 2022/01/29.
//
import Cocoa
extension NSTableView {
public static let listColumnIdentifier = NSUserInterfaceItemIdentifier("$_column")
public func becomeListStyle() {
let column = NSTableColumn(identifier: Self.listColumnIdentifier)
column.resizingMask = .autoresizingMask
// column
self.addTableColumn(column)
self.columnAutoresizingStyle = .firstColumnOnlyAutoresizingStyle
self.allowsColumnResizing = false
self.allowsColumnSelection = false
// appearance
self.headerView = nil
self.intercellSpacing = .zero
self.focusRingType = .none
// behavior
self.allowsEmptySelection = true
self.allowsMultipleSelection = false
self.backgroundColor = .clear
if #available(OSX 11.0, *) { self.style = .plain }
}
/// 1コラムのみのTableView
public static func list() -> Self {
let tableView = Self()
tableView.becomeListStyle()
return tableView
}
}
================================================
FILE: CoreUtil/CoreUtil/Extensions/UI/Ex+UI.swift
================================================
import Cocoa
public let NSOutlineViewNotificationItemKey = "NSObject"
extension NSView {
#if DEBUG
public func __setBackgroundColor(_ color: NSColor) {
self.wantsLayer = true
self.layer?.backgroundColor = color.cgColor
}
#endif
}
================================================
FILE: CoreUtil/CoreUtil/HotKey/HotKey.swift
================================================
//
// KeyboardShortcut.swift
// ListView
//
// Created by yuki on 2021/06/28.
//
import Carbon
import Cocoa
public struct HotKey: Hashable {
public let key: Key?
public let modifiers: NSEvent.ModifierFlags
public init(_ key: Key?, _ modifiers: NSEvent.ModifierFlags = []) {
self.key = key
self.modifiers = modifiers
}
}
extension HotKey {
public static let open = HotKey(.o, .command)
public static let copy = HotKey(.c, .command)
public static let paste = HotKey(.v, .command)
public static let cut = HotKey(.x, .command)
public static let duplicate = HotKey(.d, .command)
public static let save = HotKey(.s, .command)
public static let undo = HotKey(.z, .command)
public static let selectAll = HotKey(.a, .command)
public static let redo = HotKey(.z, [.command, .shift])
public static let go = HotKey(.rightBracket, .command)
public static let back = HotKey(.leftBracket, .command)
public static let print = HotKey(.p, .command)
public static let delete = HotKey(.delete)
public static let tab = HotKey(.tab)
public static let backtab = HotKey(.tab, .shift)
public static let escape = HotKey(.escape)
public static let enter = HotKey(.keypadEnter)
public static let space = HotKey(.space)
public static let `return` = HotKey(.return)
public static let leftArrow = HotKey(.leftArrow, [.numericPad, .function])
public static let rightArrow = HotKey(.rightArrow, [.numericPad, .function])
public static let upArrow = HotKey(.upArrow, [.numericPad, .function])
public static let downArrow = HotKey(.downArrow, [.numericPad, .function])
public static let leftShiftArrow = HotKey(.leftArrow, [.numericPad, .function, .shift])
public static let rightShiftArrow = HotKey(.rightArrow, [.numericPad, .function, .shift])
public static let upShiftArrow = HotKey(.upArrow, [.numericPad, .function, .shift])
public static let downShiftArrow = HotKey(.downArrow, [.numericPad, .function, .shift])
}
extension HotKey: CustomStringConvertible {
public var description: String {
var output = modifiers.description
if let key = key {
output += key.description
}
return output
}
}
extension NSEvent.ModifierFlags: Hashable {
public func hash(into hasher: inout Hasher) {
hasher.combine(rawValue)
}
}
================================================
FILE: CoreUtil/CoreUtil/HotKey/Key.swift
================================================
//
// Key.swift
// ListView
//
// Created by yuki on 2021/06/28.
//
import Carbon
public enum Key {
// MARK: - Letters -
case a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z
// MARK: - Numbers -
case zero, one, two, three, four, five, six, seven, eight, nine
// MARK: - Symbols -
case period, quote, rightBracket, semicolon, slash, backslash, comma, equal, grave, leftBracket, minus
// MARK: - White Spaces -
case space, tab, `return`
// MARK: - Modifiers -
case command, rightCommand, option, rightOption, control, rightControl, shift, rightShift, function, capsLock
// MARK: - Navigation
case pageUp, pageDown, home, end, upArrow, rightArrow, downArrow, leftArrow
// MARK: - Functions
case f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13, f14, f15, f16, f17, f18, f19, f20
// MARK: - Keypad
case keypad0, keypad1, keypad2, keypad3, keypad4, keypad5, keypad6, keypad7, keypad8, keypad9, keypadClear, keypadDecimal, keypadDivide, keypadEnter, keypadEquals, keypadMinus, keypadMultiply, keypadPlus
// MARK: - Misc
case escape, delete, forwardDelete, help, volumeUp, volumeDown, mute
public init?(keyCode: Int) {
switch keyCode {
case kVK_ANSI_A: self = .a
case kVK_ANSI_S: self = .s
case kVK_ANSI_D: self = .d
case kVK_ANSI_F: self = .f
case kVK_ANSI_H: self = .h
case kVK_ANSI_G: self = .g
case kVK_ANSI_Z: self = .z
case kVK_ANSI_X: self = .x
case kVK_ANSI_C: self = .c
case kVK_ANSI_V: self = .v
case kVK_ANSI_B: self = .b
case kVK_ANSI_Q: self = .q
case kVK_ANSI_W: self = .w
case kVK_ANSI_E: self = .e
case kVK_ANSI_R: self = .r
case kVK_ANSI_Y: self = .y
case kVK_ANSI_T: self = .t
case kVK_ANSI_1: self = .one
case kVK_ANSI_2: self = .two
case kVK_ANSI_3: self = .three
case kVK_ANSI_4: self = .four
case kVK_ANSI_6: self = .six
case kVK_ANSI_5: self = .five
case kVK_ANSI_Equal: self = .equal
case kVK_ANSI_9: self = .nine
case kVK_ANSI_7: self = .seven
case kVK_ANSI_Minus: self = .minus
case kVK_ANSI_8: self = .eight
case kVK_ANSI_0: self = .zero
case kVK_ANSI_RightBracket: self = .rightBracket
case kVK_ANSI_O: self = .o
case kVK_ANSI_U: self = .u
case kVK_ANSI_LeftBracket: self = .leftBracket
case kVK_ANSI_I: self = .i
case kVK_ANSI_P: self = .p
case kVK_ANSI_L: self = .l
case kVK_ANSI_J: self = .j
case kVK_ANSI_Quote: self = .quote
case kVK_ANSI_K: self = .k
case kVK_ANSI_Semicolon: self = .semicolon
case kVK_ANSI_Backslash: self = .backslash
case kVK_ANSI_Comma: self = .comma
case kVK_ANSI_Slash: self = .slash
case kVK_ANSI_N: self = .n
case kVK_ANSI_M: self = .m
case kVK_ANSI_Period: self = .period
case kVK_ANSI_Grave: self = .grave
case kVK_ANSI_KeypadDecimal: self = .keypadDecimal
case kVK_ANSI_KeypadMultiply: self = .keypadMultiply
case kVK_ANSI_KeypadPlus: self = .keypadPlus
case kVK_ANSI_KeypadClear: self = .keypadClear
case kVK_ANSI_KeypadDivide: self = .keypadDivide
case kVK_ANSI_KeypadEnter: self = .keypadEnter
case kVK_ANSI_KeypadMinus: self = .keypadMinus
case kVK_ANSI_KeypadEquals: self = .keypadEquals
case kVK_ANSI_Keypad0: self = .keypad0
case kVK_ANSI_Keypad1: self = .keypad1
case kVK_ANSI_Keypad2: self = .keypad2
case kVK_ANSI_Keypad3: self = .keypad3
case kVK_ANSI_Keypad4: self = .keypad4
case kVK_ANSI_Keypad5: self = .keypad5
case kVK_ANSI_Keypad6: self = .keypad6
case kVK_ANSI_Keypad7: self = .keypad7
case kVK_ANSI_Keypad8: self = .keypad8
case kVK_ANSI_Keypad9: self = .keypad9
case kVK_Return: self = .`return`
case kVK_Tab: self = .tab
case kVK_Space: self = .space
case kVK_Delete: self = .delete
case kVK_Escape: self = .escape
case kVK_Command: self = .command
case kVK_Shift: self = .shift
case kVK_CapsLock: self = .capsLock
case kVK_Option: self = .option
case kVK_Control: self = .control
case kVK_RightCommand: self = .rightCommand
case kVK_RightShift: self = .rightShift
case kVK_RightOption: self = .rightOption
case kVK_RightControl: self = .rightControl
case kVK_Function: self = .function
case kVK_F17: self = .f17
case kVK_VolumeUp: self = .volumeUp
case kVK_VolumeDown: self = .volumeDown
case kVK_Mute: self = .mute
case kVK_F18: self = .f18
case kVK_F19: self = .f19
case kVK_F20: self = .f20
case kVK_F5: self = .f5
case kVK_F6: self = .f6
case kVK_F7: self = .f7
case kVK_F3: self = .f3
case kVK_F8: self = .f8
case kVK_F9: self = .f9
case kVK_F11: self = .f11
case kVK_F13: self = .f13
case kVK_F16: self = .f16
case kVK_F14: self = .f14
case kVK_F10: self = .f10
case kVK_F12: self = .f12
case kVK_F15: self = .f15
case kVK_Help: self = .help
case kVK_Home: self = .home
case kVK_PageUp: self = .pageUp
case kVK_ForwardDelete: self = .forwardDelete
case kVK_F4: self = .f4
case kVK_End: self = .end
case kVK_F2: self = .f2
case kVK_PageDown: self = .pageDown
case kVK_F1: self = .f1
case kVK_LeftArrow: self = .leftArrow
case kVK_RightArrow: self = .rightArrow
case kVK_DownArrow: self = .downArrow
case kVK_UpArrow: self = .upArrow
default: return nil
}
}
public var keyCode: Int {
switch self {
case .a: return kVK_ANSI_A
case .s: return kVK_ANSI_S
case .d: return kVK_ANSI_D
case .f: return kVK_ANSI_F
case .h: return kVK_ANSI_H
case .g: return kVK_ANSI_G
case .z: return kVK_ANSI_Z
case .x: return kVK_ANSI_X
case .c: return kVK_ANSI_C
case .v: return kVK_ANSI_V
case .b: return kVK_ANSI_B
case .q: return kVK_ANSI_Q
case .w: return kVK_ANSI_W
case .e: return kVK_ANSI_E
case .r: return kVK_ANSI_R
case .y: return kVK_ANSI_Y
case .t: return kVK_ANSI_T
case .one: return kVK_ANSI_1
case .two: return kVK_ANSI_2
case .three: return kVK_ANSI_3
case .four: return kVK_ANSI_4
case .six: return kVK_ANSI_6
case .five: return kVK_ANSI_5
case .equal: return kVK_ANSI_Equal
case .nine: return kVK_ANSI_9
case .seven: return kVK_ANSI_7
case .minus: return kVK_ANSI_Minus
case .eight: return kVK_ANSI_8
case .zero: return kVK_ANSI_0
case .rightBracket: return kVK_ANSI_RightBracket
case .o: return kVK_ANSI_O
case .u: return kVK_ANSI_U
case .leftBracket: return kVK_ANSI_LeftBracket
case .i: return kVK_ANSI_I
case .p: return kVK_ANSI_P
case .l: return kVK_ANSI_L
case .j: return kVK_ANSI_J
case .quote: return kVK_ANSI_Quote
case .k: return kVK_ANSI_K
case .semicolon: return kVK_ANSI_Semicolon
case .backslash: return kVK_ANSI_Backslash
case .comma: return kVK_ANSI_Comma
case .slash: return kVK_ANSI_Slash
case .n: return kVK_ANSI_N
case .m: return kVK_ANSI_M
case .period: return kVK_ANSI_Period
case .grave: return kVK_ANSI_Grave
case .keypadDecimal: return kVK_ANSI_KeypadDecimal
case .keypadMultiply: return kVK_ANSI_KeypadMultiply
case .keypadPlus: return kVK_ANSI_KeypadPlus
case .keypadClear: return kVK_ANSI_KeypadClear
case .keypadDivide: return kVK_ANSI_KeypadDivide
case .keypadEnter: return kVK_ANSI_KeypadEnter
case .keypadMinus: return kVK_ANSI_KeypadMinus
case .keypadEquals: return kVK_ANSI_KeypadEquals
case .keypad0: return kVK_ANSI_Keypad0
case .keypad1: return kVK_ANSI_Keypad1
case .keypad2: return kVK_ANSI_Keypad2
case .keypad3: return kVK_ANSI_Keypad3
case .keypad4: return kVK_ANSI_Keypad4
case .keypad5: return kVK_ANSI_Keypad5
case .keypad6: return kVK_ANSI_Keypad6
case .keypad7: return kVK_ANSI_Keypad7
case .keypad8: return kVK_ANSI_Keypad8
case .keypad9: return kVK_ANSI_Keypad9
case .`return`: return kVK_Return
case .tab: return kVK_Tab
case .space: return kVK_Space
case .delete: return kVK_Delete
case .escape: return kVK_Escape
case .command: return kVK_Command
case .shift: return kVK_Shift
case .capsLock: return kVK_CapsLock
case .option: return kVK_Option
case .control: return kVK_Control
case .rightCommand: return kVK_RightCommand
case .rightShift: return kVK_RightShift
case .rightOption: return kVK_RightOption
case .rightControl: return kVK_RightControl
case .function: return kVK_Function
case .f17: return kVK_F17
case .volumeUp: return kVK_VolumeUp
case .volumeDown: return kVK_VolumeDown
case .mute: return kVK_Mute
case .f18: return kVK_F18
case .f19: return kVK_F19
case .f20: return kVK_F20
case .f5: return kVK_F5
case .f6: return kVK_F6
case .f7: return kVK_F7
case .f3: return kVK_F3
case .f8: return kVK_F8
case .f9: return kVK_F9
case .f11: return kVK_F11
case .f13: return kVK_F13
case .f16: return kVK_F16
case .f14: return kVK_F14
case .f10: return kVK_F10
case .f12: return kVK_F12
case .f15: return kVK_F15
case .help: return kVK_Help
case .home: return kVK_Home
case .pageUp: return kVK_PageUp
case .forwardDelete: return kVK_ForwardDelete
case .f4: return kVK_F4
case .end: return kVK_End
case .f2: return kVK_F2
case .pageDown: return kVK_PageDown
case .f1: return kVK_F1
case .leftArrow: return kVK_LeftArrow
case .rightArrow: return kVK_RightArrow
case .downArrow: return kVK_DownArrow
case .upArrow: return kVK_UpArrow
}
}
}
extension Key: CustomStringConvertible {
public var description: String {
switch self {
case .a: return "A"
case .s: return "S"
case .d: return "D"
case .f: return "F"
case .h: return "H"
case .g: return "G"
case .z: return "Z"
case .x: return "X"
case .c: return "C"
case .v: return "V"
case .b: return "B"
case .q: return "Q"
case .w: return "W"
case .e: return "E"
case .r: return "R"
case .y: return "Y"
case .t: return "T"
case .one, .keypad1: return "1"
case .two, .keypad2: return "2"
case .three, .keypad3: return "3"
case .four, .keypad4: return "4"
case .six, .keypad6: return "6"
case .five, .keypad5: return "5"
case .equal: return "="
case .nine, .keypad9: return "9"
case .seven, .keypad7: return "7"
case .minus: return "-"
case .eight, .keypad8: return "8"
case .zero, .keypad0: return "0"
case .rightBracket: return "]"
case .o: return "O"
case .u: return "U"
case .leftBracket: return "["
case .i: return "I"
case .p: return "P"
case .l: return "L"
case .j: return "J"
case .quote: return "\""
case .k: return "K"
case .semicolon: return ";"
case .backslash: return "\\"
case .comma: return ","
case .slash: return "/"
case .n: return "N"
case .m: return "M"
case .period: return "."
case .grave: return "`"
case .keypadDecimal: return "."
case .keypadMultiply: return "𝗑"
case .keypadPlus: return "+"
case .keypadClear: return "⌧"
case .keypadDivide: return "/"
case .keypadEnter: return "↩︎"
case .keypadMinus: return "-"
case .keypadEquals: return "="
case .`return`: return "↩︎"
case .tab: return "⇥"
case .space: return "␣"
case .delete: return "⌫"
case .escape: return "⎋"
case .command, .rightCommand: return "⌘"
case .shift, .rightShift: return "⇧"
case .capsLock: return "⇪"
case .option, .rightOption: return "⌥"
case .control, .rightControl: return "⌃"
case .function: return "fn"
case .f17: return "F17"
case .volumeUp: return "🔊"
case .volumeDown: return "🔉"
case .mute: return "🔇"
case .f18: return "F18"
case .f19: return "F19"
case .f20: return "F20"
case .f5: return "F5"
case .f6: return "F6"
case .f7: return "F7"
case .f3: return "F3"
case .f8: return "F8"
case .f9: return "F9"
case .f11: return "F11"
case .f13: return "F13"
case .f16: return "F16"
case .f14: return "F14"
case .f10: return "F10"
case .f12: return "F12"
case .f15: return "F15"
case .help: return "?⃝"
case .home: return "↖"
case .pageUp: return "⇞"
case .forwardDelete: return "⌦"
case .f4: return "F4"
case .end: return "↘"
case .f2: return "F2"
case .pageDown: return "⇟"
case .f1: return "F1"
case .leftArrow: return "←"
case .rightArrow: return "→"
case .downArrow: return "↓"
case .upArrow: return "↑"
}
}
}
================================================
FILE: CoreUtil/CoreUtil/HotKey/NSEvent+HotKey.swift
================================================
//
// NSEvent+HotKey.swift
// ListView
//
// Created by yuki on 2021/06/28.
//
import Cocoa
extension NSEvent {
public var hotKey: HotKey {
HotKey(Key(keyCode: Int(self.keyCode)), self.modifierFlags.intersection(.deviceIndependentFlagsMask))
}
}
extension NSEvent.ModifierFlags: CustomStringConvertible {
public var description: String {
var output = ""
if self.contains(.capsLock) { output += Key.capsLock.description }
if self.contains(.shift) { output += Key.shift.description }
if self.contains(.control) { output += Key.control.description }
if self.contains(.option) { output += Key.option.description }
if self.contains(.command) { output += Key.command.description }
if self.contains(.numericPad) { output += "Np" }
if self.contains(.help) { output += Key.help.description }
if self.contains(.function) { output += Key.function.description }
return output
}
}
================================================
FILE: CoreUtil/CoreUtil/Info.plist
================================================
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>$(DEVELOPMENT_LANGUAGE)</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key>
<string>$(PRODUCT_BUNDLE_PACKAGE_TYPE)</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleVersion</key>
<string>$(CURRENT_PROJECT_VERSION)</string>
</dict>
</plist>
================================================
FILE: CoreUtil/CoreUtil.xcodeproj/project.pbxproj
================================================
// !$*UTF8*$!
{
archiveVersion = 1;
classes = {
};
objectVersion = 52;
objects = {
/* Begin PBXBuildFile section */
B608540827A66635003BF243 /* NSControl+Combine.swift in Sources */ = {isa = PBXBuildFile; fileRef = B608540727A66635003BF243 /* NSControl+Combine.swift */; };
B62013E927A9147600AF5386 /* Delta.swift in Sources */ = {isa = PBXBuildFile; fileRef = B62013E827A9147600AF5386 /* Delta.swift */; };
B64B1E9427A4F67000AC2601 /* CoreUtil.h in Headers */ = {isa = PBXBuildFile; fileRef = B64B1E9227A4F67000AC2601 /* CoreUtil.h */; settings = {ATTRIBUTES = (Public, ); }; };
B64B1ED027A4F71200AC2601 /* ViewPlaceholder.swift in Sources */ = {isa = PBXBuildFile; fileRef = B64B1ECF27A4F71200AC2601 /* ViewPlaceholder.swift */; };
B64B1ED327A4F71F00AC2601 /* NS+OnAwake.swift in Sources */ = {isa = PBXBuildFile; fileRef = B64B1ED227A4F71F00AC2601 /* NS+OnAwake.swift */; };
B64B1ED627A4F72D00AC2601 /* Query.swift in Sources */ = {isa = PBXBuildFile; fileRef = B64B1ED527A4F72D00AC2601 /* Query.swift */; };
B64B1ED927A4F73700AC2601 /* Observable.swift in Sources */ = {isa = PBXBuildFile; fileRef = B64B1ED827A4F73700AC2601 /* Observable.swift */; };
B64B1EDC27A4F75600AC2601 /* PipeOperator.swift in Sources */ = {isa = PBXBuildFile; fileRef = B64B1EDB27A4F75600AC2601 /* PipeOperator.swift */; };
B64B1EE327A4F79100AC2601 /* NSEvent+HotKey.swift in Sources */ = {isa = PBXBuildFile; fileRef = B64B1EE027A4F79100AC2601 /* NSEvent+HotKey.swift */; };
B64B1EE427A4F79100AC2601 /* Key.swift in Sources */ = {isa = PBXBuildFile; fileRef = B64B1EE127A4F79100AC2601 /* Key.swift */; };
B64B1EE527A4F79100AC2601 /* HotKey.swift in Sources */ = {isa = PBXBuildFile; fileRef = B64B1EE227A4F79100AC2601 /* HotKey.swift */; };
B64B1EF727A4F7AA00AC2601 /* Ex+Number.swift in Sources */ = {isa = PBXBuildFile; fileRef = B64B1EE927A4F7AA00AC2601 /* Ex+Number.swift */; };
B64B1EFA27A4F7AA00AC2601 /* Ex+Array.swift in Sources */ = {isa = PBXBuildFile; fileRef = B64B1EEC27A4F7AA00AC2601 /* Ex+Array.swift */; };
B64B1F0027A4F7AA00AC2601 /* Ex+OptionSet.swift in Sources */ = {isa = PBXBuildFile; fileRef = B64B1EF227A4F7AA00AC2601 /* Ex+OptionSet.swift */; };
B64B1F0127A4F7AA00AC2601 /* Ex+Clamp.swift in Sources */ = {isa = PBXBuildFile; fileRef = B64B1EF327A4F7AA00AC2601 /* Ex+Clamp.swift */; };
B64B1F1627A4F80800AC2601 /* Ex+CGSize.swift in Sources */ = {isa = PBXBuildFile; fileRef = B64B1F1127A4F80800AC2601 /* Ex+CGSize.swift */; };
B64B1F1827A4F80800AC2601 /* Ex+CGPoint.swift in Sources */ = {isa = PBXBuildFile; fileRef = B64B1F1327A4F80800AC2601 /* Ex+CGPoint.swift */; };
B64B1F1A27A4F80800AC2601 /* Ex+CGRect.swift in Sources */ = {isa = PBXBuildFile; fileRef = B64B1F1527A4F80800AC2601 /* Ex+CGRect.swift */; };
B64B1F2B27A4F83500AC2601 /* Ex+UI.swift in Sources */ = {isa = PBXBuildFile; fileRef = B64B1F1F27A4F83500AC2601 /* Ex+UI.swift */; };
B64B1F2E27A4F83500AC2601 /* Ex+NSControl.swift in Sources */ = {isa = PBXBuildFile; fileRef = B64B1F2227A4F83500AC2601 /* Ex+NSControl.swift */; };
B64B1F3027A4F83500AC2601 /* Ex+NSPopover.swift in Sources */ = {isa = PBXBuildFile; fileRef = B64B1F2427A4F83500AC2601 /* Ex+NSPopover.swift */; };
B64B1F3127A4F83500AC2601 /* Ex+Image.swift in Sources */ = {isa = PBXBuildFile; fileRef = B64B1F2527A4F83500AC2601 /* Ex+Image.swift */; };
B64B1F3327A4F83500AC2601 /* Ex+NSEvent.swift in Sources */ = {isa = PBXBuildFile; fileRef = B64B1F2727A4F83500AC2601 /* Ex+NSEvent.swift */; };
B64B1F3427A4F83500AC2601 /* Ex+NSMenuItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = B64B1F2827A4F83500AC2601 /* Ex+NSMenuItem.swift */; };
B64B1F3627A4F83500AC2601 /* Ex+NSColor.swift in Sources */ = {isa = PBXBuildFile; fileRef = B64B1F2A27A4F83500AC2601 /* Ex+NSColor.swift */; };
B64B1F3927A4F8AD00AC2601 /* Ex+NSTableView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B64B1F3827A4F8AD00AC2601 /* Ex+NSTableView.swift */; };
B64B1F3C27A4F8C400AC2601 /* Ex+NSEdgeInsets.swift in Sources */ = {isa = PBXBuildFile; fileRef = B64B1F3B27A4F8C400AC2601 /* Ex+NSEdgeInsets.swift */; };
B64B1F6327A4FC5100AC2601 /* Promise in Frameworks */ = {isa = PBXBuildFile; productRef = B64B1F6227A4FC5100AC2601 /* Promise */; };
B64B1F6827A4FC8A00AC2601 /* SnapKit in Frameworks */ = {isa = PBXBuildFile; productRef = B64B1F6727A4FC8A00AC2601 /* SnapKit */; };
B64B1F6B27A4FC8F00AC2601 /* Export.swift in Sources */ = {isa = PBXBuildFile; fileRef = B64B1F6A27A4FC8F00AC2601 /* Export.swift */; };
B64B201127A50E5200AC2601 /* NSColorView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B64B201027A50E5200AC2601 /* NSColorView.swift */; };
B64B201A27A5103100AC2601 /* Ex+CALayer.swift in Sources */ = {isa = PBXBuildFile; fileRef = B64B201927A5103100AC2601 /* Ex+CALayer.swift */; };
B64B205927A530D700AC2601 /* NSViewController+ChainObject.swift in Sources */ = {isa = PBXBuildFile; fileRef = B64B205827A530D700AC2601 /* NSViewController+ChainObject.swift */; };
B64B205C27A530E800AC2601 /* NSViewController+StateObject.swift in Sources */ = {isa = PBXBuildFile; fileRef = B64B205B27A530E800AC2601 /* NSViewController+StateObject.swift */; };
B64B209527A5323A00AC2601 /* Combine+ObjectBag.swift in Sources */ = {isa = PBXBuildFile; fileRef = B64B209427A5323A00AC2601 /* Combine+ObjectBag.swift */; };
B66F0D4C27B6176A00DC812D /* Terminal.swift in Sources */ = {isa = PBXBuildFile; fileRef = B66F0D4B27B6176A00DC812D /* Terminal.swift */; };
B680A79127A681F8007CB707 /* NSTextField+Combine.swift in Sources */ = {isa = PBXBuildFile; fileRef = B680A79027A681F8007CB707 /* NSTextField+Combine.swift */; };
B680A86527A8C58C007CB707 /* Combine+Peek.swift in Sources */ = {isa = PBXBuildFile; fileRef = B680A86427A8C58C007CB707 /* Combine+Peek.swift */; };
B680A89C27A8DA16007CB707 /* Action.swift in Sources */ = {isa = PBXBuildFile; fileRef = B680A89B27A8DA16007CB707 /* Action.swift */; };
B680A8A027A8DA78007CB707 /* OrderedCollections in Frameworks */ = {isa = PBXBuildFile; productRef = B680A89F27A8DA78007CB707 /* OrderedCollections */; };
B680A8A227A8DA78007CB707 /* DequeModule in Frameworks */ = {isa = PBXBuildFile; productRef = B680A8A127A8DA78007CB707 /* DequeModule */; };
B680A8A427A8DA78007CB707 /* Collections in Frameworks */ = {isa = PBXBuildFile; productRef = B680A8A327A8DA78007CB707 /* Collections */; };
B6A93D2B27CBA2EB003A6D7F /* Zip3Sequence.swift in Sources */ = {isa = PBXBuildFile; fileRef = B6A93D2A27CBA2EB003A6D7F /* Zip3Sequence.swift */; };
B6AC27A327AA6F5C000FD713 /* Reachability+Publisher.swift in Sources */ = {isa = PBXBuildFile; fileRef = B6AC27A127AA6F5B000FD713 /* Reachability+Publisher.swift */; };
B6AC27A427AA6F5C000FD713 /* Reachability.swift in Sources */ = {isa = PBXBuildFile; fileRef = B6AC27A227AA6F5C000FD713 /* Reachability.swift */; };
B6B5727A27AC223A0069DBA7 /* RestorableState.swift in Sources */ = {isa = PBXBuildFile; fileRef = B6B5727927AC223A0069DBA7 /* RestorableState.swift */; };
B6B5727D27AC22480069DBA7 /* RestorableData.swift in Sources */ = {isa = PBXBuildFile; fileRef = B6B5727C27AC22480069DBA7 /* RestorableData.swift */; };
B6BD80FA27B8B06900152AB9 /* Ex+Localize.swift in Sources */ = {isa = PBXBuildFile; fileRef = B6BD80F927B8B06900152AB9 /* Ex+Localize.swift */; };
B6D1AF3D27A60A210022FED2 /* ExceptionHanlder.m in Sources */ = {isa = PBXBuildFile; fileRef = B6D1AF3A27A60A210022FED2 /* ExceptionHanlder.m */; };
B6D1AF3E27A60A210022FED2 /* ExceptionHanlder.h in Headers */ = {isa = PBXBuildFile; fileRef = B6D1AF3B27A60A210022FED2 /* ExceptionHanlder.h */; settings = {ATTRIBUTES = (Public, ); }; };
B6D1AF3F27A60A210022FED2 /* ExceptionHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = B6D1AF3C27A60A210022FED2 /* ExceptionHandler.swift */; };
/* End PBXBuildFile section */
/* Begin PBXFileReference section */
B608540727A66635003BF243 /* NSControl+Combine.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "NSControl+Combine.swift"; sourceTree = "<group>"; };
B62013E827A9147600AF5386 /* Delta.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Delta.swift; sourceTree = "<group>"; };
B64B1E8F27A4F67000AC2601 /* CoreUtil.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = CoreUtil.framework; sourceTree = BUILT_PRODUCTS_DIR; };
B64B1E9227A4F67000AC2601 /* CoreUtil.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CoreUtil.h; sourceTree = "<group>"; };
B64B1E9327A4F67000AC2601 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
B64B1ECF27A4F71200AC2601 /* ViewPlaceholder.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ViewPlaceholder.swift; sourceTree = "<group>"; };
B64B1ED227A4F71F00AC2601 /* NS+OnAwake.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "NS+OnAwake.swift"; sourceTree = "<group>"; };
B64B1ED527A4F72D00AC2601 /* Query.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Query.swift; sourceTree = "<group>"; };
B64B1ED827A4F73700AC2601 /* Observable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Observable.swift; sourceTree = "<group>"; };
B64B1EDB27A4F75600AC2601 /* PipeOperator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PipeOperator.swift; sourceTree = "<group>"; };
B64B1EE027A4F79100AC2601 /* NSEvent+HotKey.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "NSEvent+HotKey.swift"; sourceTree = "<group>"; };
B64B1EE127A4F79100AC2601 /* Key.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Key.swift; sourceTree = "<group>"; };
B64B1EE227A4F79100AC2601 /* HotKey.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HotKey.swift; sourceTree = "<group>"; };
B64B1EE927A4F7AA00AC2601 /* Ex+Number.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Ex+Number.swift"; sourceTree = "<group>"; };
B64B1EEC27A4F7AA00AC2601 /* Ex+Array.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Ex+Array.swift"; sourceTree = "<group>"; };
B64B1EF227A4F7AA00AC2601 /* Ex+OptionSet.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Ex+OptionSet.swift"; sourceTree = "<group>"; };
B64B1EF327A4F7AA00AC2601 /* Ex+Clamp.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Ex+Clamp.swift"; sourceTree = "<group>"; };
B64B1F1127A4F80800AC2601 /* Ex+CGSize.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Ex+CGSize.swift"; sourceTree = "<group>"; };
B64B1F1327A4F80800AC2601 /* Ex+CGPoint.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Ex+CGPoint.swift"; sourceTree = "<group>"; };
B64B1F1527A4F80800AC2601 /* Ex+CGRect.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Ex+CGRect.swift"; sourceTree = "<group>"; };
B64B1F1F27A4F83500AC2601 /* Ex+UI.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Ex+UI.swift"; sourceTree = "<group>"; };
B64B1F2227A4F83500AC2601 /* Ex+NSControl.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Ex+NSControl.swift"; sourceTree = "<group>"; };
B64B1F2427A4F83500AC2601 /* Ex+NSPopover.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Ex+NSPopover.swift"; sourceTree = "<group>"; };
B64B1F2527A4F83500AC2601 /* Ex+Image.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Ex+Image.swift"; sourceTree = "<group>"; };
B64B1F2727A4F83500AC2601 /* Ex+NSEvent.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Ex+NSEvent.swift"; sourceTree = "<group>"; };
B64B1F2827A4F83500AC2601 /* Ex+NSMenuItem.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Ex+NSMenuItem.swift"; sourceTree = "<group>"; };
B64B1F2A27A4F83500AC2601 /* Ex+NSColor.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Ex+NSColor.swift"; sourceTree = "<group>"; };
B64B1F3827A4F8AD00AC2601 /* Ex+NSTableView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Ex+NSTableView.swift"; sourceTree = "<group>"; };
B64B1F3B27A4F8C400AC2601 /* Ex+NSEdgeInsets.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Ex+NSEdgeInsets.swift"; sourceTree = "<group>"; };
B64B1F6A27A4FC8F00AC2601 /* Export.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Export.swift; sourceTree = "<group>"; };
B64B201027A50E5200AC2601 /* NSColorView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NSColorView.swift; sourceTree = "<group>"; };
B64B201927A5103100AC2601 /* Ex+CALayer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Ex+CALayer.swift"; sourceTree = "<group>"; };
B64B205827A530D700AC2601 /* NSViewController+ChainObject.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "NSViewController+ChainObject.swift"; sourceTree = "<group>"; };
B64B205B27A530E800AC2601 /* NSViewController+StateObject.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "NSViewController+StateObject.swift"; sourceTree = "<group>"; };
B64B209427A5323A00AC2601 /* Combine+ObjectBag.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Combine+ObjectBag.swift"; sourceTree = "<group>"; };
B66F0D4B27B6176A00DC812D /* Terminal.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Terminal.swift; sourceTree = "<group>"; };
B680A79027A681F8007CB707 /* NSTextField+Combine.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "NSTextField+Combine.swift"; sourceTree = "<group>"; };
B680A86427A8C58C007CB707 /* Combine+Peek.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Combine+Peek.swift"; sourceTree = "<group>"; };
B680A89B27A8DA16007CB707 /* Action.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Action.swift; sourceTree = "<group>"; };
B6A93D2A27CBA2EB003A6D7F /* Zip3Sequence.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Zip3Sequence.swift; sourceTree = "<group>"; };
B6AC27A127AA6F5B000FD713 /* Reachability+Publisher.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Reachability+Publisher.swift"; sourceTree = "<group>"; };
B6AC27A227AA6F5C000FD713 /* Reachability.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Reachability.swift; sourceTree = "<group>"; };
B6B5727927AC223A0069DBA7 /* RestorableState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RestorableState.swift; sourceTree = "<group>"; };
B6B5727C27AC22480069DBA7 /* RestorableData.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RestorableData.swift; sourceTree = "<group>"; };
B6BD80F927B8B06900152AB9 /* Ex+Localize.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Ex+Localize.swift"; sourceTree = "<group>"; };
B6D1AF3A27A60A210022FED2 /* ExceptionHanlder.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ExceptionHanlder.m; sourceTree = "<group>"; };
B6D1AF3B27A60A210022FED2 /* ExceptionHanlder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ExceptionHanlder.h; sourceTree = "<group>"; };
B6D1AF3C27A60A210022FED2 /* ExceptionHandler.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ExceptionHandler.swift; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
B64B1E8C27A4F67000AC2601 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
B64B1F6327A4FC5100AC2601 /* Promise in Frameworks */,
B680A8A227A8DA78007CB707 /* DequeModule in Frameworks */,
B680A8A427A8DA78007CB707 /* Collections in Frameworks */,
B64B1F6827A4FC8A00AC2601 /* SnapKit in Frameworks */,
B680A8A027A8DA78007CB707 /* OrderedCollections in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
B64B1E8527A4F67000AC2601 = {
isa = PBXGroup;
children = (
B64B1E9127A4F67000AC2601 /* CoreUtil */,
B64B1E9027A4F67000AC2601 /* Products */,
);
sourceTree = "<group>";
};
B64B1E9027A4F67000AC2601 /* Products */ = {
isa = PBXGroup;
children = (
B64B1E8F27A4F67000AC2601 /* CoreUtil.framework */,
);
name = Products;
sourceTree = "<group>";
};
B64B1E9127A4F67000AC2601 /* CoreUtil */ = {
isa = PBXGroup;
children = (
B64B1E9227A4F67000AC2601 /* CoreUtil.h */,
B64B1E9327A4F67000AC2601 /* Info.plist */,
B64B1F6A27A4FC8F00AC2601 /* Export.swift */,
B6D1AF3927A60A210022FED2 /* ExceptionHanlder */,
B64B1F6D27A4FC9100AC2601 /* Class */,
B64B1EE727A4F79800AC2601 /* Extensions */,
B64B1EDF27A4F79100AC2601 /* HotKey */,
);
path = CoreUtil;
sourceTree = "<group>";
};
B64B1EDF27A4F79100AC2601 /* HotKey */ = {
isa = PBXGroup;
children = (
B64B1EE027A4F79100AC2601 /* NSEvent+HotKey.swift */,
B64B1EE127A4F79100AC2601 /* Key.swift */,
B64B1EE227A4F79100AC2601 /* HotKey.swift */,
);
path = HotKey;
sourceTree = "<group>";
};
B64B1EE727A4F79800AC2601 /* Extensions */ = {
isa = PBXGroup;
children = (
B64B208E27A5322A00AC2601 /* Combine */,
B64B1F1E27A4F83500AC2601 /* UI */,
B64B1F1027A4F80800AC2601 /* CoreGraphics */,
B64B1EE827A4F7AA00AC2601 /* Swift */,
);
path = Extensions;
sourceTree = "<group>";
};
B64B1EE827A4F7AA00AC2601 /* Swift */ = {
isa = PBXGroup;
children = (
B64B1EE927A4F7AA00AC2601 /* Ex+Number.swift */,
B64B1EEC27A4F7AA00AC2601 /* Ex+Array.swift */,
B64B1EF227A4F7AA00AC2601 /* Ex+OptionSet.swift */,
B64B1EF327A4F7AA00AC2601 /* Ex+Clamp.swift */,
B6BD80F927B8B06900152AB9 /* Ex+Localize.swift */,
);
path = Swift;
sourceTree = "<group>";
};
B64B1F1027A4F80800AC2601 /* CoreGraphics */ = {
isa = PBXGroup;
children = (
B64B1F1127A4F80800AC2601 /* Ex+CGSize.swift */,
B64B1F1327A4F80800AC2601 /* Ex+CGPoint.swift */,
B64B1F1527A4F80800AC2601 /* Ex+CGRect.swift */,
);
path = CoreGraphics;
sourceTree = "<group>";
};
B64B1F1E27A4F83500AC2601 /* UI */ = {
isa = PBXGroup;
children = (
B64B201927A5103100AC2601 /* Ex+CALayer.swift */,
B64B1F1F27A4F83500AC2601 /* Ex+UI.swift */,
B64B1F2227A4F83500AC2601 /* Ex+NSControl.swift */,
B64B1F2427A4F83500AC2601 /* Ex+NSPopover.swift */,
B64B1F2527A4F83500AC2601 /* Ex+Image.swift */,
B64B1F2727A4F83500AC2601 /* Ex+NSEvent.swift */,
B64B1F2827A4F83500AC2601 /* Ex+NSMenuItem.swift */,
B64B1F2A27A4F83500AC2601 /* Ex+NSColor.swift */,
B64B1F3827A4F8AD00AC2601 /* Ex+NSTableView.swift */,
B64B1F3B27A4F8C400AC2601 /* Ex+NSEdgeInsets.swift */,
);
path = UI;
sourceTree = "<group>";
};
B64B1F6D27A4FC9100AC2601 /* Class */ = {
isa = PBXGroup;
children = (
B6A93D2A27CBA2EB003A6D7F /* Zip3Sequence.swift */,
B6AC27A227AA6F5C000FD713 /* Reachability.swift */,
B6AC27A127AA6F5B000FD713 /* Reachability+Publisher.swift */,
B64B201027A50E5200AC2601 /* NSColorView.swift */,
B64B1ECF27A4F71200AC2601 /* ViewPlaceholder.swift */,
B64B1ED527A4F72D00AC2601 /* Query.swift */,
B680A89B27A8DA16007CB707 /* Action.swift */,
B64B205827A530D700AC2601 /* NSViewController+ChainObject.swift */,
B64B205B27A530E800AC2601 /* NSViewController+StateObject.swift */,
B62013E827A9147600AF5386 /* Delta.swift */,
B64B1ED827A4F73700AC2601 /* Observable.swift */,
B64B1EDB27A4F75600AC2601 /* PipeOperator.swift */,
B64B1ED227A4F71F00AC2601 /* NS+OnAwake.swift */,
B6B5727927AC223A0069DBA7 /* RestorableState.swift */,
B6B5727C27AC22480069DBA7 /* RestorableData.swift */,
B66F0D4B27B6176A00DC812D /* Terminal.swift */,
);
path = Class;
sourceTree = "<group>";
};
B64B208E27A5322A00AC2601 /* Combine */ = {
isa = PBXGroup;
children = (
B608540727A66635003BF243 /* NSControl+Combine.swift */,
B680A79027A681F8007CB707 /* NSTextField+Combine.swift */,
B64B209427A5323A00AC2601 /* Combine+ObjectBag.swift */,
B680A86427A8C58C007CB707 /* Combine+Peek.swift */,
);
path = Combine;
sourceTree = "<group>";
};
B6D1AF3927A60A210022FED2 /* ExceptionHanlder */ = {
isa = PBXGroup;
children = (
B6D1AF3A27A60A210022FED2 /* ExceptionHanlder.m */,
B6D1AF3B27A60A210022FED2 /* ExceptionHanlder.h */,
B6D1AF3C27A60A210022FED2 /* ExceptionHandler.swift */,
);
path = ExceptionHanlder;
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXHeadersBuildPhase section */
B64B1E8A27A4F67000AC2601 /* Headers */ = {
isa = PBXHeadersBuildPhase;
buildActionMask = 2147483647;
files = (
B64B1E9427A4F67000AC2601 /* CoreUtil.h in Headers */,
B6D1AF3E27A60A210022FED2 /* ExceptionHanlder.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXHeadersBuildPhase section */
/* Begin PBXNativeTarget section */
B64B1E8E27A4F67000AC2601 /* CoreUtil */ = {
isa = PBXNativeTarget;
buildConfigurationList = B64B1E9727A4F67000AC2601 /* Build configuration list for PBXNativeTarget "CoreUtil" */;
buildPhases = (
B64B1E8A27A4F67000AC2601 /* Headers */,
B64B1E8B27A4F67000AC2601 /* Sources */,
B64B1E8C27A4F67000AC2601 /* Frameworks */,
B64B1E8D27A4F67000AC2601 /* Resources */,
);
buildRules = (
);
dependencies = (
);
name = CoreUtil;
packageProductDependencies = (
B64B1F6227A4FC5100AC2601 /* Promise */,
B64B1F6727A4FC8A00AC2601 /* SnapKit */,
B680A89F27A8DA78007CB707 /* OrderedCollections */,
B680A8A127A8DA78007CB707 /* DequeModule */,
B680A8A327A8DA78007CB707 /* Collections */,
);
productName = CoreUtil;
productReference = B64B1E8F27A4F67000AC2601 /* CoreUtil.framework */;
productType = "com.apple.product-type.framework";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
B64B1E8627A4F67000AC2601 /* Project object */ = {
isa = PBXProject;
attributes = {
LastUpgradeCheck = 1240;
TargetAttributes = {
B64B1E8E27A4F67000AC2601 = {
CreatedOnToolsVersion = 12.4;
LastSwiftMigration = 1240;
};
};
};
buildConfigurationList = B64B1E8927A4F67000AC2601 /* Build configuration list for PBXProject "CoreUtil" */;
compatibilityVersion = "Xcode 9.3";
developmentRegion = en;
hasScannedForEncodings = 0;
knownRegions = (
en,
Base,
);
mainGroup = B64B1E8527A4F67000AC2601;
packageReferences = (
B64B1F6127A4FC5100AC2601 /* XCRemoteSwiftPackageReference "Promise" */,
B64B1F6627A4FC8A00AC2601 /* XCRemoteSwiftPackageReference "SnapKit" */,
B680A89E27A8DA78007CB707 /* XCRemoteSwiftPackageReference "swift-collections" */,
);
productRefGroup = B64B1E9027A4F67000AC2601 /* Products */;
projectDirPath = "";
projectRoot = "";
targets = (
B64B1E8E27A4F67000AC2601 /* CoreUtil */,
);
};
/* End PBXProject section */
/* Begin PBXResourcesBuildPhase section */
B64B1E8D27A4F67000AC2601 /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXResourcesBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
B64B1E8B27A4F67000AC2601 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
B6D1AF3D27A60A210022FED2 /* ExceptionHanlder.m in Sources */,
B680A89C27A8DA16007CB707 /* Action.swift in Sources */,
B64B1F6B27A4FC8F00AC2601 /* Export.swift in Sources */,
B64B205C27A530E800AC2601 /* NSViewController+StateObject.swift in Sources */,
B608540827A66635003BF243 /* NSControl+Combine.swift in Sources */,
B64B1F3327A4F83500AC2601 /* Ex+NSEvent.swift in Sources */,
B64B205927A530D700AC2601 /* NSViewController+ChainObject.swift in Sources */,
B66F0D4C27B6176A00DC812D /* Terminal.swift in Sources */,
B64B1EE427A4F79100AC2601 /* Key.swift in Sources */,
B64B1F0027A4F7AA00AC2601 /* Ex+OptionSet.swift in Sources */,
B6AC27A327AA6F5C000FD713 /* Reachability+Publisher.swift in Sources */,
B64B1F2E27A4F83500AC2601 /* Ex+NSControl.swift in Sources */,
B64B1F1627A4F80800AC2601 /* Ex+CGSize.swift in Sources */,
B6B5727A27AC223A0069DBA7 /* RestorableState.swift in Sources */,
B64B1ED927A4F73700AC2601 /* Observable.swift in Sources */,
B64B201127A50E5200AC2601 /* NSColorView.swift in Sources */,
B64B1EE327A4F79100AC2601 /* NSEvent+HotKey.swift in Sources */,
B64B201A27A5103100AC2601 /* Ex+CALayer.swift in Sources */,
B680A79127A681F8007CB707 /* NSTextField+Combine.swift in Sources */,
B64B1EFA27A4F7AA00AC2601 /* Ex+Array.swift in Sources */,
B64B1F1A27A4F80800AC2601 /* Ex+CGRect.swift in Sources */,
B64B1F3C27A4F8C400AC2601 /* Ex+NSEdgeInsets.swift in Sources */,
B64B1F3427A4F83500AC2601 /* Ex+NSMenuItem.swift in Sources */,
B64B1F3027A4F83500AC2601 /* Ex+NSPopover.swift in Sources */,
B64B1EE527A4F79100AC2601 /* HotKey.swift in Sources */,
B64B1F3627A4F83500AC2601 /* Ex+NSColor.swift in Sources */,
B64B209527A5323A00AC2601 /* Combine+ObjectBag.swift in Sources */,
B64B1EDC27A4F75600AC2601 /* PipeOperator.swift in Sources */,
B6BD80FA27B8B06900152AB9 /* Ex+Localize.swift in Sources */,
B64B1F1827A4F80800AC2601 /* Ex+CGPoint.swift in Sources */,
B680A86527A8C58C007CB707 /* Combine+Peek.swift in Sources */,
B64B1ED027A4F71200AC2601 /* ViewPlaceholder.swift in Sources */,
B6A93D2B27CBA2EB003A6D7F /* Zip3Sequence.swift in Sources */,
B64B1F3127A4F83500AC2601 /* Ex+Image.swift in Sources */,
B64B1ED627A4F72D00AC2601 /* Query.swift in Sources */,
B64B1F2B27A4F83500AC2601 /* Ex+UI.swift in Sources */,
B64B1F3927A4F8AD00AC2601 /* Ex+NSTableView.swift in Sources */,
B64B1F0127A4F7AA00AC2601 /* Ex+Clamp.swift in Sources */,
B64B1EF727A4F7AA00AC2601 /* Ex+Number.swift in Sources */,
B62013E927A9147600AF5386 /* Delta.swift in Sources */,
B6D1AF3F27A60A210022FED2 /* ExceptionHandler.swift in Sources */,
B64B1ED327A4F71F00AC2601 /* NS+OnAwake.swift in Sources */,
B6AC27A427AA6F5C000FD713 /* Reachability.swift in Sources */,
B6B5727D27AC22480069DBA7 /* RestorableData.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin XCBuildConfiguration section */
B64B1E9527A4F67000AC2601 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_NONNULL = YES;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_ENABLE_OBJC_WEAK = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COPY_PHASE_STRIP = NO;
CURRENT_PROJECT_VERSION = 1;
DEBUG_INFORMATION_FORMAT = dwarf;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
GCC_C_LANGUAGE_STANDARD = gnu11;
GCC_DYNAMIC_NO_PIC = NO;
GCC_NO_COMMON_BLOCKS = YES;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
MACOSX_DEPLOYMENT_TARGET = 11.1;
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = macosx;
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
VERSIONING_SYSTEM = "apple-generic";
VERSION_INFO_PREFIX = "";
};
name = Debug;
};
B64B1E9627A4F67000AC2601 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_NONNULL = YES;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_ENABLE_OBJC_WEAK = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COPY_PHASE_STRIP = NO;
CURRENT_PROJECT_VERSION = 1;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_C_LANGUAGE_STANDARD = gnu11;
GCC_NO_COMMON_BLOCKS = YES;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
MACOSX_DEPLOYMENT_TARGET = 11.1;
MTL_ENABLE_DEBUG_INFO = NO;
MTL_FAST_MATH = YES;
SDKROOT = macosx;
SWIFT_COMPILATION_MODE = wholemodule;
SWIFT_OPTIMIZATION_LEVEL = "-O";
VERSIONING_SYSTEM = "apple-generic";
VERSION_INFO_PREFIX = "";
};
name = Release;
};
B64B1E9827A4F67000AC2601 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
DEFINES_MODULE = YES;
DEVELOPMENT_TEAM = T5HMUWWK5R;
DYLIB_COMPATIBILITY_VERSION = 1;
DYLIB_CURRENT_VERSION = 1;
DYLIB_INSTALL_NAME_BASE = "@rpath";
INFOPLIST_FILE = CoreUtil/Info.plist;
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/../Frameworks",
"@loader_path/Frameworks",
);
MACOSX_DEPLOYMENT_TARGET = 10.15;
PRODUCT_BUNDLE_IDENTIFIER = com.yuki.CoreUtil;
PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)";
SKIP_INSTALL = YES;
SWIFT_ENFORCE_EXCLUSIVE_ACCESS = off;
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 5.0;
};
name = Debug;
};
B64B1E9927A4F67000AC2601 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
DEFINES_MODULE = YES;
DEVELOPMENT_TEAM = T5HMUWWK5R;
DYLIB_COMPATIBILITY_VERSION = 1;
DYLIB_CURRENT_VERSION = 1;
DYLIB_INSTALL_NAME_BASE = "@rpath";
INFOPLIST_FILE = CoreUtil/Info.plist;
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/../Frameworks",
"@loader_path/Frameworks",
);
MACOSX_DEPLOYMENT_TARGET = 10.15;
PRODUCT_BUNDLE_IDENTIFIER = com.yuki.CoreUtil;
PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)";
SKIP_INSTALL = YES;
SWIFT_ENFORCE_EXCLUSIVE_ACCESS = off;
SWIFT_VERSION = 5.0;
};
name = Release;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
B64B1E8927A4F67000AC2601 /* Build configuration list for PBXProject "CoreUtil" */ = {
isa = XCConfigurationList;
buildConfigurations = (
B64B1E9527A4F67000AC2601 /* Debug */,
B64B1E9627A4F67000AC2601 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
B64B1E9727A4F67000AC2601 /* Build configuration list for PBXNativeTarget "CoreUtil" */ = {
isa = XCConfigurationList;
buildConfigurations = (
B64B1E9827A4F67000AC2601 /* Debug */,
B64B1E9927A4F67000AC2601 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
/* Begin XCRemoteSwiftPackageReference section */
B64B1F6127A4FC5100AC2601 /* XCRemoteSwiftPackageReference "Promise" */ = {
isa = XCRemoteSwiftPackageReference;
repositoryURL = "https://github.com/ObuchiYuki/Promise.git";
requirement = {
kind = upToNextMajorVersion;
minimumVersion = 1.0.9;
};
};
B64B1F6627A4FC8A00AC2601 /* XCRemoteSwiftPackageReference "SnapKit" */ = {
isa = XCRemoteSwiftPackageReference;
repositoryURL = "https://github.com/SnapKit/SnapKit.git";
requirement = {
kind = upToNextMajorVersion;
minimumVersion = 5.0.1;
};
};
B680A89E27A8DA78007CB707 /* XCRemoteSwiftPackageReference "swift-collections" */ = {
isa = XCRemoteSwiftPackageReference;
repositoryURL = "https://github.com/apple/swift-collections";
requirement = {
kind = upToNextMajorVersion;
minimumVersion = 1.0.2;
};
};
/* End XCRemoteSwiftPackageReference section */
/* Begin XCSwiftPackageProductDependency section */
B64B1F6227A4FC5100AC2601 /* Promise */ = {
isa = XCSwiftPackageProductDependency;
package = B64B1F6127A4FC5100AC2601 /* XCRemoteSwiftPackageReference "Promise" */;
productName = Promise;
};
B64B1F6727A4FC8A00AC2601 /* SnapKit */ = {
isa = XCSwiftPackageProductDependency;
package = B64B1F6627A4FC8A00AC2601 /* XCRemoteSwiftPackageReference "SnapKit" */;
productName = SnapKit;
};
B680A89F27A8DA78007CB707 /* OrderedCollections */ = {
isa = XCSwiftPackageProductDependency;
package = B680A89E27A8DA78007CB707 /* XCRemoteSwiftPackageReference "swift-collections" */;
productName = OrderedCollections;
};
B680A8A127A8DA78007CB707 /* DequeModule */ = {
isa = XCSwiftPackageProductDependency;
package = B680A89E27A8DA78007CB707 /* XCRemoteSwiftPackageReference "swift-collections" */;
productName = DequeModule;
};
B680A8A327A8DA78007CB707 /* Collections */ = {
isa = XCSwiftPackageProductDependency;
package = B680A89E27A8DA78007CB707 /* XCRemoteSwiftPackageReference "swift-collections" */;
productName = Collections;
};
/* End XCSwiftPackageProductDependency section */
};
rootObject = B64B1E8627A4F67000AC2601 /* Project object */;
}
================================================
FILE: CoreUtil/CoreUtil.xcodeproj/project.xcworkspace/contents.xcworkspacedata
================================================
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "self:">
</FileRef>
</Workspace>
================================================
FILE: CoreUtil/CoreUtil.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
================================================
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>IDEDidComputeMac32BitWarning</key>
<true/>
</dict>
</plist>
================================================
FILE: DevToys/DevToys/App/AppViewController.swift
================================================
//
// ViewController.swift
// DevToys
//
// Created by yuki on 2022/01/29.
//
import Cocoa
import CoreUtil
final class AppViewController: NSSplitViewController {
private let sidebarController = SidebarViewController()
private let bodyController = BodyViewController()
override func chainObjectDidLoad() {
// The object chain will be broken on `addSplitViewItem`. So call the manual chain.
self.sidebarController.chainObject = chainObject
self.bodyController.chainObject = chainObject
}
override func viewDidLoad() {
super.viewDidLoad()
let sidebarItem = NSSplitViewItem(sidebarWithViewController: sidebarController)
sidebarItem.minimumThickness = 200
sidebarItem.canCollapse = false
self.addSplitViewItem(sidebarItem)
let bodyItem = NSSplitViewItem(viewController: bodyController)
bodyItem.minimumThickness = 480
bodyItem.canCollapse = false
self.addSplitViewItem(bodyItem)
splitView.setPosition(220, ofDividerAt: 0)
self.splitView.autosaveName = "app.splitv"
}
}
================================================
FILE: DevToys/DevToys/App/AppWindowController.swift
================================================
//
// AppWindowController.swift
// DevToys
//
// Created by yuki on 2022/01/29.
//
import CoreUtil
import Darwin
import AppKit
final class AppWindowController: NSWindowController {
private let appModel = AppModel()
private lazy var separatorItem = NSTrackingSeparatorToolbarItem(
identifier: AppWindowController.separatorItemIdentifier, splitView: splitViewController.splitView, dividerIndex: 0
)
private lazy var disclosureItem = NSToolbarItem(
itemIdentifier: AppWindowController.disclosureItemIdentifier
)
private var splitViewController: NSSplitViewController {
self.window?.contentViewController as! NSSplitViewController
}
@objc private func toggleSidebar() {
splitViewController.splitViewItems[0].animator().isCollapsed.toggle()
}
override func windowDidLoad() {
self.contentViewController?.chainObject = appModel
self.appModel.settings.$appearanceType
.sink{
switch $0 {
case .useSystemSettings: self.window?.appearance = nil
case .darkMode: self.window?.appearance = NSAppearance(named: .darkAqua)
case .lightMode: self.window?.appearance = NSAppearance(named: .aqua)
}
}
.store(in: &objectBag)
self.appModel.$tool
.sink{[unowned self] in self.window?.title = $0.title }.store(in: &objectBag)
guard let toolbar = self.window?.toolbar else { return assertionFailure() }
toolbar.delegate = self
toolbar.allowsUserCustomization = true
disclosureItem.view = NSButton(title: "Sidebar", image: R.Image.sidebarDisclosure) => {
$0.bezelStyle = .texturedRounded
$0.actionPublisher.sink{[unowned self] in toggleSidebar() }.store(in: &objectBag)
}
}
}
extension AppWindowController: NSToolbarDelegate {
static let separatorItemIdentifier = NSToolbarItem.Identifier("separator")
static let disclosureItemIdentifier = NSToolbarItem.Identifier("disclosure")
func toolbarDefaultItemIdentifiers(_ toolbar: NSToolbar) -> [NSToolbarItem.Identifier] {
if #available(macOS 11.0, *) {
return [AppWindowController.disclosureItemIdentifier, AppWindowController.separatorItemIdentifier]
} else {
return [AppWindowController.disclosureItemIdentifier]
}
}
func toolbarAllowedItemIdentifiers(_ toolbar: NSToolbar) -> [NSToolbarItem.Identifier] {
self.toolbarDefaultItemIdentifiers(toolbar)
}
func toolbarSelectableItemIdentifiers(_ toolbar: NSToolbar) -> [NSToolbarItem.Identifier] {
[]
}
func toolbar(_ toolbar: NSToolbar, itemForItemIdentifier itemIdentifier: NSToolbarItem.Identifier, willBeInsertedIntoToolbar flag: Bool) -> NSToolbarItem? {
if #available(macOS 11.0, *) {
if itemIdentifier == AppWindowController.separatorItemIdentifier {
return self.separatorItem
}
}
if itemIdentifier == AppWindowController.disclosureItemIdentifier {
return self.disclosureItem
}
return nil
}
}
================================================
FILE: DevToys/DevToys/AppDelegate.swift
================================================
//
// AppDelegate.swift
// DevToys
//
// Created by yuki on 2022/01/29.
//
import Cocoa
@main
class AppDelegate: NSObject, NSApplicationDelegate {
func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) -> Bool { true }
}
================================================
FILE: DevToys/DevToys/Body/BodyViewController.swift
================================================
//
// BodyViewController.swift
// DevToys
//
// Created by yuki on 2022/01/29.
//
import CoreUtil
final class BodyViewController: NSViewController {
private let placeholderView = NSPlaceholderView()
private var contentViewController: NSViewController?
override func loadView() { self.view = placeholderView }
override func chainObjectDidLoad() {
self.appModel.$tool
.sink{[unowned self] in replaceTool($0) }.store(in: &objectBag)
self.appModel.$searchQuery
.sink{[unowned self] in handleQuery($0) }.store(in: &objectBag)
}
private func handleQuery(_ query: String) {
if query.isEmpty {
self.replaceTool(appModel.tool)
} else {
self.replaceTool(.search)
}
}
private func replaceTool(_ tool: Tool) {
self.contentViewController?.removeFromParent()
self.addChild(tool.viewController)
self.contentViewController = tool.viewController
self.placeholderView.contentView = tool.viewController.view
}
}
================================================
FILE: DevToys/DevToys/Body/Coder/Base64DecoderView+.swift
================================================
//
// Base64Decoder.swift
// DevToys
//
// Created by yuki on 2022/01/30.
//
import CoreUtil
final class Base64DecoderViewController: NSViewController {
private let cell = Base64DecoderView()
@RestorableState("base64.sourceType") private var sourceType = SourceType.text
@RestorableState("base64.rawString") private var rawString = defaultRawString
@Observable private var formattedString = defaultBase64String
override func loadView() { self.view = cell }
override func viewDidLoad() {
self.cell.inputTextSection.stringPublisher
.sink{[unowned self] in self.rawString = $0; self.formattedString = encode($0) }.store(in: &objectBag)
self.cell.encodeTextSection.stringPublisher
.sink{[unowned self] in self.formattedString = $0; self.rawString = decode($0) }.store(in: &objectBag)
self.cell.sourceTypePicker.itemPublisher
.sink{[unowned self] in self.sourceType = $0 }.store(in: &objectBag)
self.cell.fileDrop.urlsPublisher.compactMap{ $0.first }
.sink{[unowned self] in self.formattedString = self.encodeFile($0) }.store(in: &objectBag)
self.cell.exportButton.actionPublisher
.sink{[unowned self] in self.exportFile() }.store(in: &objectBag)
self.$sourceType
.sink{[unowned self] in self.cell.sourceTypePicker.selectedItem = $0; updateEncodeView($0) }.store(in: &objectBag)
self.$rawString
.sink{[unowned self] in self.cell.inputTextSection.string = $0 }.store(in: &objectBag)
self.$formattedString
.sink{[unowned self] in self.cell.encodeTextSection.string = $0 }.store(in: &objectBag)
}
private func updateEncodeView(_ sourceType: SourceType) {
switch sourceType {
case .file:
self.cell.inputSectionContainer.contentView = cell.fileDropSection
case .text:
self.cell.inputSectionContainer.contentView = cell.inputTextSection
self.formattedString = self.encode(rawString)
}
}
private func exportFile() {
let panel = NSSavePanel()
guard let data = Data(base64Encoded: formattedString), panel.runModal() == .OK, let url = panel.url else { return }
do {
try data.write(to: url)
} catch {
NSSound.beep()
}
}
private func encodeFile(_ url: URL) -> String {
(try? Data(contentsOf: url).base64EncodedString()) ?? "[Encode Failed]"
}
private func encode(_ string: String) -> String {
string.data(using: .utf8)!.base64EncodedString()
}
private func decode(_ string: String) -> String {
String(data: Data(base64Encoded: string) ?? Data(), encoding: .utf8) ?? "Not String"
}
}
private enum SourceType: String, TextItem {
case text = "Text Source"
case file = "File Source"
var title: String { rawValue.localized() }
}
final private class Base64DecoderView: Page {
let sourceTypePicker = EnumPopupButton<SourceType>()
let fileDrop = FileDrop()
let exportButton = SectionButton(title: "Export".localized(), image: R.Image.export)
let inputSectionContainer = NSPlaceholderView()
let inputTextSection = TextViewSection(title: "Text".localized(), options: [.all])
lazy var fileDropSection = Section(title: "File".localized(), items: [fileDrop], toolbarItems: [exportButton])
let encodeTextSection = TextViewSection(title: "Encoded".localized(), options: [.all])
override func layout() {
super.layout()
let halfHeight = max(200, (self.frame.height - 190) / 2)
self.fileDropSection.snp.remakeConstraints{ make in
make.height.equalTo(halfHeight)
}
self.inputTextSection.snp.remakeConstraints{ make in
make.height.equalTo(halfHeight)
}
self.encodeTextSection.snp.remakeConstraints{ make in
make.height.equalTo(halfHeight)
}
}
override func onAwake() {
self.addSection(Section(title: "Configuration".localized(), items: [
Area(icon: R.Image.convert, title: "Source Type".localized(), control: sourceTypePicker)
]))
self.inputSectionContainer.contentView = inputTextSection
self.addSection(inputSectionContainer)
self.addSection(inputTextSection)
self.addSection(encodeTextSection)
}
}
private let defaultRawString = "An Open-Source Swiss Army knife for developers. DevToys helps in everyday tasks like formatting JSON, comparing text, testing RegExp. No need to use many untruthful websites to do simple tasks with your data. With Smart Detection, DevToys is able to detect the best tool that can treat the data you copied in the clipboard of your Windows. Compact overlay lets you keep the app in small and on top of other windows. Multiple instances of the app can be used at once."
private let defaultBase64String = "QW4gT3Blbi1Tb3VyY2UgU3dpc3MgQXJteSBrbmlmZSBmb3IgZGV2ZWxvcGVycy4KRGV2VG95cyBoZWxwcyBpbiBldmVyeWRheSB0YXNrcyBsaWtlIGZvcm1hdHRpbmcgSlNPTiwgY29tcGFyaW5nIHRleHQsIHRlc3RpbmcgUmVnRXhwLiBObyBuZWVkIHRvIHVzZSBtYW55IHVudHJ1dGhmdWwgd2Vic2l0ZXMgdG8gZG8gc2ltcGxlIHRhc2tzIHdpdGggeW91ciBkYXRhLiBXaXRoIFNtYXJ0IERldGVjdGlvbiwgRGV2VG95cyBpcyBhYmxlIHRvIGRldGVjdCB0aGUgYmVzdCB0b29sIHRoYXQgY2FuIHRyZWF0IHRoZSBkYXRhIHlvdSBjb3BpZWQgaW4gdGhlIGNsaXBib2FyZCBvZiB5b3VyIFdpbmRvd3MuIENvbXBhY3Qgb3ZlcmxheSBsZXRzIHlvdSBrZWVwIHRoZSBhcHAgaW4gc21hbGwgYW5kIG9uIHRvcCBvZiBvdGhlciB3aW5kb3dzLiBNdWx0aXBsZSBpbnN0YW5jZXMgb2YgdGhlIGFwcCBjYW4gYmUgdXNlZCBhdCBvbmNlLg=="
================================================
FILE: DevToys/DevToys/Body/Coder/HTMLDecoderView+.swift
================================================
//
// HTMLDecoder.swift
// DevToys
//
// Created by yuki on 2022/01/30.
//
import CoreUtil
import HTMLEntities
final class HTMLDecoderViewController: NSViewController {
private let cell = HTMLDecoderView()
@RestorableState("html.rawString") var rawString = "<script>alert(\"abc\")</script>"
@RestorableState("html.formattedString") var formattedString = "<script>alert("abc")</script>"
override func loadView() { self.view = cell }
override func viewDidLoad() {
self.cell.decodeTextSection.stringPublisher
.sink{[unowned self] in self.rawString = $0; self.formattedString = $0.htmlEscape() }.store(in: &objectBag)
self.cell.encodeTextSection.stringPublisher
.sink{[unowned self] in self.formattedString = $0; self.rawString = $0.htmlUnescape() }.store(in: &objectBag)
self.$rawString
.sink{[unowned self] in self.cell.decodeTextSection.string = $0 }.store(in: &objectBag)
self.$formattedString
.sink{[unowned self] in self.cell.encodeTextSection.string = $0 }.store(in: &objectBag)
}
}
final private class HTMLDecoderView: Page {
let decodeTextSection = CodeViewSection(title: "Decoded".localized(), options: [.all], language: .xml)
let encodeTextSection = TextViewSection(title: "Encoded".localized(), options: [.all])
override func layout() {
super.layout()
let halfHeight = max(200, (self.frame.height - 100) / 2)
self.decodeTextSection.snp.remakeConstraints{ make in
make.height.equalTo(halfHeight)
}
self.encodeTextSection.snp.remakeConstraints{ make in
make.height.equalTo(halfHeight)
}
}
override func onAwake() {
self.addSection(decodeTextSection)
self.addSection(encodeTextSection)
}
}
================================================
FILE: DevToys/DevToys/Body/Coder/JWTDecoderView+.swift
================================================
//
// JWTDecoder.swift
// DevToys
//
// Created by yuki on 2022/02/01.
//
import CoreUtil
final class JWTDecoderViewController: NSViewController {
private let cell = JWTDecoderView()
@RestorableState("jwt.token") var token = defaultToken
@RestorableState("jwt.header") var header = defaultHeader
@RestorableState("jwt.payload") var payload = defaultPayload
override func loadView() { self.view = cell }
override func viewDidLoad() {
self.$token
.sink{[unowned self] in self.cell.tokenTextSection.string = $0 }.store(in: &objectBag)
self.$header
.sink{[unowned self] in self.cell.headerCodeSection.string = $0 }.store(in: &objectBag)
self.$payload
.sink{[unowned self] in self.cell.payloadCodeSection.string = $0 }.store(in: &objectBag)
self.cell.tokenTextSection.stringPublisher
.sink{[unowned self] in
self.token = $0
guard let (header, payload) = self.decodeJWT($0) else {
self.header = "[Decode Failed]"
self.payload = "[Decode Failed]"
return
}
self.header = header
self.payload = payload
}
.store(in: &objectBag)
}
private func decodeJWT(_ token: String) -> (header: String, payload: String)? {
let components = token.split(separator: ".").map{ String($0) }
guard components.count == 3 else { print("not3"); return nil }
guard let header = self.decodeBase64ToJson(components[0]) else { print("he"); return nil }
guard let payload = self.decodeBase64ToJson(components[1]) else { print("pa"); return nil }
return (header, payload)
}
private func decodeBase64ToJson(_ string: String) -> String? {
guard let data = Data(base64Encoded: string) ?? Data(base64Encoded: string + "=") ?? Data(base64Encoded: string + "==") else { return nil }
guard let object = try? JSONSerialization.jsonObject(with: data, options: []) else { return nil }
guard let json = try? JSONSerialization.data(withJSONObject: object, options: .prettyPrinted) else { return nil }
return String(data: json, encoding: .utf8)
}
}
final private class JWTDecoderView: Page {
let tokenTextSection = TextViewSection(title: "JWT Token".localized(), options: .defaultInput)
let headerCodeSection = CodeViewSection(title: "Header".localized(), options: .defaultOutput, language: .javascript)
let payloadCodeSection = CodeViewSection(title: "Payload".localized(), options: .defaultOutput, language: .javascript)
override func layout() {
super.layout()
let contentHeight = max(100, (self.frame.height - 100) / 3)
self.tokenTextSection.snp.remakeConstraints{ make in
make.height.equalTo(contentHeight)
}
self.headerCodeSection.snp.remakeConstraints{ make in
make.height.equalTo(contentHeight)
}
self.payloadCodeSection.snp.remakeConstraints{ make in
make.height.equalTo(contentHeight)
}
}
override func onAwake() {
self.addSection(tokenTextSection)
self.tokenTextSection.textView.snp.remakeConstraints{ make in
make.height.equalTo(85)
}
self.addSection(headerCodeSection)
self.headerCodeSection.textView.snp.remakeConstraints{ make in
make.height.equalTo(100)
}
self.addSection(payloadCodeSection)
self.payloadCodeSection.textView.snp.remakeConstraints{ make in
make.height.equalTo(100)
}
}
}
private let defaultToken = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkFsaWNlIiwiYWdlIjoxNn0.Ir_wyzMjqDXeeaGWJVgdysutJ6C9E3MX11t38LD2K60"
private let defaultPayload = """
{
"sub": "1234567890",
"name": "Alice",
"age": 16
}
"""
private let defaultHeader = """
{
"alg": "HS256",
"typ": "JWT"
}
"""
================================================
FILE: DevToys/DevToys/Body/Coder/URLDecoderView+.swift
================================================
//
// URLDecoder.swift
// DevToys
//
// Created by yuki on 2022/01/30.
//
import CoreUtil
final class URLDecoderViewController: NSViewController {
private let cell = URLDecoderView()
@RestorableState("url.rawString") var rawString = "https://www.microsoft.com/ja-jp/p/devtoys/9pgcv4v3bk4w?rtc=1#activetab=pivot:overviewtab"
@RestorableState("url.formattedString") var formattedString = "https%3A%2F%2Fwww.microsoft.com%2Fja-jp%2Fp%2Fdevtoys%2F9pgcv4v3bk4w%3Frtc%3D1%23activetab%3Dpivot%3Aoverviewtab"
override func loadView() { self.view = cell }
override func viewDidLoad() {
self.cell.decodeTextSection.stringPublisher
.sink{[unowned self] in self.rawString = $0; self.formattedString = encodeToURL($0) }.store(in: &objectBag)
self.cell.encodeTextSection.stringPublisher
.sink{[unowned self] in self.formattedString = $0; if let s = $0.removingPercentEncoding { self.rawString = s } }.store(in: &objectBag)
self.$rawString
.sink{[unowned self] in self.cell.decodeTextSection.string = $0 }.store(in: &objectBag)
self.$formattedString
.sink{[unowned self] in self.cell.encodeTextSection.string = $0 }.store(in: &objectBag)
}
private func encodeToURL(_ string: String) -> String {
let allowedCharacters = NSCharacterSet.alphanumerics.union(.init(charactersIn: "-._~"))
return string.addingPercentEncoding(withAllowedCharacters: allowedCharacters) ?? "???"
}
}
final private class URLDecoderView: Page {
let decodeTextSection = TextViewSection(title: "Decoded".localized(), options: [.all])
let encodeTextSection = TextViewSection(title: "Encoded".localized(), options: [.all])
override func layout() {
super.layout()
let halfHeight = max(200, (self.frame.height - 100) / 2)
self.decodeTextSection.snp.remakeConstraints{ make in
make.height.equalTo(halfHeight)
}
self.encodeTextSection.snp.remakeConstraints{ make in
make.height.equalTo(halfHeight)
}
}
override func onAwake() {
self.addSection(decodeTextSection)
self.addSection(encodeTextSection)
}
}
================================================
FILE: DevToys/DevToys/Body/Convert/DateConverterView+.swift
================================================
//
// DateConverter.swift
// DevToys
//
// Created by yuki on 2022/02/04.
//
import CoreUtil
final class DateConverterViewController: NSViewController {
private let cell = DateConverterView()
@Observable var date = Date()
private let isoFormatter = ISO8601DateFormatter()
private let gmtFormatter = DateFormatter() => {
$0.locale = Locale(identifier: "en_US_POSIX")
$0.timeZone = TimeZone(abbreviation: "GMT")
}
override func loadView() { self.view = cell }
override func viewDidLoad() {
self.$date
.sink{[unowned self] in
self.cell.datePicker.date = $0
self.cell.unixTimeField.value = $0.timeIntervalSince1970.rounded()
self.cell.isoDateField.string = isoFormatter.string(from: $0)
self.cell.graphicDatePicker.dateValue = $0
}
.store(in: &objectBag)
self.cell.graphicDatePicker.actionPublisher
.sink{[unowned self] in self.date = cell.graphicDatePicker.dateValue }.store(in: &objectBag)
self.cell.nowButton.actionPublisher
.sink{[unowned self] in self.date = Date() }.store(in: &objectBag)
self.cell.datePicker.datePublisher
.sink{[unowned self] in self.date = $0 }.store(in: &objectBag)
self.cell.unixTimeField.valuePublisher
.sink{[unowned self] in self.date = Date(timeIntervalSince1970: $0.reduce(self.date.timeIntervalSince1970)) }.store(in: &objectBag)
self.cell.isoDateField.changeStringPublisher.compactMap{[unowned self] in isoFormatter.date(from: $0) }
.sink{[unowned self] in self.date = $0 }.store(in: &objectBag)
}
}
final private class DateConverterView: Page {
let datePicker = DatePicker()
let utcDatePicker = DatePicker()
let nowButton = Button(title: "Now")
let unixTimeField = NumberField()
let isoDateField = TextField(showCopyButton: false)
let timestampDateField = TextField(showCopyButton: false)
let graphicDatePicker = NSDatePicker()
override func onAwake() {
self.addSection(Section(title: "Date".localized(), items: [
NSStackView() => {
$0.distribution = .equalSpacing
$0.addArrangedSubview(datePicker)
$0.addArrangedSubview(nowButton)
}
]))
self.datePicker.snp.remakeConstraints{ make in
make.right.equalTo(nowButton.snp.left).inset(-8)
}
self.addSection(Section(title: "Unix Time".localized(), items: [unixTimeField]))
self.unixTimeField.showStepper = false
self.unixTimeField.snp.remakeConstraints{ make in
make.height.equalTo(R.Size.controlHeight)
}
self.addSection(Section(title: "ISO 8601".localized(), items: [isoDateField]))
self.addSection(Section(title: "Timestamp".localized(), items: [timestampDateField]))
self.addSection(Section(title: "Calender".localized(), items: [graphicDatePicker]))
self.graphicDatePicker.datePickerStyle = .clockAndCalendar
}
}
================================================
FILE: DevToys/DevToys/Body/Convert/JSONYamlConverterView+.swift
================================================
//
// JSONYamlConverter+.swift
// DevToys
//
// Created by yuki on 2022/01/30.
//
import CoreUtil
import Yams
import SwiftJSONFormatter
final class JSONYamlConverterViewController: NSViewController {
private let cell = JSONYamlConverterView()
@RestorableState("jy.format") private var formatStyle: FormatStyle = .pretty
@RestorableState("jy.json") private var jsonCode = defaultJsonCode
@RestorableState("jy.yaml") private var yamlCode = defaultYamlCode
override func loadView() { self.view = cell }
override func viewDidLoad() {
self.$jsonCode
.sink{[unowned self] in self.cell.jsonSection.string = $0 }.store(in: &objectBag)
self.$yamlCode
.sink{[unowned self] in self.cell.yamlSection.string = $0 }.store(in: &objectBag)
self.$formatStyle
.sink{[unowned self] in self.cell.formatStylePicker.selectedItem = $0 }.store(in: &objectBag)
self.cell.formatStylePicker.itemPublisher
.sink{[unowned self] in self.formatStyle = $0 }.store(in: &objectBag)
self.cell.jsonSection.stringPublisher
.sink{[unowned self] in
self.jsonCode = $0
if let yamlCode = convertJsonToYaml(code: $0, formatStyle: self.formatStyle) {
self.yamlCode = yamlCode
}
}
.store(in: &objectBag)
self.cell.yamlSection.stringPublisher
.sink{[unowned self] in
self.yamlCode = $0
if let jsonCode = convertYamlToJson(code: $0, formatStyle: self.formatStyle) { self.jsonCode = jsonCode }
}
.store(in: &objectBag)
}
private func convertYamlToJson(code: String, formatStyle: FormatStyle) -> String? {
if code.isEmpty { return "" }
guard let object = try? Yams.load(yaml: code) else { return nil }
var options = JSONSerialization.WritingOptions()
options.insert(.sortedKeys)
if formatStyle == .pretty { options.insert(.prettyPrinted) }
return try? objc_try {
guard let data = try? JSONSerialization.data(withJSONObject: object, options: options) else { return nil }
let json = String(data: data, encoding: .utf8)!
return SwiftJSONFormatter.beautify(json, indent: " ")
}
}
private func convertJsonToYaml(code: String, formatStyle: FormatStyle) -> String? {
if code.isEmpty { return "" }
return objc_try({
guard let object = try? JSONSerialization.jsonObject(with: code.data(using: .utf8)!) else {
return nil
}
let swiftObject = convertNSObject(object)
return try? Yams.dump(object: swiftObject)
}, catch: {_ in
return nil
})
}
private func convertNSObject(_ object: Any) -> Any {
if let object = object as? NSDictionary {
return (object as! [String: Any]).mapValues{ convertNSObject($0) }
}
if let object = object as? NSArray { return (object as! [Any]).map{ convertNSObject($0) } }
if let object = object as? NSString { return object as String }
if let object = object as? NSNumber {
switch CFNumberGetType(object) {
case .cgFloatType, .floatType, .doubleType, .float32Type, .float64Type: return object.doubleValue
case .longLongType, .longType, .shortType, .intType, .sInt8Type, .sInt16Type, .sInt32Type, .sInt64Type, .cfIndexType, .nsIntegerType: return object.intValue
case .charType: return object.boolValue
@unknown default: return object.intValue
}
}
return object
}
}
private enum FormatStyle: String, TextItem {
case pretty = "Pretty"
case minified = "Minified"
var title: String { rawValue.localized() }
}
final private class JSONYamlConverterView: Page {
let formatStylePicker = EnumPopupButton<FormatStyle>()
let jsonSection = CodeViewSection(title: "JSON", options: .all, language: .javascript)
let yamlSection = CodeViewSection(title: "Yaml", options: .all, language: .yaml)
private lazy var ioStack = self.addSection2(jsonSection, yamlSection)
override func layout() {
super.layout()
self.ioStack.snp.remakeConstraints{ make in
make.height.equalTo(max(240, self.frame.height - 170))
}
}
override func onAwake() {
self.addSection(Section(title: "Configuration".localized(), items: [
Area(icon: R.Image.format, title: "Format".localized(), control: formatStylePicker)
]))
}
}
private let defaultJsonCode = """
{
"type" : "members",
"members" : [
{
"name" : "Alice",
"age" : 16
},
{
"name" : "Bob",
"age" : 24
}
],
}
"""
private let defaultYamlCode = """
type: members
members:
- age: 16
name: Alice
- age: 24
name: Bob
"""
================================================
FILE: DevToys/DevToys/Body/Convert/NumberBaseConverterView+.swift
================================================
//
// NumberBaseConverter.swift
// DevToys
//
// Created by yuki on 2022/01/30.
//
import CoreUtil
final class NumberBaseConverterViewController: NSViewController {
private let cell = NumberBaseConverterView()
@RestorableState("numbase.format") private var formatNumber = true
@RestorableState("numbase.2") private var value2 = "1 0101 1010 0101 0011"
@RestorableState("numbase.10") private var value10 = "88,659"
@RestorableState("numbase.8") private var value8 = "255 123"
@RestorableState("numbase.16") private var value16 = "1 5A53"
override func loadView() { self.view = cell }
override func viewDidLoad() {
self.$value2
.sink{[unowned self] in cell.binarySection.string = $0 }.store(in: &objectBag)
self.$value8
.sink{[unowned self] in cell.octalSection.string = $0 }.store(in: &objectBag)
self.$value10
.sink{[unowned self] in cell.decimalSection.string = $0 }.store(in: &objectBag)
self.$value16
.sink{[unowned self] in cell.hexSection.string = $0 }.store(in: &objectBag)
self.$formatNumber
.sink{[unowned self] in cell.formatSwitch.state = $0 ? .on : .off }.store(in: &objectBag)
self.cell.binarySection.stringPublisher
.sink{[unowned self] in self.updateValue(string: $0, inputRadix: 2) }.store(in: &objectBag)
self.cell.octalSection.stringPublisher
.sink{[unowned self] in self.updateValue(string: $0, inputRadix: 8) }.store(in: &objectBag)
self.cell.decimalSection.stringPublisher
.sink{[unowned self] in self.updateValue(string: $0, inputRadix: 10) }.store(in: &objectBag)
self.cell.hexSection.stringPublisher
.sink{[unowned self] in self.updateValue(string: $0, inputRadix: 16) }.store(in: &objectBag)
self.cell.formatSwitch.actionPublisher.map{[unowned self] in self.cell.formatSwitch.state == .on }
.sink{[unowned self] in self.formatNumber = $0; updateFormat() }.store(in: &objectBag)
}
private func updateFormat() {
self.updateValue(string: value10, inputRadix: 10)
}
private func updateValue(string: String, inputRadix: Int) {
let value = Int(string.replacingOccurrences(of: " ", with: "").replacingOccurrences(of: ",", with: ""), radix: inputRadix)
self.value2 = self.convertBinary(value, format: self.formatNumber)
self.value8 = self.convertOctal(value, format: self.formatNumber)
self.value10 = self.convertDecimal(value, format: self.formatNumber)
self.value16 = self.convertHex(value, format: self.formatNumber)
}
private func convertHex(_ value: Int?, format: Bool) -> String {
guard let value = value else { return "0" }
let string = String(value, radix: 16, uppercase: true)
if format { return splitString(string, split: 4, separator: " ") } else { return string }
}
private func convertDecimal(_ value: Int?, format: Bool) -> String {
guard let value = value else { return "0" }
let string = String(value, radix: 10, uppercase: true)
if format { return splitString(string, split: 3, separator: ",") } else { return string }
}
private func convertOctal(_ value: Int?, format: Bool) -> String {
guard let value = value else { return "0" }
let string = String(value, radix: 8, uppercase: true)
if format { return splitString(string, split: 3, separator: " ") } else { return string }
}
private func convertBinary(_ value: Int?, format: Bool) -> String {
guard let value = value else { return "0" }
let string = String(value, radix: 2, uppercase: true)
if format { return splitString(string, split: 4, separator: " ") } else { return string }
}
private func splitString(_ string: String, split: Int, separator: String) -> String {
var result = ""
var count = string.count
for c in string {
count -= 1
result.append(c)
if count != 0, count % split == 0 { result.append(separator) }
}
return result
}
private func convert(_ value: Int?, radix: Int) -> String {
guard let value = value else { return "0" }
return String(value, radix: radix, uppercase: true)
}
}
final private class NumberBaseConverterView: Page {
let formatSwitch = NSSwitch()
let decimalSection = TextFieldSection(title: "Decimal".localized())
let hexSection = TextFieldSection(title: "Hexdecimal".localized())
let octalSection = TextFieldSection(title: "Octal".localized())
let binarySection = TextFieldSection(title: "Binary".localized())
private lazy var formatNumberArea = Area(icon: R.Image.format, title: "Format Number".localized(), control: formatSwitch)
private lazy var configurationSection = Section(title: "Configuration".localized(), items: [formatNumberArea])
override func onAwake() {
self.addSection(configurationSection)
self.addSection(decimalSection)
self.addSection(hexSection)
self.addSection(octalSection)
self.addSection(binarySection)
}
}
================================================
FILE: DevToys/DevToys/Body/Format/JSONFormatterView+.swift
================================================
//
// JSONFormatter+.swift
// DevToys
//
// Created by yuki on 2022/01/29.
//
import CoreUtil
import SwiftJSONFormatter
final class JSONFormatterViewController: NSViewController {
@RestorableState("json.spacingtype") var spacingType: JSONSpacingType = .spaces4
@RestorableState("jq.rawCode") var rawCode: String = #"{ "Hello": "World" }"#
@RestorableState("jq.formattedCode") var formattedCode: String = "{\n \"Hello\": \"World\"\n}"
private let cell = JSONFormatterView()
override func loadView() { self.view = cell }
override func viewDidLoad() {
self.$spacingType
.sink{[unowned self] in cell.indentControl.selectedItem = $0 }.store(in: &objectBag)
self.$rawCode
.sink{[unowned self] in cell.inputSection.string = $0 }.store(in: &objectBag)
self.$formattedCode
.sink{[unowned self] in cell.outputSection.string = $0 }.store(in: &objectBag)
self.cell.inputSection.stringPublisher
.sink{[unowned self] in self.rawCode = $0; updateFormattedCode() }.store(in: &objectBag)
self.cell.indentControl.itemPublisher
.sink{[unowned self] in self.spacingType = $0; updateFormattedCode() }.store(in: &objectBag)
}
private func updateFormattedCode() {
self.formattedCode = processJSON(rawCode, spacingType: spacingType)
}
private func processJSON(_ code: String, spacingType: JSONSpacingType) -> String {
switch spacingType {
case .spaces2: return SwiftJSONFormatter.beautify(code, indent: " ")
case .spaces4: return SwiftJSONFormatter.beautify(code, indent: " ")
case .tab1: return SwiftJSONFormatter.beautify(code, indent: "\t")
case .minified: return SwiftJSONFormatter.minify(code)
}
}
}
enum JSONSpacingType: String, TextItem {
case spaces2 = "2 Spaces"
case spaces4 = "4 Spaces"
case tab1 = "1 Tab"
case minified = "Minified"
var title: String { rawValue.localized() }
}
final private class JSONFormatterView: Page {
let indentControl = EnumPopupButton<JSONSpacingType>()
let inputSection = CodeViewSection(title: "Input".localized(), options: .defaultInput, language: .javascript)
let outputSection = CodeViewSection(title: "Output".localized(), options: .defaultOutput, language: .javascript)
private lazy var indentArea = Area(icon: R.Image.spacing, title: "Indentation".localized(), control: indentControl)
private lazy var configurationSection = Section(title: "Configuration".localized(), items: [indentArea])
private lazy var ioStack = self.addSection2(inputSection, outputSection)
override func layout() {
super.layout()
self.ioStack.snp.remakeConstraints{ make in
make.height.equalTo(max(240, self.frame.height - 180))
}
}
override func onAwake() {
self.addSection(configurationSection)
self.outputSection.textView.textView.usesFindBar = true
}
}
================================================
FILE: DevToys/DevToys/Body/Format/SQLFormatterView+.swift
================================================
//
// SQLFormatterView+.swift
// DevToys
//
// Created by yuki on 2022/02/26.
//
import CoreUtil
final class SQLFormatterViewController: NSViewController {
private let cell = SQLFormatterView()
override func loadView() { self.view = cell }
override func viewDidLoad() {
}
}
final private class SQLFormatterView: Page {
override func onAwake() {
}
}
================================================
FILE: DevToys/DevToys/Body/Format/XMLFormatterView+.swift
================================================
//
// XMLFormatter.swift
// DevToys
//
// Created by yuki on 2022/02/04.
//
import CoreUtil
final class XMLFormatterViewController: NSViewController {
@RestorableState("xml.rawCode") private var rawCode: String = ""
@RestorableState("xml.formattedCode") private var formattedCode: String = ""
@RestorableState("xml.documentType") private var documentType: DocumentType = .xmlDocument
@RestorableState("xml.pretty") private var pretty = true
@RestorableState("xml.autofix") private var autofix = true
private let cell = XMLFormatterView()
override func loadView() { self.view = cell }
override func viewDidLoad() {
self.$rawCode
.sink{[unowned self] in cell.inputSection.string = $0 }.store(in: &objectBag)
self.$formattedCode
.sink{[unowned self] in cell.outputSection.string = $0 }.store(in: &objectBag)
self.$documentType
.sink{[unowned self] in cell.documentTypeControl.selectedItem = $0 }.store(in: &objectBag)
self.$pretty
.sink{[unowned self] in cell.prettySwitch.isOn = $0 }.store(in: &objectBag)
self.$autofix
.sink{[unowned self] in cell.autoFixSwitch.isOn = $0 }.store(in: &objectBag)
self.cell.prettySwitch.isOnPublisher
.sink{[unowned self] in self.pretty = $0; updateFormattedCode() }.store(in: &objectBag)
self.cell.autoFixSwitch.isOnPublisher
.sink{[unowned self] in self.autofix = $0; updateFormattedCode() }.store(in: &objectBag)
self.cell.documentTypeControl.itemPublisher
.sink{[unowned self] in self.documentType = $0; updateFormattedCode() }.store(in: &objectBag)
self.cell.inputSection.stringPublisher
.sink{[unowned self] in self.rawCode = $0; updateFormattedCode() }.store(in: &objectBag)
self.updateFormattedCode()
}
private func updateFormattedCode() {
do {
var options = XMLNode.Options()
if pretty {
options.insert(.nodePrettyPrint)
}
if autofix {
switch documentType {
case .htmlDocument: options.insert(.documentTidyHTML)
case .xmlDocument: options.insert(.documentTidyXML)
}
}
let document = try XMLDocument(xmlString: rawCode, options: options)
self.formattedCode = document.xmlString(options: options)
.replacingOccurrences(of: #"<?xml version="1.0" encoding="UTF-8"?>"#, with: "")
.replacingOccurrences(of: #"<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">"#, with: "")
.replacingOccurrences(of: #"<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">"#, with: "")
.replacingOccurrences(of: #"<html xmlns="http://www.w3.org/1999/xhtml">"#, with: "<html>")
.trimmingCharacters(in: CharacterSet.whitespacesAndNewlines)
} catch {
self.formattedCode = "[Invalid Document]"
}
}
}
private enum DocumentType: String, TextItem {
case htmlDocument = "HTML Document"
case xmlDocument = "XML Document"
var title: String { rawValue.localized() }
}
final private class XMLFormatterView: Page {
let prettySwitch = NSSwitch()
let autoFixSwitch = NSSwitch()
let documentTypeControl = EnumPopupButton<DocumentType>()
let inputSection = CodeViewSection(title: "Input".localized(), options: .defaultInput, language: .xml)
let outputSection = CodeViewSection(title: "Output".localized(), options: .defaultOutput, language: .xml)
private lazy var configurationSection = Section(title: "Configuration".localized(), items: [
Area(icon: R.Image.convert, title: "Document Type".localized(), control: documentTypeControl),
NSStackView() => {
$0.orientation = .horizontal
$0.distribution = .fillEqually
$0.addArrangedSubview(Area(icon: R.Image.format, title: "Auto Fix Document".localized(), control: autoFixSwitch))
$0.addArrangedSubview(Area(icon: R.Image.format, title: "Pretty Document".localized(), control: prettySwitch))
}
])
private lazy var ioStack = self.addSection2(inputSection, outputSection)
override func layout() {
super.layout()
self.ioStack.snp.remakeConstraints{ make in
make.height.equalTo(max(240, self.frame.height - 230))
}
}
override func onAwake() {
self.addSection(configurationSection)
}
}
================================================
FILE: DevToys/DevToys/Body/Generator/ChecksumGeneratorView+.swift
================================================
//
// ChecksumGenerator.swift
// DevToys
//
// Created by yuki on 2022/02/04.
//
import CoreUtil
final class ChecksumGeneratorViewController: NSViewController {
@RestorableState("checksum.uppercase") private var isUppercase = false
@RestorableState("checksum.alg") private var hashAlgorithm = HashAlgorithm.md5
@RestorableState("checksum.comparer") private var comparer = ""
@Observable private var output = ""
@Observable var isError = true
@Observable var fileURL: URL?
private let cell = ChecksumGeneratorView()
override func loadView() { self.view = cell }
override func viewDidLoad() {
self.$isUppercase
.sink{[unowned self] in cell.formatSwitch.isOn = $0 }.store(in: &objectBag)
self.$hashAlgorithm
.sink{[unowned self] in cell.hashAlgorithmPicker.selectedItem = $0 }.store(in: &objectBag)
self.$output
.sink{[unowned self] in cell.outputFieldSection.string = $0 }.store(in: &objectBag)
self.$comparer
.sink{[unowned self] in cell.compareFieldSection.string = $0 }.store(in: &objectBag)
self.$isError
.sink{[unowned self] in cell.compareFieldSection.textField.isError = $0 }.store(in: &objectBag)
self.cell.formatSwitch.isOnPublisher
.sink{[unowned self] in self.isUppercase = $0; updateHash() }.store(in: &objectBag)
self.cell.hashAlgorithmPicker.itemPublisher
.sink{[unowned self] in self.hashAlgorithm = $0; updateHash() }.store(in: &objectBag)
self.cell.compareFieldSection.stringPublisher
.sink{[unowned self] in self.comparer = $0; updateComparer() }.store(in: &objectBag)
self.cell.fileSection.urlsPublisher.compactMap{ $0.first }
.sink{[unowned self] in fileURL = $0; self.updateHash() }.store(in: &objectBag)
}
private func updateHash() {
guard let url = self.fileURL, let data = try? Data(contentsOf: url) else { return NSSound.beep() }
switch hashAlgorithm {
case .md5: self.output = data.md5().hexString(uppercase: isUppercase)
case .sha1: self.output = data.sha1().hexString(uppercase: isUppercase)
case .sha256: self.output = data.sha256().hexString(uppercase: isUppercase)
case .sha384: self.output = data.sha384().hexString(uppercase: isUppercase)
case .sha512: self.output = data.sha512().hexString(uppercase: isUppercase)
}
self.updateComparer()
}
private func updateComparer() {
self.isError = comparer.lowercased() != output.lowercased()
}
}
extension Data {
func hexString(uppercase: Bool) -> String {
self.map{ String(format: uppercase ? "%02X" : "%02x", $0) }.joined()
}
}
private enum HashAlgorithm: String, TextItem {
case md5 = "MD5"
case sha1 = "SHA1"
case sha256 = "SHA256"
case sha384 = "SHA384"
case sha512 = "SHA512"
var title: String { rawValue }
}
final private class ChecksumGeneratorView: Page {
let formatSwitch = NSSwitch()
let hashAlgorithmPicker = EnumPopupButton<HashAlgorithm>()
let fileSection = FileDropSection()
let outputFieldSection = TextFieldSection(title: "Output".localized(), isEditable: false)
let compareFieldSection = TextFieldSection(title: "Output Comparer".localized(), isEditable: true)
override func onAwake() {
self.addSection(Section(title: "Configuration".localized(), items: [
Area(icon: R.Image.format, title: "Uppercase".localized(), control: formatSwitch),
Area(icon: R.Image.convert, title: "Hash Algorithm".localized(), message: "Select which algorithm you want to use".localized(), control: hashAlgorithmPicker)
]))
self.addSection(fileSection)
self.addSection(outputFieldSection)
self.addSection(compareFieldSection)
}
}
================================================
FILE: DevToys/DevToys/Body/Generator/HashGeneratorView+.swift
================================================
//
// HashGenerator.swift
// DevToys
//
// Created by yuki on 2022/02/01.
//
import CoreUtil
import CryptoSwift
final class HashGeneratorViewController: NSViewController {
private let cell = HashGeneratorView()
@RestorableState("hash.upper") var isUppercase = false
@RestorableState("hash.input") var input = "Hello World"
@RestorableState("hash.md5") var md5 = ""
@RestorableState("hash.sha1") var sha1 = ""
@RestorableState("hash.sha256") var sha256 = ""
@RestorableState("hash.sha512") var sha512 = ""
override func loadView() { self.view = cell }
override func viewDidLoad() {
self.updateHash()
self.$isUppercase.sink{[unowned self] in self.cell.formatSwitch.isOn = $0 }.store(in: &objectBag)
self.$input.sink{[unowned self] in self.cell.textInputSection.string = $0 }.store(in: &objectBag)
self.$md5.sink{[unowned self] in self.cell.md5Section.string = $0 }.store(in: &objectBag)
self.$sha1.sink{[unowned self] in self.cell.sha1Section.string = $0 }.store(in: &objectBag)
self.$sha256.sink{[unowned self] in self.cell.sha256Section.string = $0 }.store(in: &objectBag)
self.$sha512.sink{[unowned self] in self.cell.sha512Section.string = $0 }.store(in: &objectBag)
self.cell.textInputSection.stringPublisher
.sink{[unowned self] in self.input = $0; updateHash() }.store(in: &objectBag)
self.cell.formatSwitch.isOnPublisher
.sink{[unowned self] in self.isUppercase = $0; updateHash() }.store(in: &objectBag)
}
private func updateHash() {
self.md5 = isUppercase ? input.md5().uppercased() : input.md5()
self.sha1 = isUppercase ? input.sha1().uppercased() : input.sha1()
self.sha256 = isUppercase ? input.sha256().uppercased() : input.sha256()
self.sha512 = isUppercase ? input.sha512().uppercased() : input.sha512()
}
}
final class HashGeneratorView: Page {
let formatSwitch = NSSwitch()
let textInputSection = TextViewSection(title: "Input".localized(), options: .all)
let md5Section = TextFieldSection(title: "MD5", isEditable: false)
let sha1Section = TextFieldSection(title: "SHA1", isEditable: false)
let sha256Section = TextFieldSection(title: "SHA256", isEditable: false)
let sha512Section = TextFieldSection(title: "SHA512", isEditable: false)
private lazy var formatNumberArea = Area(icon: R.Image.format, title: "Uppercase".localized(), control: formatSwitch)
private lazy var configurationSection = Section(title: "Configuration".localized(), items: [formatNumberArea])
override func onAwake() {
self.addSection(configurationSection)
self.addSection(textInputSection)
self.textInputSection.snp.remakeConstraints{ make in
make.height.equalTo(180)
}
self.addSection(md5Section)
self.addSection(sha1Section)
self.addSection(sha256Section)
self.addSection(sha512Section)
}
}
extension NSSwitch {
var isOn: Bool {
get { self.state == .on } set { self.state = newValue ? .on : .off }
}
var isOnPublisher: AnyPublisher<Bool, Never> {
self.actionPublisher.map{_ in self.state == .on }.eraseToAnyPublisher()
}
}
================================================
FILE: DevToys/DevToys/Body/Generator/LoremIpsumGeneratorView+.swift
================================================
//
// LoremIpsumGenerator.swift
// DevToys
//
// Created by yuki on 2022/02/01.
//
import CoreUtil
final class LoremIpsumGeneratorViewController: NSViewController {
private let cell = LoremIpsumGeneratorView()
@RestorableState("li.type") var generateType = LoremIpsumGenerateType.sentences
@RestorableState("li.length") var length = 3
@RestorableState("li.output") var output = "hello world"
override func loadView() { self.view = cell }
override func viewDidLoad() {
self.generate()
self.$generateType.sink{[unowned self] in self.cell.typePicker.selectedItem = $0 }.store(in: &objectBag)
self.$length.sink{[unowned self] in self.cell.lengthField.value = Double($0) }.store(in: &objectBag)
self.$output.sink{[unowned self] in self.cell.outputSection.string = $0 }.store(in: &objectBag)
self.cell.typePicker.itemPublisher
.sink{[unowned self] in self.generateType = $0; generate() }.store(in: &objectBag)
self.cell.lengthField.valuePublisher.map{ $0.map{ Int($0) } }
.sink{[unowned self] in
let next = $0.reduce(self.length).clamped(1...)
if next != self.length { self.length = next; self.generate() }
}.store(in: &objectBag)
}
private func generate() {
switch self.generateType {
case .words: self.output = generateWords(length)
case .sentences: self.output = generateSentences(length)
case .paragraphs: self.output = generateParagraphs(length)
}
}
private func generateParagraphs(_ count: Int) -> String {
if count < 0 { return "" }
return (0..<count).map{_ in generateSentences(.random(in: 3...6)) }.joined(separator: "\n\n")
}
private func generateSentences(_ count: Int) -> String {
if count < 0 { return "" }
return (0..<count).map{_ in generateWords(.random(in: 10...20)) }.map{ $0 + "." }.joined(separator: " ")
}
private func generateWords(_ count: Int) -> String {
if count < 0 { return "" }
return (0..<count).map{_ in wordSource.randomElement()! }.joined(separator: " ").capitalizingFirstLetter()
}
}
enum LoremIpsumGenerateType: String, TextItem {
case words = "Words"
case sentences = "Sentences"
case paragraphs = "Paragraphs"
var title: String { rawValue.localized() }
}
final private class LoremIpsumGeneratorView: Page {
let typePicker = EnumPopupButton<LoremIpsumGenerateType>()
let lengthField = NumberField()
let outputSection = TextViewSection(title: "Output".localized(), options: [.outputable, .copyable, .inputable])
override func layout() {
super.layout()
self.outputSection.snp.remakeConstraints{ make in
make.height.equalTo(max(240, self.frame.height - 230))
}
}
override func onA
gitextract_01cekmvj/
├── .gitignore
├── CoreUtil/
│ ├── CoreUtil/
│ │ ├── Class/
│ │ │ ├── Action.swift
│ │ │ ├── Delta.swift
│ │ │ ├── NS+OnAwake.swift
│ │ │ ├── NSColorView.swift
│ │ │ ├── NSViewController+ChainObject.swift
│ │ │ ├── NSViewController+StateObject.swift
│ │ │ ├── Observable.swift
│ │ │ ├── PipeOperator.swift
│ │ │ ├── Query.swift
│ │ │ ├── Reachability+Publisher.swift
│ │ │ ├── Reachability.swift
│ │ │ ├── RestorableData.swift
│ │ │ ├── RestorableState.swift
│ │ │ ├── Terminal.swift
│ │ │ ├── ViewPlaceholder.swift
│ │ │ └── Zip3Sequence.swift
│ │ ├── CoreUtil.h
│ │ ├── ExceptionHanlder/
│ │ │ ├── ExceptionHandler.swift
│ │ │ ├── ExceptionHanlder.h
│ │ │ └── ExceptionHanlder.m
│ │ ├── Export.swift
│ │ ├── Extensions/
│ │ │ ├── Combine/
│ │ │ │ ├── Combine+ObjectBag.swift
│ │ │ │ ├── Combine+Peek.swift
│ │ │ │ ├── NSControl+Combine.swift
│ │ │ │ └── NSTextField+Combine.swift
│ │ │ ├── CoreGraphics/
│ │ │ │ ├── Ex+CGPoint.swift
│ │ │ │ ├── Ex+CGRect.swift
│ │ │ │ └── Ex+CGSize.swift
│ │ │ ├── Swift/
│ │ │ │ ├── Ex+Array.swift
│ │ │ │ ├── Ex+Clamp.swift
│ │ │ │ ├── Ex+Localize.swift
│ │ │ │ ├── Ex+Number.swift
│ │ │ │ └── Ex+OptionSet.swift
│ │ │ └── UI/
│ │ │ ├── Ex+CALayer.swift
│ │ │ ├── Ex+Image.swift
│ │ │ ├── Ex+NSColor.swift
│ │ │ ├── Ex+NSControl.swift
│ │ │ ├── Ex+NSEdgeInsets.swift
│ │ │ ├── Ex+NSEvent.swift
│ │ │ ├── Ex+NSMenuItem.swift
│ │ │ ├── Ex+NSPopover.swift
│ │ │ ├── Ex+NSTableView.swift
│ │ │ └── Ex+UI.swift
│ │ ├── HotKey/
│ │ │ ├── HotKey.swift
│ │ │ ├── Key.swift
│ │ │ └── NSEvent+HotKey.swift
│ │ └── Info.plist
│ └── CoreUtil.xcodeproj/
│ ├── project.pbxproj
│ └── project.xcworkspace/
│ ├── contents.xcworkspacedata
│ └── xcshareddata/
│ └── IDEWorkspaceChecks.plist
├── DevToys/
│ ├── DevToys/
│ │ ├── App/
│ │ │ ├── AppViewController.swift
│ │ │ └── AppWindowController.swift
│ │ ├── AppDelegate.swift
│ │ ├── Body/
│ │ │ ├── BodyViewController.swift
│ │ │ ├── Coder/
│ │ │ │ ├── Base64DecoderView+.swift
│ │ │ │ ├── HTMLDecoderView+.swift
│ │ │ │ ├── JWTDecoderView+.swift
│ │ │ │ └── URLDecoderView+.swift
│ │ │ ├── Convert/
│ │ │ │ ├── DateConverterView+.swift
│ │ │ │ ├── JSONYamlConverterView+.swift
│ │ │ │ └── NumberBaseConverterView+.swift
│ │ │ ├── Format/
│ │ │ │ ├── JSONFormatterView+.swift
│ │ │ │ ├── SQLFormatterView+.swift
│ │ │ │ └── XMLFormatterView+.swift
│ │ │ ├── Generator/
│ │ │ │ ├── ChecksumGeneratorView+.swift
│ │ │ │ ├── HashGeneratorView+.swift
│ │ │ │ ├── LoremIpsumGeneratorView+.swift
│ │ │ │ ├── QRCodeGeneratorView+.swift
│ │ │ │ └── UUIDGeneratorView+.swift
│ │ │ ├── Graphic/
│ │ │ │ ├── Icon Generator/
│ │ │ │ │ ├── Generators/
│ │ │ │ │ │ ├── AndroidIconGenerator.swift
│ │ │ │ │ │ ├── IOSIconGenerator.swift
│ │ │ │ │ │ ├── IcnsGenerator.swift
│ │ │ │ │ │ ├── IcoGenerator.swift
│ │ │ │ │ │ ├── IconFolderGenerator.swift
│ │ │ │ │ │ ├── IconGenerator+Model.swift
│ │ │ │ │ │ ├── IconsetGenerator.swift
│ │ │ │ │ │ ├── IosIconGenerator.swift
│ │ │ │ │ │ └── PngIconGenerator.swift
│ │ │ │ │ ├── Icon Templete/
│ │ │ │ │ │ ├── IconImageManager.swift
│ │ │ │ │ │ ├── IconSet.swift
│ │ │ │ │ │ ├── IconTemplete+.swift
│ │ │ │ │ │ └── IconTemplete.swift
│ │ │ │ │ └── IconGeneratorView+.swift
│ │ │ │ ├── Image Converter/
│ │ │ │ │ ├── Exporters/
│ │ │ │ │ │ ├── DefaultImageExporter.swift
│ │ │ │ │ │ ├── HeicImageExporter.swift
│ │ │ │ │ │ ├── WebpImageExporter.swift
│ │ │ │ │ │ └── cwebp
│ │ │ │ │ ├── ImageConverter.swift
│ │ │ │ │ └── ImageConverterView+.swift
│ │ │ │ ├── Image Optimizer/
│ │ │ │ │ ├── ImageOptimaizerView.swift
│ │ │ │ │ ├── ImageOptimizer.swift
│ │ │ │ │ ├── jpegoptim
│ │ │ │ │ └── optipng
│ │ │ │ ├── PDFGeneratorView+.swift
│ │ │ │ └── QRCodeReaderView+.swift
│ │ │ ├── HomeView+.swift
│ │ │ ├── Media/
│ │ │ │ ├── Audio Converter/
│ │ │ │ │ ├── AudioConverter.swift
│ │ │ │ │ ├── AudioConverterView+.swift
│ │ │ │ │ └── AudioFileScanner.swift
│ │ │ │ ├── Color Picker/
│ │ │ │ │ ├── Color.swift
│ │ │ │ │ ├── ColorPickerView+.swift
│ │ │ │ │ ├── Components/
│ │ │ │ │ │ ├── BoxHSBColorPicker.swift
│ │ │ │ │ │ ├── BrightnessBarView.swift
│ │ │ │ │ │ ├── CircleBarsHSBColorPicker.swift
│ │ │ │ │ │ ├── CircleBoxHSBColorPicker.swift
│ │ │ │ │ │ ├── CircleHueBarView.swift
│ │ │ │ │ │ ├── ColorBoxView.swift
│ │ │ │ │ │ ├── ColorPickerHandleLayer.swift
│ │ │ │ │ │ ├── ColorSampleView.swift
│ │ │ │ │ │ ├── HueBarView.swift
│ │ │ │ │ │ ├── OpacityBarView.swift
│ │ │ │ │ │ └── SaturationBarView.swift
│ │ │ │ │ ├── Pixel Picker/
│ │ │ │ │ │ ├── ACOverlayController.swift
│ │ │ │ │ │ ├── ACOverlayController.xib
│ │ │ │ │ │ ├── ACOverlayPanel.swift
│ │ │ │ │ │ ├── ACOverlayPreview.swift
│ │ │ │ │ │ ├── ACOverlayWrapper.swift
│ │ │ │ │ │ ├── ACPixelPicker.swift
│ │ │ │ │ │ └── Utils/
│ │ │ │ │ │ ├── Ex+CGImage.swift
│ │ │ │ │ │ ├── Ex+NSBezierPath.swift
│ │ │ │ │ │ ├── Ex+NSColor.swift
│ │ │ │ │ │ ├── ShowAndHideCursor.h
│ │ │ │ │ │ ├── ShowAndHideCursor.m
│ │ │ │ │ │ ├── ShowAndHideCursor.swift
│ │ │ │ │ │ └── Util+PixelPicker.swift
│ │ │ │ │ └── R+ColorPicker.swift
│ │ │ │ └── Movie to Gif/
│ │ │ │ ├── GifConverter.swift
│ │ │ │ └── GifConverterView+.swift
│ │ │ ├── SettingView+.swift
│ │ │ ├── Text/
│ │ │ │ ├── HyphenationRemoverView+.swift
│ │ │ │ ├── JSON Search/
│ │ │ │ │ ├── JSONNormalSearchView.swift
│ │ │ │ │ └── JSONSearchView+.swift
│ │ │ │ ├── RegexTesterView+.swift
│ │ │ │ ├── TextDiffView+.swift
│ │ │ │ └── TextInspectorView+.swift
│ │ │ └── Utils/
│ │ │ ├── CameraViewController.swift
│ │ │ ├── FileConflictAvoider.swift
│ │ │ ├── Identifier.swift
│ │ │ ├── ImageDropper.swift
│ │ │ ├── Slugify.swift
│ │ │ └── ffmpeg/
│ │ │ ├── FFMpegExecutor.swift
│ │ │ ├── FFProgressReport.swift
│ │ │ ├── FFTask.swift
│ │ │ ├── FFThumnailGenerator.swift
│ │ │ ├── FFTime.swift
│ │ │ └── ffmpeg
│ │ ├── Bridging-Header.h
│ │ ├── Component/
│ │ │ ├── Area.swift
│ │ │ ├── Button.swift
│ │ │ ├── CodeTextView.swift
│ │ │ ├── ControlBackgroundLayer.swift
│ │ │ ├── ControlContainer.swift
│ │ │ ├── DatePicker.swift
│ │ │ ├── DragImageView.swift
│ │ │ ├── EmptyImageTableView.swift
│ │ │ ├── FileDrop.swift
│ │ │ ├── ImageDropView.swift
│ │ │ ├── NumberField.swift
│ │ │ ├── Page.swift
│ │ │ ├── PopupButton.swift
│ │ │ ├── RegexTextView.swift
│ │ │ ├── Section.swift
│ │ │ ├── SectionButton+.swift
│ │ │ ├── SectionButton.swift
│ │ │ ├── TagCloudView.swift
│ │ │ ├── TextField.swift
│ │ │ ├── TextFieldSection.swift
│ │ │ ├── TextView.swift
│ │ │ ├── TextViewSection.swift
│ │ │ └── Toast.swift
│ │ ├── DevToys.entitlements
│ │ ├── Info.plist
│ │ ├── Model/
│ │ │ ├── AppModel.swift
│ │ │ ├── Settings.swift
│ │ │ ├── Tool+Default.swift
│ │ │ ├── ToolCategory+Default.swift
│ │ │ └── ToolManager+.swift
│ │ ├── Resource/
│ │ │ ├── Assets.xcassets/
│ │ │ │ ├── AccentColor.colorset/
│ │ │ │ │ └── Contents.json
│ │ │ │ ├── AppIcon.appiconset/
│ │ │ │ │ └── Contents.json
│ │ │ │ ├── Contents.json
│ │ │ │ ├── applewatch.imageset/
│ │ │ │ │ └── Contents.json
│ │ │ │ ├── carplay.imageset/
│ │ │ │ │ └── Contents.json
│ │ │ │ ├── check.imageset/
│ │ │ │ │ └── Contents.json
│ │ │ │ ├── clear.imageset/
│ │ │ │ │ └── Contents.json
│ │ │ │ ├── convert.imageset/
│ │ │ │ │ └── Contents.json
│ │ │ │ ├── copy.imageset/
│ │ │ │ │ └── Contents.json
│ │ │ │ ├── drop.imageset/
│ │ │ │ │ └── Contents.json
│ │ │ │ ├── error.imageset/
│ │ │ │ │ └── Contents.json
│ │ │ │ ├── export.imageset/
│ │ │ │ │ └── Contents.json
│ │ │ │ ├── format.imageset/
│ │ │ │ │ └── Contents.json
│ │ │ │ ├── hyphen.imageset/
│ │ │ │ │ └── Contents.json
│ │ │ │ ├── ipad.imageset/
│ │ │ │ │ └── Contents.json
│ │ │ │ ├── ipaddress.imageset/
│ │ │ │ │ └── Contents.json
│ │ │ │ ├── iphone.imageset/
│ │ │ │ │ └── Contents.json
│ │ │ │ ├── mac.imageset/
│ │ │ │ │ └── Contents.json
│ │ │ │ ├── network.status.imageset/
│ │ │ │ │ └── Contents.json
│ │ │ │ ├── number.imageset/
│ │ │ │ │ └── Contents.json
│ │ │ │ ├── open.imageset/
│ │ │ │ │ └── Contents.json
│ │ │ │ ├── paramators.imageset/
│ │ │ │ │ └── Contents.json
│ │ │ │ ├── paste.imageset/
│ │ │ │ │ └── Contents.json
│ │ │ │ ├── pulldown.indicator.imageset/
│ │ │ │ │ └── Contents.json
│ │ │ │ ├── search.imageset/
│ │ │ │ │ └── Contents.json
│ │ │ │ ├── settings.imageset/
│ │ │ │ │ └── Contents.json
│ │ │ │ ├── sidebar.disclosure.imageset/
│ │ │ │ │ └── Contents.json
│ │ │ │ ├── spacing.imageset/
│ │ │ │ │ └── Contents.json
│ │ │ │ ├── speed.imageset/
│ │ │ │ │ └── Contents.json
│ │ │ │ ├── spuit.imageset/
│ │ │ │ │ └── Contents.json
│ │ │ │ ├── stepper.down.imageset/
│ │ │ │ │ └── Contents.json
│ │ │ │ ├── stepper.up.imageset/
│ │ │ │ │ └── Contents.json
│ │ │ │ ├── text.imageset/
│ │ │ │ │ └── Contents.json
│ │ │ │ ├── tool/
│ │ │ │ │ ├── Contents.json
│ │ │ │ │ ├── api.imageset/
│ │ │ │ │ │ └── Contents.json
│ │ │ │ │ ├── audio.convert.imageset/
│ │ │ │ │ │ └── Contents.json
│ │ │ │ │ ├── base64.coder.imageset/
│ │ │ │ │ │ └── Contents.json
│ │ │ │ │ ├── color.blindness.simulator.imageset/
│ │ │ │ │ │ └── Contents.json
│ │ │ │ │ ├── color.picker.imageset/
│ │ │ │ │ │ └── Contents.json
│ │ │ │ │ ├── convert.imageset/
│ │ │ │ │ │ └── Contents.json
│ │ │ │ │ ├── date.convert.imageset/
│ │ │ │ │ │ └── Contents.json
│ │ │ │ │ ├── encoder.decoder.imageset/
│ │ │ │ │ │ └── Contents.json
│ │ │ │ │ ├── formatter.imageset/
│ │ │ │ │ │ └── Contents.json
│ │ │ │ │ ├── generator.imageset/
│ │ │ │ │ │ └── Contents.json
│ │ │ │ │ ├── gif.imageset/
│ │ │ │ │ │ └── Contents.json
│ │ │ │ │ ├── graphic.imageset/
│ │ │ │ │ │ └── Contents.json
│ │ │ │ │ ├── hash.generator.imageset/
│ │ │ │ │ │ └── Contents.json
│ │ │ │ │ ├── home.imageset/
│ │ │ │ │ │ └── Contents.json
│ │ │ │ │ ├── html.coder.imageset/
│ │ │ │ │ │ └── Contents.json
│ │ │ │ │ ├── icon.generator.imageset/
│ │ │ │ │ │ └── Contents.json
│ │ │ │ │ ├── image.compressor.imageset/
│ │ │ │ │ │ └── Contents.json
│ │ │ │ │ ├── image.converter.imageset/
│ │ │ │ │ │ └── Contents.json
│ │ │ │ │ ├── json.convert.imageset/
│ │ │ │ │ │ └── Contents.json
│ │ │ │ │ ├── json.formatter.imageset/
│ │ │ │ │ │ └── Contents.json
│ │ │ │ │ ├── json.search.imageset/
│ │ │ │ │ │ └── Contents.json
│ │ │ │ │ ├── jwt.coder.imageset/
│ │ │ │ │ │ └── Contents.json
│ │ │ │ │ ├── lorem.ipsum.generator.imageset/
│ │ │ │ │ │ └── Contents.json
│ │ │ │ │ ├── markdown.preview.imageset/
│ │ │ │ │ │ └── Contents.json
│ │ │ │ │ ├── media.imageset/
│ │ │ │ │ │ └── Contents.json
│ │ │ │ │ ├── network.imageset/
│ │ │ │ │ │ └── Contents.json
│ │ │ │ │ ├── number.base.convert.imageset/
│ │ │ │ │ │ └── Contents.json
│ │ │ │ │ ├── pdf.imageset/
│ │ │ │ │ │ └── Contents.json
│ │ │ │ │ ├── qr.generator.imageset/
│ │ │ │ │ │ └── Contents.json
│ │ │ │ │ ├── regex.tester.imageset/
│ │ │ │ │ │ └── Contents.json
│ │ │ │ │ ├── settings.imageset/
│ │ │ │ │ │ └── Contents.json
│ │ │ │ │ ├── sql.formatter.imageset/
│ │ │ │ │ │ └── Contents.json
│ │ │ │ │ ├── text.diff.imageset/
│ │ │ │ │ │ └── Contents.json
│ │ │ │ │ ├── text.imageset/
│ │ │ │ │ │ └── Contents.json
│ │ │ │ │ ├── text.inspector.imageset/
│ │ │ │ │ │ └── Contents.json
│ │ │ │ │ ├── url.coder.imageset/
│ │ │ │ │ │ └── Contents.json
│ │ │ │ │ ├── uuid.generator.imageset/
│ │ │ │ │ │ └── Contents.json
│ │ │ │ │ └── xml.formatter.imageset/
│ │ │ │ │ └── Contents.json
│ │ │ │ └── transparent_background.imageset/
│ │ │ │ └── Contents.json
│ │ │ ├── Base.lproj/
│ │ │ │ └── Main.storyboard
│ │ │ ├── R.swift
│ │ │ ├── de.lproj/
│ │ │ │ ├── Localizable.strings
│ │ │ │ └── Main.strings
│ │ │ ├── en.lproj/
│ │ │ │ ├── Localizable.strings
│ │ │ │ └── Main.strings
│ │ │ ├── es.lproj/
│ │ │ │ ├── Localizable.strings
│ │ │ │ └── Main.strings
│ │ │ ├── ja.lproj/
│ │ │ │ ├── Localizable.strings
│ │ │ │ └── Main.strings
│ │ │ ├── pt-BR.lproj/
│ │ │ │ ├── Localizable.strings
│ │ │ │ └── Main.strings
│ │ │ └── zh-Hans.lproj/
│ │ │ ├── Localizable.strings
│ │ │ └── Main.strings
│ │ └── Sidebar/
│ │ ├── SearchCell.swift
│ │ ├── SidebarView+.swift
│ │ ├── ToolCategoryCell.swift
│ │ ├── ToolMenuCell.swift
│ │ └── View/
│ │ └── Separator.swift
│ └── DevToys.xcodeproj/
│ ├── project.pbxproj
│ ├── project.xcworkspace/
│ │ ├── contents.xcworkspacedata
│ │ └── xcshareddata/
│ │ └── IDEWorkspaceChecks.plist
│ └── xcshareddata/
│ └── xcschemes/
│ └── DevToys.xcscheme
├── DevToys.xcworkspace/
│ ├── contents.xcworkspacedata
│ └── xcshareddata/
│ ├── IDEWorkspaceChecks.plist
│ └── swiftpm/
│ └── Package.resolved
├── LICENSE
├── README.md
├── Release Checklist.md
└── docs/
├── index.html
└── sparkle/
└── appcast.xml
Condensed preview — 282 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (977K chars).
[
{
"path": ".gitignore",
"chars": 2188,
"preview": "# Mac\n.DS_Store\n\n# Xcode\n#\n# gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & "
},
{
"path": "CoreUtil/CoreUtil/Class/Action.swift",
"chars": 337,
"preview": "//\n// Action.swift\n// CoreUtil\n//\n// Created by yuki on 2022/01/16.\n// Copyright © 2022 yuki. All rights reserved.\n/"
},
{
"path": "CoreUtil/CoreUtil/Class/Delta.swift",
"chars": 2881,
"preview": "//\n// Delta.swift\n// CoreUtil\n//\n// Created by yuki on 2020/05/14.\n// Copyright © 2020 yuki. All rights reserved.\n//"
},
{
"path": "CoreUtil/CoreUtil/Class/NS+OnAwake.swift",
"chars": 5858,
"preview": "//\n// NSLoadView.swift\n// CoreUtil\n//\n// Created by yuki on 2020/08/31.\n// Copyright © 2020 yuki. All rights reserve"
},
{
"path": "CoreUtil/CoreUtil/Class/NSColorView.swift",
"chars": 819,
"preview": "//\n// NSColorView.swift\n// CoreUtil\n//\n// Created by yuki on 2021/10/05.\n// Copyright © 2021 yuki. All rights reserv"
},
{
"path": "CoreUtil/CoreUtil/Class/NSViewController+ChainObject.swift",
"chars": 1524,
"preview": "//\n// NSViewController.swift\n// CoreUtil\n//\n// Created by yuki on 2021/07/19.\n// Copyright © 2021 yuki. All rights r"
},
{
"path": "CoreUtil/CoreUtil/Class/NSViewController+StateObject.swift",
"chars": 3257,
"preview": "//\n// NSViewController+StateObject.swift\n// CoreUtil\n//\n// Created by yuki on 2021/06/24.\n// Copyright © 2021 yuki. "
},
{
"path": "CoreUtil/CoreUtil/Class/Observable.swift",
"chars": 1081,
"preview": "//\n// Property.swift\n// CoreUtil\n//\n// Created by yuki on 2020/07/06.\n// Copyright © 2020 yuki. All rights reserved."
},
{
"path": "CoreUtil/CoreUtil/Class/PipeOperator.swift",
"chars": 740,
"preview": "//\n// +Functions.swift\n// CoreUtil\n//\n// Created by yuki on 2020/10/01.\n// Copyright © 2020 yuki. All rights reserve"
},
{
"path": "CoreUtil/CoreUtil/Class/Query.swift",
"chars": 1222,
"preview": "//\n// Query.swift\n// CoreUtil\n//\n// Created by yuki on 2020/01/13.\n// Copyright © 2020 yuki. All rights reserved.\n//"
},
{
"path": "CoreUtil/CoreUtil/Class/Reachability+Publisher.swift",
"chars": 920,
"preview": "//\n// Reachability+Ex.swift\n// CoreUtil\n//\n// Created by yuki on 2021/09/14.\n// Copyright © 2021 yuki. All rights re"
},
{
"path": "CoreUtil/CoreUtil/Class/Reachability.swift",
"chars": 13812,
"preview": "/*\nCopyright (c) 2014, Ashley Mills\nAll rights reserved.\n\nRedistribution and use in source and binary forms, with or wit"
},
{
"path": "CoreUtil/CoreUtil/Class/RestorableData.swift",
"chars": 3318,
"preview": "//\n// RestorableData.swift\n// CoreUtil\n//\n// Created by yuki on 2022/02/03.\n//\n\nimport Cocoa\n\nextension FileManager {"
},
{
"path": "CoreUtil/CoreUtil/Class/RestorableState.swift",
"chars": 2177,
"preview": "//\n// RestorableState.swift\n// CoreUtil\n//\n// Created by yuki on 2022/02/03.\n//\n\nimport Foundation\n\n@propertyWrapper\n"
},
{
"path": "CoreUtil/CoreUtil/Class/Terminal.swift",
"chars": 1811,
"preview": "//\n// Terminal.swift\n// CoreUtil\n//\n// Created by yuki on 2022/02/11.\n//\n\nimport Foundation\n\npublic enum TerminalErro"
},
{
"path": "CoreUtil/CoreUtil/Class/ViewPlaceholder.swift",
"chars": 910,
"preview": "//\n// ViewPlaceholder.swift\n// CoreUtil\n//\n// Created by yuki on 2021/06/03.\n// Copyright © 2021 yuki. All rights re"
},
{
"path": "CoreUtil/CoreUtil/Class/Zip3Sequence.swift",
"chars": 2051,
"preview": "//\n// Zip3Sequence.swift\n// CoreUtil\n//\n// Created by yuki on 2022/01/22.\n// Copyright © 2022 yuki. All rights reser"
},
{
"path": "CoreUtil/CoreUtil/CoreUtil.h",
"chars": 466,
"preview": "//\n// CoreUtil.h\n// CoreUtil\n//\n// Created by yuki on 2022/01/29.\n//\n\n#import <Foundation/Foundation.h>\n#import \"Exce"
},
{
"path": "CoreUtil/CoreUtil/ExceptionHanlder/ExceptionHandler.swift",
"chars": 1446,
"preview": "//\n// ExceptionHandler.swift\n// CoreUtil\n//\n// Created by yuki on 2021/06/26.\n// Copyright © 2021 yuki. All rights r"
},
{
"path": "CoreUtil/CoreUtil/ExceptionHanlder/ExceptionHanlder.h",
"chars": 463,
"preview": "//\n// ExceptionHanlder.h\n// CoreUtil\n//\n// Created by yuki on 2021/06/26.\n// Copyright © 2021 yuki. All rights reser"
},
{
"path": "CoreUtil/CoreUtil/ExceptionHanlder/ExceptionHanlder.m",
"chars": 675,
"preview": "//\n// ExceptionHanlder.m\n// CoreUtil\n//\n// Created by yuki on 2021/06/26.\n// Copyright © 2021 yuki. All rights reser"
},
{
"path": "CoreUtil/CoreUtil/Export.swift",
"chars": 177,
"preview": "//\n// Export.swift\n// CoreUtil\n//\n// Created by yuki on 2022/01/29.\n//\n\n@_exported import Promise\n@_exported import S"
},
{
"path": "CoreUtil/CoreUtil/Extensions/Combine/Combine+ObjectBag.swift",
"chars": 754,
"preview": "//\n// NSObject+Combine.swift\n// CoreUtil\n//\n// Created by yuki on 2020/05/22.\n// Copyright © 2020 yuki. All rights r"
},
{
"path": "CoreUtil/CoreUtil/Extensions/Combine/Combine+Peek.swift",
"chars": 432,
"preview": "//\n// Combine+Peek.swift\n// CoreUtil\n//\n// Created by yuki on 2022/02/01.\n//\n\nimport Combine\n\nextension Publisher {\n "
},
{
"path": "CoreUtil/CoreUtil/Extensions/Combine/NSControl+Combine.swift",
"chars": 1396,
"preview": "//\n// NSButton+Combine.swift\n// CoreUtil\n//\n// Created by yuki on 2021/07/23.\n// Copyright © 2021 yuki. All rights r"
},
{
"path": "CoreUtil/CoreUtil/Extensions/Combine/NSTextField+Combine.swift",
"chars": 2455,
"preview": "//\n// Combine+TextField.swift\n// CoreUtil\n//\n// Created by yuki on 2021/01/03.\n// Copyright © 2021 yuki. All rights "
},
{
"path": "CoreUtil/CoreUtil/Extensions/CoreGraphics/Ex+CGPoint.swift",
"chars": 4204,
"preview": "//\n// Ex+CGPoint.swift\n// Topica\n//\n// Created by yuki on 2019/10/27.\n// Copyright © 2019 yuki. All rights reserved."
},
{
"path": "CoreUtil/CoreUtil/Extensions/CoreGraphics/Ex+CGRect.swift",
"chars": 5197,
"preview": "//\n// Ex+CGRect.swift\n// CoreUtil\n//\n// Created by yuki on 2020/02/03.\n// Copyright © 2020 yuki. All rights reserved"
},
{
"path": "CoreUtil/CoreUtil/Extensions/CoreGraphics/Ex+CGSize.swift",
"chars": 4126,
"preview": "import CoreGraphics\n\n\n@inlinable public func round(_ size: CGSize) -> CGSize {\n CGSize(width: round(size.width), heig"
},
{
"path": "CoreUtil/CoreUtil/Extensions/Swift/Ex+Array.swift",
"chars": 3549,
"preview": "//\n// Extensions.swift\n// DANMAKER\n//\n// Created by yuki on 2015/06/24.\n// Copyright © 2015 yuki. All rights reserve"
},
{
"path": "CoreUtil/CoreUtil/Extensions/Swift/Ex+Clamp.swift",
"chars": 1055,
"preview": "//\n// Ex+Comparable.swift\n// CoreUtil\n//\n// Created by yuki on 2020/04/01.\n// Copyright © 2020 yuki. All rights rese"
},
{
"path": "CoreUtil/CoreUtil/Extensions/Swift/Ex+Localize.swift",
"chars": 213,
"preview": "//\n// Ex+Localize.swift\n// CoreUtil\n//\n// Created by yuki on 2022/02/13.\n//\n\nimport Foundation\n\nextension String {\n "
},
{
"path": "CoreUtil/CoreUtil/Extensions/Swift/Ex+Number.swift",
"chars": 1053,
"preview": "//\n// Ex+NUmber.swift\n// CoreUtil\n//\n// Created by yuki on 2020/06/24.\n// Copyright © 2020 yuki. All rights reserved"
},
{
"path": "CoreUtil/CoreUtil/Extensions/Swift/Ex+OptionSet.swift",
"chars": 292,
"preview": "//\n// Ex+OptionSet.swift\n// CoreUtil\n//\n// Created by yuki on 2020/04/13.\n// Copyright © 2020 yuki. All rights reser"
},
{
"path": "CoreUtil/CoreUtil/Extensions/UI/Ex+CALayer.swift",
"chars": 808,
"preview": "//\n// Ex+CALayer.swift\n// CoreUtil\n//\n// Created by yuki on 2020/06/23.\n// Copyright © 2020 yuki. All rights reserve"
},
{
"path": "CoreUtil/CoreUtil/Extensions/UI/Ex+Image.swift",
"chars": 811,
"preview": "//\n// Ex+Image.swift\n// CoreUtil\n//\n// Created by yuki on 2020/03/10.\n// Copyright © 2020 yuki. All rights reserved."
},
{
"path": "CoreUtil/CoreUtil/Extensions/UI/Ex+NSColor.swift",
"chars": 967,
"preview": "import Cocoa\n\n// MARK: - Extension for Color\nextension NSColor {\n public convenience init(colorSpace: NSColorSpace = "
},
{
"path": "CoreUtil/CoreUtil/Extensions/UI/Ex+NSControl.swift",
"chars": 557,
"preview": "//\n// Ex+NSControl.swift\n// CoreUtil\n//\n// Created by yuki on 2021/10/28.\n// Copyright © 2021 yuki. All rights reser"
},
{
"path": "CoreUtil/CoreUtil/Extensions/UI/Ex+NSEdgeInsets.swift",
"chars": 865,
"preview": "//\n// Ex+NSEdgeInsets.swift\n// CoreUtil\n//\n// Created by yuki on 2022/01/29.\n//\n\nimport Cocoa\n\nextension NSEdgeInsets"
},
{
"path": "CoreUtil/CoreUtil/Extensions/UI/Ex+NSEvent.swift",
"chars": 296,
"preview": "//\n// NSEvent+Location.swift\n// CoreUtil\n//\n// Created by yuki on 2021/11/11.\n// Copyright © 2021 yuki. All rights r"
},
{
"path": "CoreUtil/CoreUtil/Extensions/UI/Ex+NSMenuItem.swift",
"chars": 1676,
"preview": "//\n// Ex+NSMenuItem.swift\n// CoreUtil\n//\n// Created by yuki on 2020/08/20.\n// Copyright © 2020 yuki. All rights rese"
},
{
"path": "CoreUtil/CoreUtil/Extensions/UI/Ex+NSPopover.swift",
"chars": 2079,
"preview": "//\n// Ex+NSPopover.swift\n// CoreUtil\n//\n// Created by yuki on 2021/05/31.\n// Copyright © 2021 yuki. All rights reser"
},
{
"path": "CoreUtil/CoreUtil/Extensions/UI/Ex+NSTableView.swift",
"chars": 1104,
"preview": "//\n// Ex+NSTableView.swift\n// CoreUtil\n//\n// Created by yuki on 2022/01/29.\n//\n\nimport Cocoa\n\nextension NSTableView {"
},
{
"path": "CoreUtil/CoreUtil/Extensions/UI/Ex+UI.swift",
"chars": 264,
"preview": "import Cocoa\n\npublic let NSOutlineViewNotificationItemKey = \"NSObject\"\n\nextension NSView {\n #if DEBUG\n public func"
},
{
"path": "CoreUtil/CoreUtil/HotKey/HotKey.swift",
"chars": 2403,
"preview": "//\n// KeyboardShortcut.swift\n// ListView\n//\n// Created by yuki on 2021/06/28.\n//\n\nimport Carbon\nimport Cocoa\n\npublic "
},
{
"path": "CoreUtil/CoreUtil/HotKey/Key.swift",
"chars": 14023,
"preview": "//\n// Key.swift\n// ListView\n//\n// Created by yuki on 2021/06/28.\n//\n\nimport Carbon\n\npublic enum Key {\n // MARK: - "
},
{
"path": "CoreUtil/CoreUtil/HotKey/NSEvent+HotKey.swift",
"chars": 990,
"preview": "//\n// NSEvent+HotKey.swift\n// ListView\n//\n// Created by yuki on 2021/06/28.\n//\n\nimport Cocoa\n\nextension NSEvent {\n "
},
{
"path": "CoreUtil/CoreUtil/Info.plist",
"chars": 752,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/P"
},
{
"path": "CoreUtil/CoreUtil.xcodeproj/project.pbxproj",
"chars": 37045,
"preview": "// !$*UTF8*$!\n{\n\tarchiveVersion = 1;\n\tclasses = {\n\t};\n\tobjectVersion = 52;\n\tobjects = {\n\n/* Begin PBXBuildFile section *"
},
{
"path": "CoreUtil/CoreUtil.xcodeproj/project.xcworkspace/contents.xcworkspacedata",
"chars": 135,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Workspace\n version = \"1.0\">\n <FileRef\n location = \"self:\">\n </FileRef"
},
{
"path": "CoreUtil/CoreUtil.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist",
"chars": 238,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/P"
},
{
"path": "DevToys/DevToys/App/AppViewController.swift",
"chars": 1151,
"preview": "//\n// ViewController.swift\n// DevToys\n//\n// Created by yuki on 2022/01/29.\n//\n\nimport Cocoa\nimport CoreUtil\n\nfinal cl"
},
{
"path": "DevToys/DevToys/App/AppWindowController.swift",
"chars": 3214,
"preview": "//\n// AppWindowController.swift\n// DevToys\n//\n// Created by yuki on 2022/01/29.\n//\n\nimport CoreUtil\nimport Darwin\nimp"
},
{
"path": "DevToys/DevToys/AppDelegate.swift",
"chars": 254,
"preview": "//\n// AppDelegate.swift\n// DevToys\n//\n// Created by yuki on 2022/01/29.\n//\n\nimport Cocoa\n\n@main\nclass AppDelegate: NS"
},
{
"path": "DevToys/DevToys/Body/BodyViewController.swift",
"chars": 1074,
"preview": "//\n// BodyViewController.swift\n// DevToys\n//\n// Created by yuki on 2022/01/29.\n//\n\nimport CoreUtil\n\nfinal class BodyV"
},
{
"path": "DevToys/DevToys/Body/Coder/Base64DecoderView+.swift",
"chars": 5618,
"preview": "//\n// Base64Decoder.swift\n// DevToys\n//\n// Created by yuki on 2022/01/30.\n//\n\nimport CoreUtil\n\nfinal class Base64Deco"
},
{
"path": "DevToys/DevToys/Body/Coder/HTMLDecoderView+.swift",
"chars": 1899,
"preview": "//\n// HTMLDecoder.swift\n// DevToys\n//\n// Created by yuki on 2022/01/30.\n//\n\nimport CoreUtil\nimport HTMLEntities\n\nfina"
},
{
"path": "DevToys/DevToys/Body/Coder/JWTDecoderView+.swift",
"chars": 4117,
"preview": "//\n// JWTDecoder.swift\n// DevToys\n//\n// Created by yuki on 2022/02/01.\n//\n\nimport CoreUtil\n\nfinal class JWTDecoderVie"
},
{
"path": "DevToys/DevToys/Body/Coder/URLDecoderView+.swift",
"chars": 2253,
"preview": "//\n// URLDecoder.swift\n// DevToys\n//\n// Created by yuki on 2022/01/30.\n//\n\nimport CoreUtil\n\nfinal class URLDecoderVie"
},
{
"path": "DevToys/DevToys/Body/Convert/DateConverterView+.swift",
"chars": 3150,
"preview": "//\n// DateConverter.swift\n// DevToys\n//\n// Created by yuki on 2022/02/04.\n//\n\nimport CoreUtil\n\nfinal class DateConver"
},
{
"path": "DevToys/DevToys/Body/Convert/JSONYamlConverterView+.swift",
"chars": 5100,
"preview": "//\n// JSONYamlConverter+.swift\n// DevToys\n//\n// Created by yuki on 2022/01/30.\n//\n\nimport CoreUtil\nimport Yams\nimport"
},
{
"path": "DevToys/DevToys/Body/Convert/NumberBaseConverterView+.swift",
"chars": 5309,
"preview": "//\n// NumberBaseConverter.swift\n// DevToys\n//\n// Created by yuki on 2022/01/30.\n//\n\nimport CoreUtil\n\nfinal class Numb"
},
{
"path": "DevToys/DevToys/Body/Format/JSONFormatterView+.swift",
"chars": 3059,
"preview": "//\n// JSONFormatter+.swift\n// DevToys\n//\n// Created by yuki on 2022/01/29.\n//\n\nimport CoreUtil\nimport SwiftJSONFormat"
},
{
"path": "DevToys/DevToys/Body/Format/SQLFormatterView+.swift",
"chars": 407,
"preview": "//\n// SQLFormatterView+.swift\n// DevToys\n//\n// Created by yuki on 2022/02/26.\n//\n\nimport CoreUtil\n\nfinal class SQLFor"
},
{
"path": "DevToys/DevToys/Body/Format/XMLFormatterView+.swift",
"chars": 4787,
"preview": "//\n// XMLFormatter.swift\n// DevToys\n//\n// Created by yuki on 2022/02/04.\n//\n\nimport CoreUtil\n\nfinal class XMLFormatte"
},
{
"path": "DevToys/DevToys/Body/Generator/ChecksumGeneratorView+.swift",
"chars": 3929,
"preview": "//\n// ChecksumGenerator.swift\n// DevToys\n//\n// Created by yuki on 2022/02/04.\n//\n\nimport CoreUtil\n\nfinal class Checks"
},
{
"path": "DevToys/DevToys/Body/Generator/HashGeneratorView+.swift",
"chars": 3332,
"preview": "//\n// HashGenerator.swift\n// DevToys\n//\n// Created by yuki on 2022/02/01.\n//\n\nimport CoreUtil\nimport CryptoSwift\n\nfin"
},
{
"path": "DevToys/DevToys/Body/Generator/LoremIpsumGeneratorView+.swift",
"chars": 4008,
"preview": "//\n// LoremIpsumGenerator.swift\n// DevToys\n//\n// Created by yuki on 2022/02/01.\n//\n\nimport CoreUtil\n\nfinal class Lore"
},
{
"path": "DevToys/DevToys/Body/Generator/QRCodeGeneratorView+.swift",
"chars": 4247,
"preview": "//\n// QLCodeGeneratorView+.swift\n// DevToys\n//\n// Created by yuki on 2022/02/23.\n//\n\nimport CoreUtil\nimport CoreImage"
},
{
"path": "DevToys/DevToys/Body/Generator/UUIDGeneratorView+.swift",
"chars": 3469,
"preview": "//\n// UUIDGenerator.swift\n// DevToys\n//\n// Created by yuki on 2022/02/01.\n//\n\nimport CoreUtil\n\nfinal class UUIDGenera"
},
{
"path": "DevToys/DevToys/Body/Graphic/Icon Generator/Generators/AndroidIconGenerator.swift",
"chars": 1887,
"preview": "//\n// AndroidIconGenerator.swift\n// DevToys\n//\n// Created by yuki on 2022/02/27.\n//\n\nimport CoreUtil\n\nenum AndroidIco"
},
{
"path": "DevToys/DevToys/Body/Graphic/Icon Generator/Generators/IOSIconGenerator.swift",
"chars": 10052,
"preview": "//\n// IcnsGenerator.swift\n// DevToys\n//\n// Created by yuki on 2022/02/26.\n//\n\nimport CoreUtil\n\nenum IosIconGenerator "
},
{
"path": "DevToys/DevToys/Body/Graphic/Icon Generator/Generators/IcnsGenerator.swift",
"chars": 1204,
"preview": "//\n// IcnsGenerator.swift\n// DevToys\n//\n// Created by yuki on 2022/02/26.\n//\n\nimport CoreUtil\n\nenum IcnsGenerator {\n "
},
{
"path": "DevToys/DevToys/Body/Graphic/Icon Generator/Generators/IcoGenerator.swift",
"chars": 851,
"preview": "//\n// IcoGenerator.swift\n// DevToys\n//\n// Created by yuki on 2022/02/28.\n//\n\nimport CoreUtil\n\n\nenum IcoGenerator {\n "
},
{
"path": "DevToys/DevToys/Body/Graphic/Icon Generator/Generators/IconFolderGenerator.swift",
"chars": 666,
"preview": "//\n// IconFolderGenerator.swift\n// DevToys\n//\n// Created by yuki on 2022/02/26.\n//\n\nimport CoreUtil\nimport CoreGraphi"
},
{
"path": "DevToys/DevToys/Body/Graphic/Icon Generator/Generators/IconGenerator+Model.swift",
"chars": 285,
"preview": "//\n// IconGenerator+Model.swift\n// DevToys\n//\n// Created by yuki on 2022/02/26.\n//\n\nimport CoreUtil\n\nstruct IconGener"
},
{
"path": "DevToys/DevToys/Body/Graphic/Icon Generator/Generators/IconsetGenerator.swift",
"chars": 767,
"preview": "//\n// IconsetGenerator.swift\n// DevToys\n//\n// Created by yuki on 2022/02/26.\n//\n\nimport CoreUtil\n\nenum IconsetGenerat"
},
{
"path": "DevToys/DevToys/Body/Graphic/Icon Generator/Generators/IosIconGenerator.swift",
"chars": 10052,
"preview": "//\n// IcnsGenerator.swift\n// DevToys\n//\n// Created by yuki on 2022/02/26.\n//\n\nimport CoreUtil\n\nenum IosIconGenerator "
},
{
"path": "DevToys/DevToys/Body/Graphic/Icon Generator/Generators/PngIconGenerator.swift",
"chars": 1093,
"preview": "//\n// PNGGenerator.swift\n// DevToys\n//\n// Created by yuki on 2022/02/28.\n//\n\nimport Foundation\n\nenum PngIconGenerator"
},
{
"path": "DevToys/DevToys/Body/Graphic/Icon Generator/Icon Templete/IconImageManager.swift",
"chars": 943,
"preview": "//\n// IconImageManager.swift\n// DevToys\n//\n// Created by yuki on 2022/02/28.\n//\n\nimport CoreUtil\n\nfinal class IconIma"
},
{
"path": "DevToys/DevToys/Body/Graphic/Icon Generator/Icon Templete/IconSet.swift",
"chars": 3205,
"preview": "//\n// IconSet.swift\n// DevToys\n//\n// Created by yuki on 2022/02/27.\n//\n\nimport CoreUtil\n\n\n\nstruct IconSet {\n enum "
},
{
"path": "DevToys/DevToys/Body/Graphic/Icon Generator/Icon Templete/IconTemplete+.swift",
"chars": 10219,
"preview": "//\n// FolderFillIconImage.swift\n// DevToys\n//\n// Created by yuki on 2022/02/27.\n//\n\nimport CoreUtil\nimport CoreGraphi"
},
{
"path": "DevToys/DevToys/Body/Graphic/Icon Generator/Icon Templete/IconTemplete.swift",
"chars": 403,
"preview": "//\n// IconImageManager+.swift\n// DevToys\n//\n// Created by yuki on 2022/02/27.\n//\n\nimport CoreUtil\n\nprotocol IconTempl"
},
{
"path": "DevToys/DevToys/Body/Graphic/Icon Generator/IconGeneratorView+.swift",
"chars": 10231,
"preview": "//\n// IconGeneratorView+.swift\n// DevToys\n//\n// Created by yuki on 2022/02/26.\n//\n\nimport CoreUtil\n\nfinal class IconG"
},
{
"path": "DevToys/DevToys/Body/Graphic/Image Converter/Exporters/DefaultImageExporter.swift",
"chars": 1953,
"preview": "//\n// DefaultImageExporter.swift\n// DevToys\n//\n// Created by yuki on 2022/02/18.\n//\n\nimport CoreUtil\n\nenum ImageExpor"
},
{
"path": "DevToys/DevToys/Body/Graphic/Image Converter/Exporters/HeicImageExporter.swift",
"chars": 891,
"preview": "//\n// HeicConverter.swift\n// DevToys\n//\n// Created by yuki on 2022/02/18.\n//\n\nimport AVFoundation\nimport CoreUtil\n\nen"
},
{
"path": "DevToys/DevToys/Body/Graphic/Image Converter/Exporters/WebpImageExporter.swift",
"chars": 1046,
"preview": "//\n// WebpExporter.swift\n// DevToys\n//\n// Created by yuki on 2022/02/18.\n//\n\nimport CoreUtil\n\nenum WebpExportError: E"
},
{
"path": "DevToys/DevToys/Body/Graphic/Image Converter/ImageConverter.swift",
"chars": 5956,
"preview": "//\n// ImageConverter.swift\n// DevToys\n//\n// Created by yuki on 2022/02/04.\n//\n\nimport CoreUtil\n\nstruct ImageConvertTa"
},
{
"path": "DevToys/DevToys/Body/Graphic/Image Converter/ImageConverterView+.swift",
"chars": 9750,
"preview": "//\n// ImageConverter.swift\n// DevToys\n//\n// Created by yuki on 2022/02/04.\n//\n\nimport CoreUtil\n\nfinal class ImageConv"
},
{
"path": "DevToys/DevToys/Body/Graphic/Image Optimizer/ImageOptimaizerView.swift",
"chars": 7951,
"preview": "//\n// Image Optimizer.swift\n// DevToys\n//\n// Created by yuki on 2022/02/01.\n//\n\nimport CoreUtil\n\nfinal class ImageOpt"
},
{
"path": "DevToys/DevToys/Body/Graphic/Image Optimizer/ImageOptimizer.swift",
"chars": 5356,
"preview": "//\n// ImageOptimizer.swift\n// DevToys\n//\n// Created by yuki on 2022/02/02.\n//\n\nimport CoreUtil\n\nstruct ImageOptimizeT"
},
{
"path": "DevToys/DevToys/Body/Graphic/PDFGeneratorView+.swift",
"chars": 10550,
"preview": "//\n// PDFGenerator.swift\n// DevToys\n//\n// Created by yuki on 2022/02/02.\n//\n\nimport CoreUtil\n\nfinal class PDFGenerato"
},
{
"path": "DevToys/DevToys/Body/Graphic/QRCodeReaderView+.swift",
"chars": 7251,
"preview": "//\n// QRCodeReaderView+.swift\n// DevToys\n//\n// Created by yuki on 2022/02/28.\n//\n\nimport CoreUtil\nimport AVFoundation"
},
{
"path": "DevToys/DevToys/Body/HomeView+.swift",
"chars": 7142,
"preview": "//\n// HomeViewController+.swift\n// DevToys\n//\n// Created by yuki on 2022/01/29.\n//\n\nimport CoreUtil\n\nclass SearchView"
},
{
"path": "DevToys/DevToys/Body/Media/Audio Converter/AudioConverter.swift",
"chars": 1399,
"preview": "//\n// AudioConverter.swift\n// DevToys\n//\n// Created by yuki on 2022/02/21.\n//\n\nimport CoreUtil\n\nstruct AudioConvertOp"
},
{
"path": "DevToys/DevToys/Body/Media/Audio Converter/AudioConverterView+.swift",
"chars": 13304,
"preview": "//\n// AudioConverter.swift\n// DevToys\n//\n// Created by yuki on 2022/02/21.\n//\n\nimport CoreUtil\nimport Quartz\n\nfinal c"
},
{
"path": "DevToys/DevToys/Body/Media/Audio Converter/AudioFileScanner.swift",
"chars": 1256,
"preview": "//\n// FileTreeScanner.swift\n// DevToys\n//\n// Created by yuki on 2022/02/22.\n//\n\nimport CoreUtil\n\nenum AudioFileScanne"
},
{
"path": "DevToys/DevToys/Body/Media/Color Picker/Color.swift",
"chars": 5873,
"preview": "//\n// Color.swift\n// DevToys\n//\n// Created by yuki on 2022/02/19.\n//\n\nimport CoreUtil\n\nstruct Color: Codable {\n va"
},
{
"path": "DevToys/DevToys/Body/Media/Color Picker/ColorPickerView+.swift",
"chars": 14043,
"preview": "//\n// ColorPickerView+.swift\n// DevToys\n//\n// Created by yuki on 2022/02/19.\n//\n\nimport CoreUtil\n\n\nfinal class ColorP"
},
{
"path": "DevToys/DevToys/Body/Media/Color Picker/Components/BoxHSBColorPicker.swift",
"chars": 1153,
"preview": "//\n// BoxColorPicker.swift\n// DevToys\n//\n// Created by yuki on 2022/02/19.\n//\n\nimport CoreUtil\n\nfinal class BoxHSBCol"
},
{
"path": "DevToys/DevToys/Body/Media/Color Picker/Components/BrightnessBarView.swift",
"chars": 1874,
"preview": "//\n// BrightnessBarView.swift\n// DevToys\n//\n// Created by yuki on 2022/02/19.\n//\n\nimport CoreUtil\n\nfinal class Bright"
},
{
"path": "DevToys/DevToys/Body/Media/Color Picker/Components/CircleBarsHSBColorPicker.swift",
"chars": 1432,
"preview": "//\n// CircleBarsHSBColorPicker.swift\n// DevToys\n//\n// Created by yuki on 2022/02/19.\n//\n\nimport CoreUtil\n\n\nfinal clas"
},
{
"path": "DevToys/DevToys/Body/Media/Color Picker/Components/CircleBoxHSBColorPicker.swift",
"chars": 1206,
"preview": "//\n// CircleColorPicker.swift\n// DevToys\n//\n// Created by yuki on 2022/02/19.\n//\n\nimport CoreUtil\n\nfinal class Circle"
},
{
"path": "DevToys/DevToys/Body/Media/Color Picker/Components/CircleHueBarView.swift",
"chars": 2827,
"preview": "//\n// CircleHueBarView.swift\n// DevToys\n//\n// Created by yuki on 2022/02/19.\n//\n\nimport CoreUtil\n\n\nfinal class Circle"
},
{
"path": "DevToys/DevToys/Body/Media/Color Picker/Components/ColorBoxView.swift",
"chars": 2361,
"preview": "//\n// ColorBoxView.swift\n// DevToys\n//\n// Created by yuki on 2022/02/19.\n//\n\nimport CoreUtil\n\nfinal class ColorBoxVie"
},
{
"path": "DevToys/DevToys/Body/Media/Color Picker/Components/ColorPickerHandleLayer.swift",
"chars": 1033,
"preview": "//\n// ColorPickerHandleLayer.swift\n// DevToys\n//\n// Created by yuki on 2022/02/19.\n//\n\nimport CoreUtil\n\nprivate let h"
},
{
"path": "DevToys/DevToys/Body/Media/Color Picker/Components/ColorSampleView.swift",
"chars": 949,
"preview": "//\n// ColorSampleView.swift\n// DevToys\n//\n// Created by yuki on 2022/02/19.\n//\n\nimport CoreUtil\n\nfinal class ColorSam"
},
{
"path": "DevToys/DevToys/Body/Media/Color Picker/Components/HueBarView.swift",
"chars": 1724,
"preview": "//\n// HueBarView.swift\n// DevToys\n//\n// Created by yuki on 2022/02/19.\n//\n\nimport CoreUtil\n\nfinal class HueBarView: N"
},
{
"path": "DevToys/DevToys/Body/Media/Color Picker/Components/OpacityBarView.swift",
"chars": 1724,
"preview": "//\n// OpacityBarView.swift\n// DevToys\n//\n// Created by yuki on 2022/02/19.\n//\n\nimport CoreUtil\n\nfinal class OpacityBa"
},
{
"path": "DevToys/DevToys/Body/Media/Color Picker/Components/SaturationBarView.swift",
"chars": 1876,
"preview": "//\n// SaturationBarView.swift\n// DevToys\n//\n// Created by yuki on 2022/02/19.\n//\n\nimport CoreUtil\n\nfinal class Satura"
},
{
"path": "DevToys/DevToys/Body/Media/Color Picker/Pixel Picker/ACOverlayController.swift",
"chars": 8834,
"preview": "//\n// PPOverlayController.swift\n// Pixel Picker\n//\n\nimport Cocoa\nimport Carbon.HIToolbox\n\nprivate let magnification = "
},
{
"path": "DevToys/DevToys/Body/Media/Color Picker/Pixel Picker/ACOverlayController.xib",
"chars": 5744,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<document type=\"com.apple.InterfaceBuilder3.Cocoa.XIB\" version=\"3.0\" toolsVersion"
},
{
"path": "DevToys/DevToys/Body/Media/Color Picker/Pixel Picker/ACOverlayPanel.swift",
"chars": 999,
"preview": "//\n// ACOverlayPanel.swift\n// PixelPicker\n//\n// Created by yuki on 2020/06/30.\n// Copyright © 2020 yuki. All rights "
},
{
"path": "DevToys/DevToys/Body/Media/Color Picker/Pixel Picker/ACOverlayPreview.swift",
"chars": 2455,
"preview": "//\n// ACOverlayPreview.swift\n// PixelPicker\n//\n// Created by yuki on 2020/06/30.\n// Copyright © 2020 yuki. All right"
},
{
"path": "DevToys/DevToys/Body/Media/Color Picker/Pixel Picker/ACOverlayWrapper.swift",
"chars": 467,
"preview": "//\n// ACOverlayWrapper.swift\n// PixelPicker\n//\n// Created by yuki on 2020/06/30.\n// Copyright © 2020 yuki. All right"
},
{
"path": "DevToys/DevToys/Body/Media/Color Picker/Pixel Picker/ACPixelPicker.swift",
"chars": 985,
"preview": "//\n// ACPixelPicker.swift\n// AxComponents\n//\n// Created by yuki on 2020/06/30.\n// Copyright © 2020 yuki. All rights "
},
{
"path": "DevToys/DevToys/Body/Media/Color Picker/Pixel Picker/Utils/Ex+CGImage.swift",
"chars": 2141,
"preview": "//\n// CGImage.swift\n// Pixel Picker\n//\n\nimport Cocoa\n\nextension CGImage {\n func colorAt(x: Int, y: Int) -> NSColor "
},
{
"path": "DevToys/DevToys/Body/Media/Color Picker/Pixel Picker/Utils/Ex+NSBezierPath.swift",
"chars": 663,
"preview": "//\n// NSBezierPath.swift\n// Pixel Picker\n//\n\nimport Cocoa\n\nextension NSBezierPath {\n var cgPath: CGPath {\n l"
},
{
"path": "DevToys/DevToys/Body/Media/Color Picker/Pixel Picker/Utils/Ex+NSColor.swift",
"chars": 764,
"preview": "//\n// NSColor.swift\n// Pixel Picker\n//\n\nimport Cocoa\n\nextension NSColor {\n func image(withSize size: NSSize) -> NSI"
},
{
"path": "DevToys/DevToys/Body/Media/Color Picker/Pixel Picker/Utils/ShowAndHideCursor.h",
"chars": 226,
"preview": "//\n// ShowAndHideCursor.h\n// Pixel Picker\n//\n\n#ifndef ShowAndHideCursor_h\n#define ShowAndHideCursor_h\n\n#import <Founda"
},
{
"path": "DevToys/DevToys/Body/Media/Color Picker/Pixel Picker/Utils/ShowAndHideCursor.m",
"chars": 229,
"preview": "//\n// ShowAndHideCursor.m\n// Pixel Picker\n//\n\n#include \"ShowAndHideCursor.h\"\n\n// Unfortunately `kCGDirectMainDisplay` "
},
{
"path": "DevToys/DevToys/Body/Media/Color Picker/Pixel Picker/Utils/ShowAndHideCursor.swift",
"chars": 2361,
"preview": "//\n// ShowAndHideCursor.swift\n// Pixel Picker\n//\n\nimport Foundation\nimport ApplicationServices\n\ntypealias notAPrivateA"
},
{
"path": "DevToys/DevToys/Body/Media/Color Picker/Pixel Picker/Utils/Util+PixelPicker.swift",
"chars": 2439,
"preview": "//\n// Util.swift\n// Pixel Picker\n//\n\nimport Cocoa\n\nlet APP_NAME = Bundle.main.infoDictionary![kCFBundleNameKey as Stri"
},
{
"path": "DevToys/DevToys/Body/Media/Color Picker/R+ColorPicker.swift",
"chars": 217,
"preview": "//\n// R+ColorPicker.swift\n// DevToys\n//\n// Created by yuki on 2022/02/19.\n//\n\nextension R {\n enum ColorPicker {\n//"
},
{
"path": "DevToys/DevToys/Body/Media/Movie to Gif/GifConverter.swift",
"chars": 1713,
"preview": "//\n// GifConverter.swift\n// DevToys\n//\n// Created by yuki on 2022/02/20.\n//\n\nimport CoreUtil\nimport CoreGraphics\n\nstr"
},
{
"path": "DevToys/DevToys/Body/Media/Movie to Gif/GifConverterView+.swift",
"chars": 10424,
"preview": "//\n// MovieToGifView.swift\n// DevToys\n//\n// Created by yuki on 2022/02/20.\n//\n\nimport CoreUtil\nimport CoreGraphics\nim"
},
{
"path": "DevToys/DevToys/Body/SettingView+.swift",
"chars": 1143,
"preview": "//\n// SettingView+.swift\n// DevToys\n//\n// Created by yuki on 2022/02/16.\n//\n\nimport CoreUtil\n\nfinal class SettingView"
},
{
"path": "DevToys/DevToys/Body/Text/HyphenationRemoverView+.swift",
"chars": 1821,
"preview": "import CoreUtil\n\nfinal class HyphenationRemoverViewController: NSViewController {\n @RestorableState(\"hyphenation.rawC"
},
{
"path": "DevToys/DevToys/Body/Text/JSON Search/JSONNormalSearchView.swift",
"chars": 261,
"preview": "//\n// JSONNormalSearchView.swift\n// DevToys\n//\n// Created by yuki on 2022/02/25.\n//\n\nimport CoreUtil\n\nfinal class JSO"
},
{
"path": "DevToys/DevToys/Body/Text/JSON Search/JSONSearchView+.swift",
"chars": 824,
"preview": "//\n// JSONSearchView.swift\n// DevToys\n//\n// Created by yuki on 2022/02/25.\n//\n\nimport CoreUtil\n\nfinal class JSONSearc"
},
{
"path": "DevToys/DevToys/Body/Text/RegexTesterView+.swift",
"chars": 2975,
"preview": "//\n// RegexTesterView+.swift\n// DevToys\n//\n// Created by yuki on 2022/02/03.\n//\n\nimport CoreUtil\n\nfinal class RegexTe"
},
{
"path": "DevToys/DevToys/Body/Text/TextDiffView+.swift",
"chars": 4622,
"preview": "//\n// TextDiffView+.swift\n// DevToys\n//\n// Created by yuki on 2022/02/23.\n//\n\nimport DiffMatchPatch\nimport CoreUtil\n\n"
},
{
"path": "DevToys/DevToys/Body/Text/TextInspectorView+.swift",
"chars": 5571,
"preview": "//\n// TextInspector.swift\n// DevToys\n//\n// Created by yuki on 2022/02/01.\n//\n\nimport CoreUtil\n\nfinal class TextInspec"
},
{
"path": "DevToys/DevToys/Body/Utils/CameraViewController.swift",
"chars": 2229,
"preview": "//\n// ViewController.swift\n// macOS Camera\n//\n// Created by Mihail Șalari. on 4/24/17.\n// Copyright © 2017 Mihail Șa"
},
{
"path": "DevToys/DevToys/Body/Utils/FileConflictAvoider.swift",
"chars": 1312,
"preview": "//\n// FileConflictAvoider.swift\n// DevToys\n//\n// Created by yuki on 2022/02/22.\n//\n\nimport CoreUtil\n\nenum FileConflic"
},
{
"path": "DevToys/DevToys/Body/Utils/Identifier.swift",
"chars": 1522,
"preview": "//\n// Identifier.swift\n// CoreUtil\n//\n// Created by yuki on 2021/04/29.\n// Copyright © 2021 yuki. All rights reserve"
},
{
"path": "DevToys/DevToys/Body/Utils/ImageDropper.swift",
"chars": 965,
"preview": "//\n// ImageDropper.swift\n// DevToys\n//\n// Created by yuki on 2022/02/04.\n//\n\nimport Cocoa\n\nenum ImageDropper {\n st"
},
{
"path": "DevToys/DevToys/Body/Utils/Slugify.swift",
"chars": 8373,
"preview": "//\n// Slugify.swift\n// DevToys\n//\n// Created by yuki on 2022/02/26.\n//\n\nimport Foundation\n\nextension String {\n pub"
},
{
"path": "DevToys/DevToys/Body/Utils/ffmpeg/FFMpegExecutor.swift",
"chars": 3213,
"preview": "//\n// FFMpegExecutor.swift\n// DevToys\n//\n// Created by yuki on 2022/02/20.\n//\n\nimport CoreUtil\n\nenum FFExecutor {\n "
},
{
"path": "DevToys/DevToys/Body/Utils/ffmpeg/FFProgressReport.swift",
"chars": 1540,
"preview": "//\n// FFProgressReport.swift\n// DevToys\n//\n// Created by yuki on 2022/02/20.\n//\n\nimport CoreUtil\n\nstruct FFProgressRe"
},
{
"path": "DevToys/DevToys/Body/Utils/ffmpeg/FFTask.swift",
"chars": 696,
"preview": "//\n// FFTask.swift\n// DevToys\n//\n// Created by yuki on 2022/02/21.\n//\n\nimport CoreUtil\n\nfinal class FFTask {\n let "
},
{
"path": "DevToys/DevToys/Body/Utils/ffmpeg/FFThumnailGenerator.swift",
"chars": 998,
"preview": "//\n// FFThumnailGenerator.swift\n// DevToys\n//\n// Created by yuki on 2022/02/21.\n//\n\nimport CoreUtil\n\nenum FFThumnailG"
},
{
"path": "DevToys/DevToys/Body/Utils/ffmpeg/FFTime.swift",
"chars": 982,
"preview": "//\n// FFTime.swift\n// DevToys\n//\n// Created by yuki on 2022/02/20.\n//\n\nimport Foundation\n\nstruct FFTime: CustomString"
},
{
"path": "DevToys/DevToys/Bridging-Header.h",
"chars": 194,
"preview": "//\n// Bridging-Header.h\n// DevToys\n//\n// Created by yuki on 2022/02/19.\n//\n\n#ifndef Bridging_Header_h\n#define Bridgin"
},
{
"path": "DevToys/DevToys/Component/Area.swift",
"chars": 3504,
"preview": "//\n// ComponentBaseView.swift\n// DevToys\n//\n// Created by yuki on 2022/01/29.\n//\n\nimport CoreUtil\n\nfinal class Area: "
},
{
"path": "DevToys/DevToys/Component/Button.swift",
"chars": 1001,
"preview": "//\n// Button.swift\n// DevToys\n//\n// Created by yuki on 2022/02/01.\n//\n\nimport CoreUtil\n\nfinal class Button: NSLoadBut"
},
{
"path": "DevToys/DevToys/Component/CodeTextView.swift",
"chars": 14857,
"preview": "//\n// CodeTextView.swift\n// DevToys\n//\n// Created by yuki on 2022/01/29.\n//\n\nimport CoreUtil\nimport Highlightr\nimport"
},
{
"path": "DevToys/DevToys/Component/ControlBackgroundLayer.swift",
"chars": 1339,
"preview": "//\n// ControlBackgroundLayer.swift\n// DevToys\n//\n// Created by yuki on 2022/01/29.\n//\n\nimport CoreUtil\n\nfinal class C"
},
{
"path": "DevToys/DevToys/Component/ControlContainer.swift",
"chars": 3005,
"preview": "//\n// ComponentBaseView.swift\n// DevToys\n//\n// Created by yuki on 2022/01/29.\n//\n\nimport CoreUtil\n\nfinal class Contro"
},
{
"path": "DevToys/DevToys/Component/DatePicker.swift",
"chars": 1248,
"preview": "//\n// DatePicker.swift\n// DevToys\n//\n// Created by yuki on 2022/02/04.\n//\n\nimport CoreUtil\n\nfinal class DatePicker: N"
},
{
"path": "DevToys/DevToys/Component/DragImageView.swift",
"chars": 2642,
"preview": "//\n// ImageBoxView.swift\n// DevToys\n//\n// Created by yuki on 2022/02/25.\n//\n\nimport CoreUtil\nimport AppKit\n\nprotocol "
},
{
"path": "DevToys/DevToys/Component/EmptyImageTableView.swift",
"chars": 2082,
"preview": "//\n// EmptyImageTableView.swift\n// DevToys\n//\n// Created by yuki on 2022/02/22.\n//\n\nimport CoreUtil\n\nopen class Empty"
},
{
"path": "DevToys/DevToys/Component/FileDrop.swift",
"chars": 2182,
"preview": "//\n// FileDrop.swift\n// DevToys\n//\n// Created by yuki on 2022/02/02.\n//\n\nimport CoreUtil\n\nfinal class FileDropSection"
},
{
"path": "DevToys/DevToys/Component/ImageDropView.swift",
"chars": 1825,
"preview": "//\n// ImageDropView.swift\n// DevToys\n//\n// Created by yuki on 2022/02/28.\n//\n\nimport CoreUtil\n\nclass ImageDropView: N"
},
{
"path": "DevToys/DevToys/Component/NumberField.swift",
"chars": 6832,
"preview": "//\n// NumberField.swift\n// DevToys\n//\n// Created by yuki on 2022/02/01.\n//\n\nimport CoreUtil\nimport CoreGraphics\n\nfina"
},
{
"path": "DevToys/DevToys/Component/Page.swift",
"chars": 1813,
"preview": "//\n// ToolPage.swift\n// DevToys\n//\n// Created by yuki on 2022/01/30.\n//\n\nimport CoreUtil\n \nclass Page: NSLoadView { \n"
},
{
"path": "DevToys/DevToys/Component/PopupButton.swift",
"chars": 2707,
"preview": "//\n// PopupButton.swift\n// DevToys\n//\n// Created by yuki on 2022/01/29.\n//\n\nimport CoreUtil\n\nprotocol TextItem: CaseI"
},
{
"path": "DevToys/DevToys/Component/RegexTextView.swift",
"chars": 2009,
"preview": "//\n// RegexTextView.swift\n// DevToys\n//\n// Created by yuki on 2022/02/03.\n//\n\nimport CoreUtil\n\nfinal class RegexTextV"
},
{
"path": "DevToys/DevToys/Component/Section.swift",
"chars": 2766,
"preview": "//\n// ControlStack.swift\n// DevToys\n//\n// Created by yuki on 2022/01/29.\n//\n\nimport CoreUtil\n\nclass Section: NSLoadVi"
},
{
"path": "DevToys/DevToys/Component/SectionButton+.swift",
"chars": 3073,
"preview": "//\n// SectionButton+.swift\n// DevToys\n//\n// Created by yuki on 2022/01/30.\n//\n\nimport CoreUtil\n\nfinal class SearchSec"
},
{
"path": "DevToys/DevToys/Component/SectionButton.swift",
"chars": 2509,
"preview": "//\n// ControlStackButton.swift\n// DevToys\n//\n// Created by yuki on 2022/01/29.\n//\n\nimport CoreUtil\n\nclass SectionButt"
},
{
"path": "DevToys/DevToys/Component/TagCloudView.swift",
"chars": 5978,
"preview": "//\n// TagCloudView.swift\n// DevToys\n//\n// Created by yuki on 2022/02/01.\n//\n\nimport CoreUtil\n\n\nfinal class TagCloudVi"
},
{
"path": "DevToys/DevToys/Component/TextField.swift",
"chars": 3818,
"preview": "//\n// TextField.swift\n// DevToys\n//\n// Created by yuki on 2022/01/30.\n//\n\nimport CoreUtil\n\nfinal class TextField: NSL"
},
{
"path": "DevToys/DevToys/Component/TextFieldSection.swift",
"chars": 1196,
"preview": "//\n// TextFieldSection.swift\n// DevToys\n//\n// Created by yuki on 2022/02/01.\n//\n\nimport CoreUtil\n\nstruct TextFieldSec"
},
{
"path": "DevToys/DevToys/Component/TextView.swift",
"chars": 2262,
"preview": "//\n// TextView.swift\n// DevToys\n//\n// Created by yuki on 2022/02/03.\n//\n\nimport CoreUtil\n\nfinal class TextView: NSLoa"
},
{
"path": "DevToys/DevToys/Component/TextViewSection.swift",
"chars": 3760,
"preview": "//\n// TextViewSection.swift\n// DevToys\n//\n// Created by yuki on 2022/02/01.\n//\n\nimport CoreUtil\n\nstruct TextSectionOp"
},
{
"path": "DevToys/DevToys/Component/Toast.swift",
"chars": 10267,
"preview": "//\n// ACToast.swift\n// AxComponents\n//\n// Created by yuki on 2021/09/13.\n// Copyright © 2021 yuki. All rights reserv"
},
{
"path": "DevToys/DevToys/DevToys.entitlements",
"chars": 301,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/P"
},
{
"path": "DevToys/DevToys/Info.plist",
"chars": 1350,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/P"
},
{
"path": "DevToys/DevToys/Model/AppModel.swift",
"chars": 573,
"preview": "//\n// AppModel.swift\n// DevToys\n//\n// Created by yuki on 2022/01/29.\n//\n\nimport CoreUtil\n\nextension NSViewController "
},
{
"path": "DevToys/DevToys/Model/Settings.swift",
"chars": 383,
"preview": "//\n// Settings.swift\n// DevToys\n//\n// Created by yuki on 2022/02/16.\n//\n\nimport CoreUtil\n\nfinal class Settings {\n "
},
{
"path": "DevToys/DevToys/Model/Tool+Default.swift",
"chars": 12331,
"preview": "//\n// Tool+Default.swift\n// DevToys\n//\n// Created by yuki on 2022/02/13.\n//\n\nimport CoreUtil\n\nextension Tool {\n st"
},
{
"path": "DevToys/DevToys/Model/ToolCategory+Default.swift",
"chars": 1289,
"preview": "//\n// ToolCategory+Default.swift\n// DevToys\n//\n// Created by yuki on 2022/02/13.\n//\n\nextension ToolCategory {\n sta"
},
{
"path": "DevToys/DevToys/Model/ToolManager+.swift",
"chars": 3389,
"preview": "//\n// ToolManager.swift\n// DevToys\n//\n// Created by yuki on 2022/02/12.\n//\n\nimport CoreUtil\nimport OrderedCollections"
},
{
"path": "DevToys/DevToys/Resource/Assets.xcassets/AccentColor.colorset/Contents.json",
"chars": 123,
"preview": "{\n \"colors\" : [\n {\n \"idiom\" : \"universal\"\n }\n ],\n \"info\" : {\n \"author\" : \"xcode\",\n \"version\" : 1\n }"
},
{
"path": "DevToys/DevToys/Resource/Assets.xcassets/AppIcon.appiconset/Contents.json",
"chars": 1301,
"preview": "{\n \"images\" : [\n {\n \"filename\" : \"icon_16x16.png\",\n \"idiom\" : \"mac\",\n \"scale\" : \"1x\",\n \"size\" : "
},
{
"path": "DevToys/DevToys/Resource/Assets.xcassets/Contents.json",
"chars": 63,
"preview": "{\n \"info\" : {\n \"author\" : \"xcode\",\n \"version\" : 1\n }\n}\n"
},
{
"path": "DevToys/DevToys/Resource/Assets.xcassets/applewatch.imageset/Contents.json",
"chars": 377,
"preview": "{\n \"images\" : [\n {\n \"filename\" : \"applewatch.pdf\",\n \"idiom\" : \"universal\",\n \"scale\" : \"1x\"\n },\n "
},
{
"path": "DevToys/DevToys/Resource/Assets.xcassets/carplay.imageset/Contents.json",
"chars": 374,
"preview": "{\n \"images\" : [\n {\n \"filename\" : \"carplay.pdf\",\n \"idiom\" : \"universal\",\n \"scale\" : \"1x\"\n },\n {\n"
},
{
"path": "DevToys/DevToys/Resource/Assets.xcassets/check.imageset/Contents.json",
"chars": 314,
"preview": "{\n \"images\" : [\n {\n \"filename\" : \"Artboard Copy 22.pdf\",\n \"idiom\" : \"universal\",\n \"scale\" : \"1x\"\n "
},
{
"path": "DevToys/DevToys/Resource/Assets.xcassets/clear.imageset/Contents.json",
"chars": 372,
"preview": "{\n \"images\" : [\n {\n \"filename\" : \"clear.pdf\",\n \"idiom\" : \"universal\",\n \"scale\" : \"1x\"\n },\n {\n "
},
{
"path": "DevToys/DevToys/Resource/Assets.xcassets/convert.imageset/Contents.json",
"chars": 374,
"preview": "{\n \"images\" : [\n {\n \"filename\" : \"convert.pdf\",\n \"idiom\" : \"universal\",\n \"scale\" : \"1x\"\n },\n {\n"
},
{
"path": "DevToys/DevToys/Resource/Assets.xcassets/copy.imageset/Contents.json",
"chars": 371,
"preview": "{\n \"images\" : [\n {\n \"filename\" : \"copy.pdf\",\n \"idiom\" : \"universal\",\n \"scale\" : \"1x\"\n },\n {\n "
},
{
"path": "DevToys/DevToys/Resource/Assets.xcassets/drop.imageset/Contents.json",
"chars": 371,
"preview": "{\n \"images\" : [\n {\n \"filename\" : \"drop.pdf\",\n \"idiom\" : \"universal\",\n \"scale\" : \"1x\"\n },\n {\n "
},
{
"path": "DevToys/DevToys/Resource/Assets.xcassets/error.imageset/Contents.json",
"chars": 314,
"preview": "{\n \"images\" : [\n {\n \"filename\" : \"Artboard Copy 23.pdf\",\n \"idiom\" : \"universal\",\n \"scale\" : \"1x\"\n "
},
{
"path": "DevToys/DevToys/Resource/Assets.xcassets/export.imageset/Contents.json",
"chars": 373,
"preview": "{\n \"images\" : [\n {\n \"filename\" : \"export.pdf\",\n \"idiom\" : \"universal\",\n \"scale\" : \"1x\"\n },\n {\n "
},
{
"path": "DevToys/DevToys/Resource/Assets.xcassets/format.imageset/Contents.json",
"chars": 373,
"preview": "{\n \"images\" : [\n {\n \"filename\" : \"format.pdf\",\n \"idiom\" : \"universal\",\n \"scale\" : \"1x\"\n },\n {\n "
},
{
"path": "DevToys/DevToys/Resource/Assets.xcassets/hyphen.imageset/Contents.json",
"chars": 373,
"preview": "{\n \"images\" : [\n {\n \"filename\" : \"hyphen.pdf\",\n \"idiom\" : \"universal\",\n \"scale\" : \"1x\"\n },\n {\n "
},
{
"path": "DevToys/DevToys/Resource/Assets.xcassets/ipad.imageset/Contents.json",
"chars": 371,
"preview": "{\n \"images\" : [\n {\n \"filename\" : \"ipad.pdf\",\n \"idiom\" : \"universal\",\n \"scale\" : \"1x\"\n },\n {\n "
},
{
"path": "DevToys/DevToys/Resource/Assets.xcassets/ipaddress.imageset/Contents.json",
"chars": 376,
"preview": "{\n \"images\" : [\n {\n \"filename\" : \"ipaddress.pdf\",\n \"idiom\" : \"universal\",\n \"scale\" : \"1x\"\n },\n "
},
{
"path": "DevToys/DevToys/Resource/Assets.xcassets/iphone.imageset/Contents.json",
"chars": 373,
"preview": "{\n \"images\" : [\n {\n \"filename\" : \"iphone.pdf\",\n \"idiom\" : \"universal\",\n \"scale\" : \"1x\"\n },\n {\n "
},
{
"path": "DevToys/DevToys/Resource/Assets.xcassets/mac.imageset/Contents.json",
"chars": 370,
"preview": "{\n \"images\" : [\n {\n \"filename\" : \"mac.pdf\",\n \"idiom\" : \"universal\",\n \"scale\" : \"1x\"\n },\n {\n "
},
{
"path": "DevToys/DevToys/Resource/Assets.xcassets/network.status.imageset/Contents.json",
"chars": 381,
"preview": "{\n \"images\" : [\n {\n \"filename\" : \"network.status.pdf\",\n \"idiom\" : \"universal\",\n \"scale\" : \"1x\"\n },"
},
{
"path": "DevToys/DevToys/Resource/Assets.xcassets/number.imageset/Contents.json",
"chars": 378,
"preview": "{\n \"images\" : [\n {\n \"filename\" : \"text copy 5.pdf\",\n \"idiom\" : \"universal\",\n \"scale\" : \"1x\"\n },\n "
},
{
"path": "DevToys/DevToys/Resource/Assets.xcassets/open.imageset/Contents.json",
"chars": 371,
"preview": "{\n \"images\" : [\n {\n \"filename\" : \"open.pdf\",\n \"idiom\" : \"universal\",\n \"scale\" : \"1x\"\n },\n {\n "
},
{
"path": "DevToys/DevToys/Resource/Assets.xcassets/paramators.imageset/Contents.json",
"chars": 377,
"preview": "{\n \"images\" : [\n {\n \"filename\" : \"paramators.pdf\",\n \"idiom\" : \"universal\",\n \"scale\" : \"1x\"\n },\n "
},
{
"path": "DevToys/DevToys/Resource/Assets.xcassets/paste.imageset/Contents.json",
"chars": 372,
"preview": "{\n \"images\" : [\n {\n \"filename\" : \"paste.pdf\",\n \"idiom\" : \"universal\",\n \"scale\" : \"1x\"\n },\n {\n "
},
{
"path": "DevToys/DevToys/Resource/Assets.xcassets/pulldown.indicator.imageset/Contents.json",
"chars": 379,
"preview": "{\n \"images\" : [\n {\n \"filename\" : \"text copy 26.pdf\",\n \"idiom\" : \"universal\",\n \"scale\" : \"1x\"\n },\n "
},
{
"path": "DevToys/DevToys/Resource/Assets.xcassets/search.imageset/Contents.json",
"chars": 379,
"preview": "{\n \"images\" : [\n {\n \"filename\" : \"text copy 25.pdf\",\n \"idiom\" : \"universal\",\n \"scale\" : \"1x\"\n },\n "
},
{
"path": "DevToys/DevToys/Resource/Assets.xcassets/settings.imageset/Contents.json",
"chars": 375,
"preview": "{\n \"images\" : [\n {\n \"filename\" : \"settings.pdf\",\n \"idiom\" : \"universal\",\n \"scale\" : \"1x\"\n },\n {"
}
]
// ... and 82 more files (download for full content)
About this extraction
This page contains the full source code of the DevToys-app/DevToysMac GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 282 files (22.5 MB), approximately 260.8k tokens. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.