Skip to content

Commit

Permalink
feat: add url support for applescript, fix examples in readme
Browse files Browse the repository at this point in the history
  • Loading branch information
mdevils committed Mar 20, 2024
1 parent 6f550e1 commit 738dda4
Show file tree
Hide file tree
Showing 6 changed files with 59 additions and 166 deletions.
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "osakit"
version = "0.1.2"
version = "0.2.0"
edition = "2021"
authors = ["Marat Dulin <mdevils@gmail.com>"]
description = "OSAKit macOS Framework adapted for Rust"
Expand Down
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,6 @@ lint-fix:
cargo fmt

test-watch:
cargo bin cargo-watch -x "test --all-features --no-fail-fast $T"
cargo bin cargo-watch -x "bin cargo-nextest run --all-features --no-fail-fast $T"

pre-commit: test lint
60 changes: 32 additions & 28 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ Input and output data are represented using `Value` from

Comes with `declare_script!` macro (unstable) to simplify working with `OSAKit Framework`.

[Source code on GitHub](https://github.com/mdevils/rust-osakit)

## Installation

Add `osakit` to the dependencies. Specify `"full"` feature if you want to use `declare_script`
Expand All @@ -26,7 +28,8 @@ osakit = { version = "0.1.0", features = ["full"] }
```rust
use serde::{Deserialize, Serialize};
use osakit::declare_script;

use std::error::Error;

declare_script! {
#[language(JavaScript)]
#[source("
Expand Down Expand Up @@ -57,76 +60,77 @@ struct User {
id: u16,
name: String,
}

#[test]
fn it_runs_my_js_script() {

fn main() -> Result<(), Box<dyn Error>> {
let script = MyJsScript::new().unwrap();
assert_eq!(
script.multiply(3, 2).unwrap(),
6
);
assert_eq!(
script.concat("Hello, ", "World").unwrap(),
script.concat("Hello, ", "World")?,
"Hello, World"
);
assert_eq!(
script.current_user().unwrap(),
script.current_user()?,
User {
id: 21,
name: "root".into()
}
);
Ok(())
}
```

## Example using `Script`

```rust
use osakit::{Language, Map, Script, Value, Number};

#[test]
fn it_constructs_and_executes_scripts() {
let mut script = Script::new_from_source(
Language::AppleScript, "
on launch_terminal()
tell application \"Terminal\" to launch
end launch_terminal
use std::error::Error;

fn main() -> Result<(), Box<dyn Error>> {
let mut script = Script::new_from_source(Language::AppleScript, "
on is_app_running()
tell application \"Hopefully Non-Existing Application\" to running
end is_app_running
on concat(x, y)
return x & y
end concat
return {id: 21, name: \"root\"}
");

script.compile().unwrap();

script.compile()?;
assert_eq!(
script.execute().unwrap(),
script.execute()?,
Value::Object(Map::from_iter(vec![
("id".into(), Value::Number(Number::from(21))),
("name".into(), Value::String("root".into()))
]))
);

assert_eq!(
script.execute_function("concat", &vec![
script.execute_function("concat", vec![
Value::String("Hello, ".into()),
Value::String("World!".into())
]).unwrap(),
])?,
Value::String("Hello, World!".into())
);
assert!(
script.execute_function("launch_terminal", &vec![]).is_ok()
assert_eq!(
script.execute_function("is_app_running", vec![])?,
Value::Bool(false)
);

Ok(())
}
```

## Usage

See [Full Documentation](https://docs.rs/osakit/).

## Limitations

Due to limitations on `OSAKit Framework`-side integer values returned from `JavaScript` code
are limited to `i32` type.

## Supported platforms

Due to the fact that OSAKit is Mac-specific, only `macOS` is supported.
Expand All @@ -136,9 +140,9 @@ Due to the fact that OSAKit is Mac-specific, only `macOS` is supported.
Licensed under either of

* Apache License, Version 2.0
([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0)
([LICENSE-APACHE](LICENSE-APACHE) or <http://www.apache.org/licenses/LICENSE-2.0>)
* MIT license
([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT)
([LICENSE-MIT](LICENSE-MIT) or <http://opensource.org/licenses/MIT>)

at your option.

Expand Down
136 changes: 1 addition & 135 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,138 +1,4 @@
//! `osakit` aims to provide direct access to `OSAKit Framework` of macOS. Is uses ObjC-bindings
//! to access OSAKit and run both `AppleScript` and `JavaScript`.
//!
//! `osakit` is built using [`serde`](https://crates.io/crates/serde) for input-output
//! serialization/deserialization.
//! Allows passing data to `JavaScript`/`AppleScript` functions and returns back the results.
//! Input and output data are represented using `Value` from [`serde_json`].
//!
//! Comes with [`declare_script!`] macro (unstable) to simplify
//! working with `OSAKit Framework`.
//!
//! [Source code on GitHub](https://github.com/mdevils/rust-osakit)
//!
//! ## Installation
//!
//! Add `osakit` to the dependencies. Specify `"full"` feature if you want to use `declare_script`
//! macro or `"stable"` feature to only include stable API.
//!
//! ```toml
//! [dependencies]
//! osakit = { version = "0.1.2", features = ["full"] }
//! ```
//!
//! ## Example using `declare_script`
//!
//! ```
//! use serde::{Deserialize, Serialize};
//! use osakit::declare_script;
//!
//! declare_script! {
//! #[language(JavaScript)]
//! #[source("
//! function concat(x, y) {
//! return x + y;
//! }
//!
//! function multiply(a, b) {
//! return a * b;
//! }
//!
//! function current_user() {
//! return {
//! id: 21,
//! name: \"root\"
//! };
//! }
//! ")]
//! MyJsScript {
//! fn concat(x: &str, y: &str) -> String;
//! fn multiply(a: i32, b: i32) -> i32;
//! fn current_user() -> User;
//! }
//! }
//!
//! #[derive(Deserialize, Serialize, Debug, PartialEq, Eq)]
//! struct User {
//! id: u16,
//! name: String,
//! }
//!
//! # use std::error::Error;
//! # fn main() -> Result<(), Box<dyn Error>> {
//! #
//! let script = MyJsScript::new()?;
//! assert_eq!(
//! script.multiply(3, 2)?,
//! 6
//! );
//! assert_eq!(
//! script.concat("Hello, ", "World")?,
//! "Hello, World"
//! );
//! assert_eq!(
//! script.current_user()?,
//! User {
//! id: 21,
//! name: "root".into()
//! }
//! );
//! #
//! # Ok(())
//! # }
//! ```
//!
//! ## Example using `Script`
//!
//! ```
//! use osakit::{Language, Map, Script, Value, Number};
//!
//! # use std::error::Error;
//! # fn main() -> Result<(), Box<dyn Error>> {
//! #
//! let mut script = Script::new_from_source(
//! Language::AppleScript, "
//! on is_app_running()
//! tell application \"Hopefully Non-Existing Application\" to running
//! end is_app_running
//!
//! on concat(x, y)
//! return x & y
//! end concat
//!
//! return {id: 21, name: \"root\"}
//! ");
//!
//! script.compile()?;
//!
//! assert_eq!(
//! script.execute()?,
//! Value::Object(Map::from_iter(vec![
//! ("id".into(), Value::Number(Number::from(21))),
//! ("name".into(), Value::String("root".into()))
//! ]))
//! );
//!
//! assert_eq!(
//! script.execute_function("concat", vec![
//! Value::String("Hello, ".into()),
//! Value::String("World!".into())
//! ])?,
//! Value::String("Hello, World!".into())
//! );
//!
//! assert_eq!(
//! script.execute_function("is_app_running", vec![])?,
//! Value::Bool(false)
//! );
//! #
//! # Ok(())
//! # }
//! ```
//!
//! ## Supported platforms
//!
//! Due to the fact that OSAKit is Mac-specific, only `macOS` is supported.
#![doc = include_str!("../README.md")]

mod script;
mod value;
Expand Down
23 changes: 23 additions & 0 deletions src/value/output.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ pub enum ScriptOutputConversionError {
DescriptorNotFoundAtIndex(isize),
#[error("infinite float cannot be converted: `{0}`")]
InfiniteFloat(String),
#[error("url expected, but none found")]
UrlExpectedButNoneFound,
}

type FourCharCode = u32;
Expand Down Expand Up @@ -80,6 +82,7 @@ four_char_codes! {
DESC_TYPE_NULL: "null",
DESC_TYPE_ENUM: "enum",
DESC_TYPE_LDATE: "ldt ",
DESC_TYPE_URL: "url ",
OSTYPE_MISSING: "msng",
OSTYPE_NULL: "null",
OSTYPE_YES: "yes ",
Expand Down Expand Up @@ -141,6 +144,10 @@ pub(crate) fn get_value_from_ns_apple_event_descriptor(
))
}
},
DESC_TYPE_URL => match unsafe { descriptor.stringValue() } {
Some(url) => Value::String(url.to_string()),
None => return Err(ScriptOutputConversionError::UrlExpectedButNoneFound),
},
DESC_TYPE_NULL => Value::Null,
DESC_TYPE_RECORD => {
let mut result: Map<String, Value> = Map::new();
Expand Down Expand Up @@ -407,6 +414,14 @@ mod test {
);
}

#[test]
fn it_returns_positive_longlong_as_float() {
assert_eq!(
value_from_apple_script("9000000000"),
Value::Number(Number::from_f64(9000000000.0).unwrap())
);
}

#[test]
fn it_returns_negative_long() {
assert_eq!(
Expand Down Expand Up @@ -446,6 +461,14 @@ mod test {
);
}

#[test]
fn it_returns_url_as_string() {
assert_eq!(
value_from_apple_script("\"http://example.com\" as URL"),
Value::String("http://example.com".into())
);
}

#[test]
fn it_returns_null() {
assert_eq!(value_from_apple_script("null"), Value::Null);
Expand Down

0 comments on commit 738dda4

Please sign in to comment.