Giter Club home page Giter Club logo

extensions-swift-tools's Introduction

Swift for Raycast Extensions

This Swift Package contains code generation macros and plugins to build a communication chanel between Raycast's React extensions and Swift native code. Basically, it lets you import Swift code into your Raycast extension in order to:

  • leverage native macOS APIs that might not be exposed to TS/JS, or
  • use Swift for targeted sections of your extension, letting you use all Swift language features (such as result builders, async/await, generics/existentials, etc.), or
  • compartmentalize your extension into client-facing code (react) and system code (swift).

Requirements

  • Xcode.

    Xcode needs to be installed in your system. We are hoping to not need Xcode in the future and use the pure Swift toolchain, alas we are not there yet. Please notice, you don't need to write the swift code in Xcode, you can use any other editor such as VSCode, Sublime, or Nova.

Using the Package

  1. Create (or fork) a Raycast extension.

    If you don't know how, check out this guide.

  2. Create a Swift executable target in the folder of your Raycast extension.

    You can create the target in any of the following ways:

    using Xcode, or

    • Open Xcode
    • File > New > Package... to create a new Swift package
    • Select `Executable`
    • Select the place within the Raycast extension package you want
    • Untick the "Create Git repository on my Mac"

      I like to put it in a `swift` folder next to the existing `src` folder.

    • Delete the main.swift file autogenerated by Xcode.

      This file is reserved for the Raycast plugins generating the TypeScript interface.

    • Create a new package New executable package

    using the swift package command in the terminal or VSCode.

    • Run swift package init --type executable --name CustomName in the Raycast extension folder.

      In the previous command of code CustomName references the name for the Swift Package. You can name this whatever you want.

    • Delete the main.swift file autogenerated by swift package.

      This file is reserved for the Raycast plugins generating the TypeScript interface.

    You shouldn't have a main.swift file in your project nor a structure marked with @main. These are reserved for the Swift-to-TypeScript plugins.

  3. Modify the Package.swift file to include the necessary macros and build plugins.

    // swift-tools-version: 5.9
    
    import PackageDescription
    
    let package = Package(
        name: "CustomName",
    +    platforms: [
    +      .macOS(.v12)
    +    ],
    +    dependencies: [
    +      .package(url: "https://github.com/raycast/extensions-swift-tools", from: "1.0.0")
    +    ],
        targets: [
          .executableTarget(
            name: "CustomName",
    +       dependencies: [
    +         .product(name: "RaycastSwiftMacros", package: "extensions-swift-tools"),
    +         .product(name: "RaycastSwiftPlugin", package: "extensions-swift-tools"),
    +         .product(name: "RaycastTypeScriptPlugin", package: "extensions-swift-tools"),
    +       ]
          ),
        ]
    )
  4. Import RaycastSwiftMacros in your Swift file.

    import RaycastSwiftMacros
  5. Write global Swift functions and mark them with the @raycast attribute.

    Global functions marked with @raycast are exported to TypeScript. These functions can have any number of parameters or one or no return types. Likewise, the function can be asynchronous (async) or throw errors (throws). The only restrictions are:

    • Parameters must conform to Decodable.
    • The return type (if any) must conform to Encodable.
    • Variadic parameters and value packs are not supported.
    • Only global functions will be exported. Methods or functions within structs or enums won't be exported.
    @raycast func greet(name: String, isFormal: Bool) -> String {
     let address = isFormal ? "Mr/Ms" : ""
     return "Hello \(address) \(name)! How are you?"
    }

    Custom types can be received as parameters or returned by the function. You just need to be sure for the type to conform to Codable.

    @raycast func pickColor(name: String) throws -> Color {
      switch name {
      case "red": Color(red: 1, green: 0, blue: 0)
      case "green": Color(red: 0, green: 1, blue: 0)
      case "blue": Color(red: 0, green: 0, blue: 1)
      default: throw Color.Error.unsupportedColor
      }
    }
    
    struct Color: Encodable {
      let red: Float
      let green: Float
      let blue: Float
    
      enum Error: Swift.Error {
        case unsupportedColor
      }
    }

extensions-swift-tools's People

Contributors

dehesa avatar grzegorzkrukowski avatar mathieudutour avatar

Stargazers

 avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.