A framework for writing terminal applications in Swift.

Overview

Ashen

A framework for writing terminal applications in Swift. Based on The Elm Architecture.

As a tutorial of Ashen, let's consider an application that fetches some todo items and renders them as a list.

Example

Old way

In a traditional controller/view pattern, views are created during initialization, and updated later as needed with your application data. Loading data from a server to load a list of views. Views are stored in instance variables and edited "in place", and the views/subviews are added/removed as events happen, so a lot of code is there to manage view state.

New way

What would this look like using Ashen or Elm or React? In these frameworks, rendering output is declarative; it is based the model, and you render all the views and their properties based on that state. Model goes in, View comes out.

func render(model: Model) -> View<Message> {
    guard
        let data = model.data
    else {
        // no data?  Show the spinner.
        return Spinner()
    }

    return Stack(.topToBottom, [
        Text("List of things"),
        ListView(dataList: data) { row in
            LabelView(text: row.title)
        }
        // 👆 this view is similar to how UITableView renders cells - only
        // the rows that are visible will be rendered. rowHeight can also be
        // assigned a function, btw, to support dynamic heights.
        //
        // Also, this view is not done yet! Sorry - but it'll look something
        // like this.
    ])
}

So instead of mutating the isHidden property of views, or addSubview, we just render the views we need based on our model. SwiftUI has also adopted this model, so if you've been using it, Ashen will feel very familiar.

Commands and Messages

To fetch our data, we need to call out to the runtime to ask it to perform a background task, aka a Command, and then report the results back as a Message. Message is how your Components can tell your application about changes that might result in a change to your model. For instance, if someone types in a "name" text field you probably want to know about that so you can update the model's name property.

Sources of Messages include Views, Commands, and system event components (e.g. a KeyEvent message can be captured via the OnKeyPress component, which receives system-level events and maps those into an instance of your app's Message type).

Our application starts at the initial() method. We return our initial model and a command to run. We will return an Http command:

enum Message {
    case received(Result<(Int, Headers, Data), HttpError>)
}

func initial() -> Initial<Model, Message> {
    let url = URL(string: "http://example.com")!
    let cmd = Http.get(url) { result in
      Message.received(result)
    }

    return Initial(Model(), cmd)
}

When the Http request succeeds (or fails) the result will be turned into an instance of your application's Message type (usually an enum), and passed to the update() function that you provide.

To send multiple commands, group them with Command.list([cmd1, cmd2, ...])

Updating

In your application's update() function, you will instruct the runtime how the message affects your state. Your options are:

  • .noChange — ignore the message
  • .update(model, command) — return a model and a list of Commands to run
  • .quit — graceful exit (usually means exit with status 0)
  • .quitAnd({ ... })— graceful exit with a closure that runs just before the runtime is done cleaning up. You can also throw an error in that closure.

For convenience there are two helper "types":

  • .model(model) — return just updated model, no commands (shortcut for .update(model, Command.none()))
  • .error(error) — quit and raise an error.

Program

Here's a skeleton program template:

// This is usually an enum, but it can be any type.  Your app will respond
// to state changes by accepting a `Message` and returning a modified
// `Model`.
enum Message {
    case quit
}

// The entired state of you program will be stored here, so a struct is the
// most common type.
struct Model {
}

// Return your initial model and commands. if your app requires
// initialization from an API (i.eg. a loading spinner), use a
// `loading/loaded/error` enum to represent the initial state.  If you
// persist your application to the database you could load that here, either
// synchronously or via a `Command`.
func initial() -> Initial<Model, Message> {
    Initial(Model())
}

// Ashen will call this method with the current model, and a message that
// you use to update your model.  This will result in a screen refresh, but
// it also means that your program is very easy to test; pass a model to
// this method along with the message you want to test, and check the values
// of the model.
//
// The return value also includes a list of "commands".  Commands are
// another form of event emitters, like Components, but they talk with
// external services, either asynchronously or synchronously.
func update(model: Model, message: Message)
    -> State<Model, Message>
{
    switch message {
    case .quit:
        return .quit
    }
}

// Finally the render() method is given your model and you return
// an array of views. Why an array? I optimized for the common case: some key
// handlers, maybe some mouse events, and a "main" view.
func render(model: Model) -> [View<Message>] {
    [
        OnKeyPress(.enter, { Message.quit }),
        Frame(Spinner(), .alignment(.middleCenter)),
    ])
}

Running your Program

To run your program, pass your initial, update, view, and unmount functions to Ashen.Program and run it with ashen(program). It will return .quit or .error, depending on how the program exited.

do {
    try ashen(Program(initial, update, view))
    exit(EX_OK)
} catch {
    exit(EX_IOERR)
}

Important note: ALL Ashen programs can be aborted using ctrl+c. It is recommended that you support ctrl+\ to gracefully exit your program.

Views

  • Text() - display text or attributed text.
    Text("Some plain text")
    Text("Some underlined text".underlined())
  • Input() - editable text, make sure to pass .isResponder(true) to the active Input.
    enum Message {
        case textChanged(String)
    }
    Input("Editable text", Message.textChanged, .isResponder(true))
  • Box() - surround a view with a customizable border.
    Box(view)
    Box(view, .border(.double))
    Box(view, .border(.double), .title("Welcome".bold()))
  • Flow() - arrange views using a flexbox like layout.
    Flow(.leftToRight, [  // alias: .ltr
        (.fixed, Text(" ")),
        (.flex1, Text(Hi!).underlined()), // this view will stretch to fill the available space
        // .flex1 is a handy alias for .flex(1) - just like CSS flex: 1, you can use different flex
        // values to give more or less % of the available space to the subviews
        (.fixed, Text(" ")),
    ])
    Flow(.bottomToTop, views)
  • Columns() - arrange views horizontally, equally sized and taking up all space.
    Columns(views)
  • Rows() - arrange views vertically, equally sized and taking up all space.
    Rows(views)
  • Stack() - arrange views according to their preferred (usually smallest) size.
    Stack(.ltr, views)
  • Frame() - place a view inside a container that fills the available space, and supports alignment.
    Frame(Text("Hi!"), .alignment(.middleCenter))
  • Spinner() - show a simple 1x1 spinner animation
    Spinner()
  • Scroll(view, .offset(pt|x:|y:)) - Make a view scrollable. By default the scroll view does not respond to key or mouse events. To make the view scrollable via mouse, try this:
    enum Message {
        case scroll(Int)  // update model.scrollY by this value
    }
    OnMouseWheel(
        Scroll(Stack(.down, [...]), .offset(model.scrollY)),
        Message.scroll
    )
    Also consider adding a "listener" for the onResizeContent: message, which will pass a LocalViewport (which has the size of the entire scrollable area and the visible: Rect)
  • Repeating(view) - Useful for background drawing. By itself it has preferredSize: .zero, but will draw the passed view to fill the available area.
    // draw the text "Hi!" centered, then fill the rest of the background with red.
    ZStack([Frame(Text("Hi!".background(.red)), .alignment(.middleCenter)), Repeating(Text(" ".background(.red)))])

View Modifiers

Views can be created in a fluent syntax (these will feel much like SwiftUI, though not nearly that level of complexity & sophistication).

  • .size(preferredSize), .minSize(preferredSize), .maxSize(preferredSize) - ensures the view is at least, exactly, or at most preferredSize. See also .width(w), .minWidth(w), .maxWidth(w), .height(h), .minHeight(h), .maxHeight(h) to control only the width or height.
    Text("Hi!").width(5)
    Stack(.ltr, [...]).maxSize(Size(width: 20, height: 5))
  • .matchContainer(), .matchContainer(dimension: .width|.height) - Ignores the view's preferred size in favor of the size provided by the containing view.
  • .matchSize(ofView: view), .matchSize(ofView: view, dimension: .width|.height) - Ignores the view's preferred size in favor of another view (usually a sibling view, in a ZStack).
  • .fitInContainer(.width|.height) - Make sure the width or height is equal to or less than the containing view's width or height.
  • .compact() - Usually the containing view's size is passed to the view's render function, even if it's much more than the preferred size. This method renders the view using the preferredSize instead.
  • .padding(left:,top:,right:,bottom:) or .padding(Insets) - Increases the preferred size to accommodate padding, and renders the view inside the padded area. If you are interested in peaking into some simple rendering/masking code, this is a good place to start.
  • .styled(Attr) - After drawing the view, the rendered area is modified to include the Attr. See also: underlined(), bottomLined(), reversed(), bold(), foreground(color:), background(color:), reset()
    Text("Hi!".underlined()).background(color: .red)
    Stack(.ltr, [...]).reversed()
  • .border(BoxBorder) - Surrounds the view in a border.
    Text("Hi!").border(.single, .title("Message"))
  • .aligned(Alignment) - This is useful when you know a view will be rendered in an area much larger than the view's preferredSize. The Alignment options are topLeft, topCenter, topRight, middleLeft, middleCenter, middleRight, bottomLeft, bottomCenter, bottomRight.
    Text("Hi!").aligned(.middleCenter)
    See also .centered(), which is shorthand for .aligned(.topCenter), useful for centering text or a group of views.
  • .scrollable(offset: Point) - Wraps the view in Scroll(view, .offset(offset))

Events

  • OnKeyPress
  • OnTick
  • OnResize
  • OnNext
  • OnClick
  • OnMouseWheel
  • OnMouse
  • IgnoreMouse
You might also like...
PrettyColors is a Swift library for styling and coloring text in the Terminal.

PrettyColors is a Swift library for styling and coloring text in the Terminal. The library outputs ANSI escape codes and conforms to ECMA Standard 48.

VT100/Xterm Terminal emulator in Swift
VT100/Xterm Terminal emulator in Swift

SwiftTerm SwiftTerm is a VT100/Xterm terminal emulator library for Swift applications that can be embedded into macOS, iOS applications, text-based, h

Demo using Terminal.Gui with Llama Swift
Demo using Terminal.Gui with Llama Swift

Hola! This repo is a demo which shows the use of Llama Swift with Terminal.Gui. Llama is my exploratory project to compile "other languages" for .NET

Terminal string styling for Swift.
Terminal string styling for Swift.

Terminal string styling for Swift. Integration Swift Package Manager (SPM) You can use The Swift Package Manager to install ColorizeSwift by adding it

✏️Expressive styling on terminal string. (chalk for swift)
✏️Expressive styling on terminal string. (chalk for swift)

Chalk Expressive styling on terminal string. Highlights Expressive API 256/TrueColor support Nest styles Auto downgrading to terminal supported color

Terminal TODO application in Swift with ncurses.
Terminal TODO application in Swift with ncurses.

stodo Terminal TODO application in Swift with ncurses. Development streamed live

✏️Expressive styling on terminal string. (chalk for swift)
✏️Expressive styling on terminal string. (chalk for swift)

Chalk Expressive styling on terminal string. Highlights Expressive API 256/TrueColor support Nest styles Auto downgrading to terminal supported color

Terminal Colors for Swift
Terminal Colors for Swift

Terminal string styling for Swift Colors is a clean and focused solution for string styling in Swift. Usage import Colors print(Colors.blue("Blue str

A simple game running from the terminal

A simple game running from the terminal

macOS terminal utility for monitoring WiFi link quality
macOS terminal utility for monitoring WiFi link quality

📡 wifimon Synopsis wifimon is a wireless device monitoring terminal application that allows you to watch signal, noise and SNR levels as well as devi

Lock a terminal command to the efficiency or performance cores on a big.LITTLE ARM processor

CPU-Lock Lock a terminal command to the efficiency or performance cores on a big.LITTLE ARM processor (Designed for Apple Silicon). Usage Download the

Lock a terminal command to the efficiency or performance cores on a big.LITTLE ARM processor.

cpu-lock Lock a terminal command to the efficiency or performance cores on a big.LITTLE ARM processor (Designed for Apple Silicon). Usage Download the

Mac-asksec - Test Mac Permissions from the Terminal

asksec A simple CLI to test permissions from any macOS terminal app. Building ru

iOS sandboxed terminal with Python, Lua and Clang

LibTerm LibTerm is a terminal for iOS with Python 3.7 and Lua 5.3. Supports iOS 13 dark mode and multi window. Features The app supports most of OpenT

A terminal for iOS, with multiple windows

a-shell: A terminal for iOS, with multiple windows The goal in this project is to provide a simple Unix-like terminal on iOS. It uses ios_system for c

Terminal Watch Face for Apple Watch
Terminal Watch Face for Apple Watch

Terminal Watch Face for Apple Watch

A Swift-based API for reading from & writing to the Apple System Log (more commonly known somewhat inaccurately as
A Swift-based API for reading from & writing to the Apple System Log (more commonly known somewhat inaccurately as "the console")

CleanroomASL Notice: CleanroomASL is no longer supported The Apple System Log facility has been deprecated by Apple. As a result, we've deprecated Cle

A lightweight library for writing HTTP web servers with Swift

Taylor Disclaimer: Not actively working on it anymore. You can check out some alternatives Swift 2.0 required. Working with Xcode 7.1. Disclaimer: It

đź“„ A Swift DSL for writing type-safe HTML/CSS in SwiftUI way

đź“„ swift-web-page (swep) Swep is a Swift DSL for writing type-safe HTML/CSS in SwiftUI way. Table of Contents Motivation Examples Safety Design FAQ In

Comments
  • Cursor or

    Cursor or "selectable" elements

    Hello!

    I have been using Ashen to recreate a Magit-like experience in my terminal. If you do not know Magit, it’s a git porcelain inside Emacs. You navigate in a Magit "view" with a cursor that can move up and down (see an example here https://youtu.be/NDP91RNgT4A?t=129), and perform actions on the currently "highlighted" item.

    Creating the interface with sections and headers was easy, but I am now trying to implement this cursor, or a way to "highlight" items. I haven’t really found a way to do this yet, so I thought I’d just ask. Is this something that can be done right now, or something you have thought about implementing?

    opened by bendiksolheim 1
  • Can this project run on linux?

    Can this project run on linux?

    I tried running an example app on LInux(I'm using Pop OS)

    and I got this error running swift run

    `/home/alex/Documents/app-test/.build/checkouts/Ashen/Sources/Ashen/Core/Ashen.swift:65:25: error: cannot find 'mach_absolute_time' in scope var prevTimestamp = mach_absolute_time() ^~~~~~~~~~~~~~~~~~ /home/alex/Documents/app-test/.build/checkouts/Ashen/Sources/Ashen/Core/Ashen.swift:66:16: error: cannot find 'mach_timebase_info' in scope var info = mach_timebase_info(numer: 0, denom: 0) ^~~~~~~~~~~~~~~~~~ /home/alex/Documents/app-test/.build/checkouts/Ashen/Sources/Ashen/Core/Ashen.swift:67:5: error: cannot find 'mach_timebase_info' in scope mach_timebase_info(&info) ^~~~~~~~~~~~~~~~~~ /home/alex/Documents/app-test/.build/checkouts/Ashen/Sources/Ashen/Core/Ashen.swift:164:23: error: cannot find 'mach_absolute_time' in scope let currentTime = mach_absolute_time() ^~~~~~~~~~~~~~~~~~ /home/alex/Documents/app-test/.build/checkouts/Ashen/Sources/Ashen/Views/Input.swift:618:10: error: the compiler is unable to type-check this expression in reasonable time; try breaking up the expression into distinct sub-expressions .replacingOccurrences(of: "\u{F0004}y", with: "ỳ") /home/alex/Documents/app-test/.build/checkouts/Ashen/Sources/Ashen/Commands/Http.swift:574:28: error: cannot find type 'URLRequest' in scope func toURLRequest() -> URLRequest? ^~~~~~~~~~ /home/alex/Documents/app-test/.build/checkouts/Ashen/Sources/Ashen/Commands/Http.swift:264:29: error: cannot find type 'NSURLRequest' in scope case networkService(NSURLRequest.NetworkServiceType) // default, voip, video, background, voice ^~~~~~~~~~~~ /home/alex/Documents/app-test/.build/checkouts/Ashen/Sources/Ashen/Commands/Http.swift:288:20: error: 'URLSessionConfiguration' is unavailable: This type has moved to the FoundationNetworking module. Import that module to use it. case mock((URLSessionConfiguration) -> URLSessionProtocol) ^~~~~~~~~~~~~~~~~~~~~~~ Foundation.URLSessionConfiguration:2:18: note: 'URLSessionConfiguration' has been explicitly marked unavailable here public typealias URLSessionConfiguration = AnyObject ^ /home/alex/Documents/app-test/.build/checkouts/Ashen/Sources/Ashen/Commands/Http.swift:463:15: error: cannot find type 'URLRequest' in scope with: URLRequest, completionHandler: ((Int, [Http.Header], Data?, Swift.Error?) -> Void)? ^~~~~~~~~~ /home/alex/Documents/app-test/.build/checkouts/Ashen/Sources/Ashen/Commands/Http.swift:467:15: error: cannot find type 'URLRequest' in scope with: URLRequest, completionHandler: ((Int, [Http.Header], Data?, Swift.Error?) -> Void)? ^~~~~~~~~~ /home/alex/Documents/app-test/.build/checkouts/Ashen/Sources/Ashen/Commands/Http.swift:290:64: error: cannot find type 'URLSessionDelegate' in scope func create(config: URLSessionConfiguration, delegate: URLSessionDelegate) ^~~~~~~~~~~~~~~~~~ /home/alex/Documents/app-test/.build/checkouts/Ashen/Sources/Ashen/Commands/Http.swift:290:29: error: 'URLSessionConfiguration' is unavailable: This type has moved to the FoundationNetworking module. Import that module to use it. func create(config: URLSessionConfiguration, delegate: URLSessionDelegate) ^~~~~~~~~~~~~~~~~~~~~~~ Foundation.URLSessionConfiguration:2:18: note: 'URLSessionConfiguration' has been explicitly marked unavailable here public typealias URLSessionConfiguration = AnyObject ^ /home/alex/Documents/app-test/.build/checkouts/Ashen/Sources/Ashen/Commands/Http.swift:315:18: error: cannot find type 'URLRequest' in scope let request: URLRequest ^~~~~~~~~~ /home/alex/Documents/app-test/.build/checkouts/Ashen/Sources/Ashen/Commands/Http.swift:321:27: error: cannot find type 'URLRequest' in scope request request: URLRequest, ^~~~~~~~~~ /home/alex/Documents/app-test/.build/checkouts/Ashen/Sources/Ashen/Commands/Http.swift:392:43: error: cannot find type 'URLRequest' in scope private func startDataTask( request: URLRequest) { ^~~~~~~~~~ /home/alex/Documents/app-test/.build/checkouts/Ashen/Sources/Ashen/Commands/Http.swift:400:47: error: cannot find type 'URLRequest' in scope private func startDownloadTask(_ request: URLRequest) { ^~~~~~~~~~ /home/alex/Documents/app-test/.build/checkouts/Ashen/Sources/Ashen/Commands/Http.swift:410:40: error: cannot find type 'URLSessionDelegate' in scope extension HttpPrivateRequest.Delegate: URLSessionDelegate {} ^~~~~~~~~~~~~~~~~~ /home/alex/Documents/app-test/.build/checkouts/Ashen/Sources/Ashen/Commands/Http.swift:412:40: error: cannot find type 'URLSessionTaskDelegate' in scope extension HttpPrivateRequest.Delegate: URLSessionTaskDelegate { ^~~~~~~~~~~~~~~~~~~~~~ /home/alex/Documents/app-test/.build/checkouts/Ashen/Sources/Ashen/Commands/Http.swift:419:40: error: cannot find type 'URLSessionDataDelegate' in scope extension HttpPrivateRequest.Delegate: URLSessionDataDelegate { ^~~~~~~~~~~~~~~~~~~~~~ /home/alex/Documents/app-test/.build/checkouts/Ashen/Sources/Ashen/Commands/Http.swift:424:40: error: cannot find type 'URLSessionDownloadDelegate' in scope extension HttpPrivateRequest.Delegate: URLSessionDownloadDelegate { ^~~~~~~~~~~~~~~~~~~~~~~~~~ /home/alex/Documents/app-test/.build/checkouts/Ashen/Sources/Ashen/Commands/Http.swift:427:20: error: 'URLSession' is unavailable: This type has moved to the FoundationNetworking module. Import that module to use it. _ session: URLSession, ^~~~~~~~~~ Foundation.URLSession:2:18: note: 'URLSession' has been explicitly marked unavailable here public typealias URLSession = AnyObject ^ /home/alex/Documents/app-test/.build/checkouts/Ashen/Sources/Ashen/Commands/Http.swift:428:23: error: 'URLSessionDownloadTask' is unavailable: This type has moved to the FoundationNetworking module. Import that module to use it. downloadTask: URLSessionDownloadTask, ^~~~~~~~~~~~~~~~~~~~~~ Foundation.URLSessionDownloadTask:2:18: note: 'URLSessionDownloadTask' has been explicitly marked unavailable here public typealias URLSessionDownloadTask = AnyObject ^ /home/alex/Documents/app-test/.build/checkouts/Ashen/Sources/Ashen/Commands/Http.swift:441:20: error: 'URLSession' is unavailable: This type has moved to the FoundationNetworking module. Import that module to use it. _ session: URLSession, ^~~~~~~~~~ Foundation.URLSession:2:18: note: 'URLSession' has been explicitly marked unavailable here public typealias URLSession = AnyObject ^ /home/alex/Documents/app-test/.build/checkouts/Ashen/Sources/Ashen/Commands/Http.swift:442:23: error: 'URLSessionDownloadTask' is unavailable: This type has moved to the FoundationNetworking module. Import that module to use it. downloadTask: URLSessionDownloadTask, ^~~~~~~~~~~~~~~~~~~~~~ Foundation.URLSessionDownloadTask:2:18: note: 'URLSessionDownloadTask' has been explicitly marked unavailable here public typealias URLSessionDownloadTask = AnyObject ^ /home/alex/Documents/app-test/.build/checkouts/Ashen/Sources/Ashen/Commands/Http.swift:453:44: error: 'URLResponse' is unavailable: This type has moved to the FoundationNetworking module. Import that module to use it. private func responseToHeaders(_ response: URLResponse?) -> [Http.Header] { ^~~~~~~~~~~ Foundation.URLResponse:2:18: note: 'URLResponse' has been explicitly marked unavailable here public typealias URLResponse = AnyObject ^ /home/alex/Documents/app-test/.build/checkouts/Ashen/Sources/Ashen/Commands/Http.swift:473:1: error: non-nominal type 'URLSession' (aka 'AnyObject') cannot be extended extension URLSession: URLSessionProtocol { ^ ~~~~~~~~~~ /home/alex/Documents/app-test/.build/checkouts/Ashen/Sources/Ashen/Commands/Http.swift:522:1: error: non-nominal type 'URLSessionTask' (aka 'AnyObject') cannot be extended extension URLSessionTask: URLSessionTaskProtocol { ^ ~~~~~~~~~~~~~~ /home/alex/Documents/app-test/.build/checkouts/Ashen/Sources/Ashen/Commands/Http.swift:529:33: error: 'URLSessionConfiguration' is unavailable: This type has moved to the FoundationNetworking module. Import that module to use it. func apply(toConfig config: URLSessionConfiguration) { ^~~~~~~~~~~~~~~~~~~~~~~ Foundation.URLSessionConfiguration:2:18: note: 'URLSessionConfiguration' has been explicitly marked unavailable here public typealias URLSessionConfiguration = AnyObject ^ /home/alex/Documents/app-test/.build/checkouts/Ashen/Sources/Ashen/Commands/Http.swift:550:41: error: cannot find type 'URLRequest' in scope func apply(toRequest request: inout URLRequest) { ^~~~~~~~~~ /home/alex/Documents/app-test/.build/checkouts/Ashen/Sources/Ashen/Commands/Http.swift:578:35: error: cannot find type 'URLRequest' in scope public func toURLRequest() -> URLRequest? { ^~~~~~~~~~ /home/alex/Documents/app-test/.build/checkouts/Ashen/Sources/Ashen/Commands/Http.swift:584:35: error: cannot find type 'URLRequest' in scope public func toURLRequest() -> URLRequest? { ^~~~~~~~~~ /home/alex/Documents/app-test/.build/checkouts/Ashen/Sources/Ashen/Commands/Http.swift:589:11: error: cannot find type 'URLRequest' in scope extension URLRequest: URLRequestConvertible { ^~~~~~~~~~ /home/alex/Documents/app-test/.build/checkouts/Ashen/Sources/Ashen/Commands/Http.swift:295:24: error: type 'URLSession' (aka 'AnyObject') has no member 'init' return URLSession(configuration: config, delegate: delegate, delegateQueue: nil) ^~~~~~~~~~ /home/alex/Documents/app-test/.build/checkouts/Ashen/Sources/Ashen/Commands/Http.swift:295:93: error: 'nil' requires a contextual type return URLSession(configuration: config, delegate: delegate, delegateQueue: nil) ^ /home/alex/Documents/app-test/.build/checkouts/Ashen/Sources/Ashen/Commands/Http.swift:325:24: error: 'URLSessionConfiguration' is unavailable: This type has moved to the FoundationNetworking module. Import that module to use it. var configOpt: URLSessionConfiguration? ^~~~~~~~~~~~~~~~~~~~~~~ Foundation.URLSessionConfiguration:2:18: note: 'URLSessionConfiguration' has been explicitly marked unavailable here public typealias URLSessionConfiguration = AnyObject ^ /home/alex/Documents/app-test/.build/checkouts/Ashen/Sources/Ashen/Commands/Http.swift:328:20: error: type of expression is ambiguous without more context option.apply(toRequest: &request) ~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~ /home/alex/Documents/app-test/.build/checkouts/Ashen/Sources/Ashen/Commands/Http.swift:330:30: error: type 'URLSessionConfiguration?' (aka 'Optional') has no member 'background' configOpt = .background(withIdentifier: identifier) ~^~~~~~~~~~ /home/alex/Documents/app-test/.build/checkouts/Ashen/Sources/Ashen/Commands/Http.swift:332:30: error: type 'URLSessionConfiguration?' (aka 'Optional') has no member 'ephemeral' configOpt = .ephemeral ~^~~~~~~~~ /home/alex/Documents/app-test/.build/checkouts/Ashen/Sources/Ashen/Commands/Http.swift:344:36: error: type 'URLSessionConfiguration?' (aka 'Optional') has no member 'default' let config = configOpt ?? .default ~^~~~~~~ /home/alex/Documents/app-test/.build/checkouts/Ashen/Sources/Ashen/Commands/Http.swift:454:35: warning: conditional downcast from 'URLResponse?' (aka 'Optional') to 'HTTPURLResponse' (aka 'AnyObject') does nothing guard let response = response as? HTTPURLResponse else { return [] } ~~~~~~~~~^~~~~~~~~~~~~~~~~~~

    /home/alex/Documents/app-test/.build/checkouts/Ashen/Sources/Ashen/Commands/Http.swift:454:39: error: 'HTTPURLResponse' is unavailable: This type has moved to the FoundationNetworking module. Import that module to use it. guard let response = response as? HTTPURLResponse else { return [] } ^~~~~~~~~~~~~~~ Foundation.HTTPURLResponse:2:18: note: 'HTTPURLResponse' has been explicitly marked unavailable here public typealias HTTPURLResponse = AnyObject ^ /home/alex/Documents/app-test/.build/checkouts/Ashen/Sources/Ashen/Commands/Http.swift:455:21: error: value of type 'HTTPURLResponse' (aka 'AnyObject') has no member 'allHeaderFields' return response.allHeaderFields.compactMap { name, value -> Http.Header? in ~~~~~~~~ ^~~~~~~~~~~~~~~ /home/alex/Documents/app-test/.build/checkouts/Ashen/Sources/Ashen/Commands/Http.swift:532:20: error: value of type 'URLSessionConfiguration' (aka 'AnyObject') has no member 'timeoutIntervalForRequest' config.timeoutIntervalForRequest = value ~~~~~~ ^~~~~~~~~~~~~~~~~~~~~~~~~ /home/alex/Documents/app-test/.build/checkouts/Ashen/Sources/Ashen/Commands/Http.swift:533:20: error: value of type 'URLSessionConfiguration' (aka 'AnyObject') has no member 'timeoutIntervalForResource' config.timeoutIntervalForResource = value ~~~~~~ ^~~~~~~~~~~~~~~~~~~~~~~~~~ /home/alex/Documents/app-test/.build/checkouts/Ashen/Sources/Ashen/Commands/Http.swift:535:20: error: value of type 'URLSessionConfiguration' (aka 'AnyObject') has no member 'timeoutIntervalForRequest' config.timeoutIntervalForRequest = value ~~~~~~ ^~~~~~~~~~~~~~~~~~~~~~~~~ /home/alex/Documents/app-test/.build/checkouts/Ashen/Sources/Ashen/Commands/Http.swift:537:20: error: value of type 'URLSessionConfiguration' (aka 'AnyObject') has no member 'timeoutIntervalForResource' config.timeoutIntervalForResource = value ~~~~~~ ^~~~~~~~~~~~~~~~~~~~~~~~~~ /home/alex/Documents/app-test/.build/checkouts/Ashen/Sources/Ashen/Commands/Http.swift:539:20: error: value of type 'URLSessionConfiguration' (aka 'AnyObject') has no member 'networkServiceType' config.networkServiceType = value ~~~~~~ ^~~~~~~~~~~~~~~~~~ /home/alex/Documents/app-test/.build/checkouts/Ashen/Sources/Ashen/Commands/Http.swift:541:20: error: value of type 'URLSessionConfiguration' (aka 'AnyObject') has no member 'allowsCellularAccess' config.allowsCellularAccess = value ~~~~~~ ^~~~~~~~~~~~~~~~~~~~ /home/alex/Documents/app-test/.build/checkouts/Ashen/Sources/Ashen/Commands/Http.swift:543:20: error: value of type 'URLSessionConfiguration' (aka 'AnyObject') has no member 'sharedContainerIdentifier' config.sharedContainerIdentifier = value ~~~~~~ ^~~~~~~~~~~~~~~~~~~~~~~~~ /home/alex/Documents/app-test/.build/checkouts/Ashen/Sources/Ashen/Commands/Http.swift:559:30: error: 'nil' requires a contextual type request.setValue(nil, forHTTPHeaderField: key) ^ /home/alex/Documents/app-test/.build/checkouts/Ashen/Sources/Ashen/Commands/Http.swift:475:23: error: cannot find type 'URLRequest' in scope with request: URLRequest, ^~~~~~~~~~ /home/alex/Documents/app-test/.build/checkouts/Ashen/Sources/Ashen/Commands/Http.swift:489:23: error: cannot find type 'URLRequest' in scope with request: URLRequest, ^~~~~~~~~~ /home/alex/Documents/app-test/.build/checkouts/Ashen/Sources/Ashen/Commands/Http.swift:590:35: error: cannot find type 'URLRequest' in scope public func toURLRequest() -> URLRequest? { ^~~~~~~~~~ [3/6] Compiling Ashen Http.swift error: fatalError`

    What could be the cause of this issue?

    opened by ajstrand 0
  • Include of non-modular header inside framework module 'ctermbox':

    Include of non-modular header inside framework module 'ctermbox':

    I tried to import the library with SPM, but I got an error of non-modular header inside the framework. The strangest thing of all is: It compiles with swift run on the terminal, but it does not compile with Xcode, which leads me to some kind of issue with Xcode beta, but I couldn't figure it out yet. So, I'm reporting the issue here, in case you have faced it before.

    Note: I'm using the Xcode beta 5

    opened by amadeu01 1
Owner
Colin T.A. Gray
Principle Developer of Mobile at Shopify. Enthusiastic open source coder. These days hardware hacking is floating my boat (see Mechy).
Colin T.A. Gray
A template for new Swift iOS / macOS / tvOS / watchOS Framework project ready with travis-ci, cocoapods, Carthage, SwiftPM and a Readme file

Swift Framework Template A template for new Swift Framework. What's in the template? Deployment Targets - iOS 9.0 / Mac OS X 10.10 / tvOS 9.0 / watchO

Rahul Katariya 529 Jun 27, 2022
Swift Modules, a swift module (or package) manager

Swift Modules The Swift Modules manager similar to the JavaScript world's npm and bower

Jan KuÄŤa 60 Jun 3, 2021
A package manager that installs and runs executable Swift packages

Mint ?? A package manager that installs and runs Swift command line tool packages. $ mint run realm/[email protected] This would install and run SwiftL

Yonas Kolb 2k Jan 7, 2023
The Package Manager for the Swift Programming Language

Swift Package Manager Project The Swift Package Manager is a tool for managing distribution of source code, aimed at making it easy to share your code

Apple 9.1k Dec 29, 2022
Gradle plugin for managing Swift by enhancing Carthage with Maven repository

Works presents Athena Preface As a mobile application engineer that develops iOS and Android applications, I found that in Android, dependencies can b

Yunarta Kartawahyudi 1 Nov 3, 2020
Helping you find inner peace when comparing version numbers in Swift

Helping you find inner peace when comparing version numbers in Swift. Comparing with the current applications version couldn't be easier. // App.versi

Christoffer Winterkvist 207 Jun 29, 2022
Frank is a DSL for quickly writing web applications in Swift

Frank Frank is a DSL for quickly writing web applications in Swift with type-safe path routing. Sources/main.swift import Frank // Handle GET request

Kyle Fuller Archive 377 Jun 29, 2022
Frank is a DSL for quickly writing web applications in Swift

Frank Frank is a DSL for quickly writing web applications in Swift with type-safe path routing. Sources/main.swift import Frank // Handle GET request

Kyle Fuller Archive 376 Jan 3, 2023
A collection of useful test helpers designed to ease the burden of writing tests for iOS applications.

MetovaTestKit is a collection of useful test helpers designed to ease the burden of writing tests for iOS applications. Requirements Installation Usag

null 23 Aug 29, 2021
Swift framework containing a set of helpful XCTest extensions for writing UI automation tests

AutoMate • AppBuddy • Templates • ModelGenie AutoMate AutoMate is a Swift framework containing a set of helpful XCTest extensions for writing UI autom

PGS Software 274 Dec 30, 2022