Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 18 additions & 20 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,28 +8,25 @@ Have you ever found yourself context switching all the time when you are develop

simctl.nvim can help you:

* Create shortcuts to boot, shut down, restart and reset Simulators
* Remote control Simulator settings like light/dark mode, permissions and font sizes
* Develop Expo or React Native apps with easy run actions
* Automate starting a Simulator when running your front end project
* Create custom run and build actions setting up the Simulator just so
* Automate setting UI options like time and network connection for screenshots
* Test push notifications from APNS or JSON source files
* Enroll biometry and send matching and non-matching authentication
- Create shortcuts to boot, shut down, restart and reset Simulators
- Remote control Simulator settings like light/dark mode, permissions and font sizes
- Develop Expo or React Native apps with easy run actions
- Automate starting a Simulator when running your front end project
- Create custom run and build actions setting up the Simulator just so
- Automate setting UI options like time and network connection for screenshots
- Test push notifications from APNS or JSON source files
- Enroll biometry and send matching and non-matching authentication

## Installation

Mac OS and Xcode are required. Make sure `xcrun` is available in your terminal.
NeoVim 0.10 or newer on Mac OS, as well as Xcode are required. Make sure `xcrun` is available in your terminal.

Using Lazy:

```lua
{
"terje/simctl.nvim",
version = "*", -- Use latest release instead of latest commit. Recommended.
dependencies = {
"nvim-lua/plenary.nvim",
},
}
```

Expand Down Expand Up @@ -70,13 +67,13 @@ The `SimctlNotify` command is automatically registered for `.json` and `.apns` f

```json
{
"Simulator Target Bundle": "com.test.MyNotifiedApp",
"aps": {
"alert": {
"title": "NeoVim says hello",
"body": "Your favourite editor sends its greetings"
}
"Simulator Target Bundle": "com.test.MyNotifiedApp",
"aps": {
"alert": {
"title": "NeoVim says hello",
"body": "Your favourite editor sends its greetings"
}
}
}
```

Expand Down Expand Up @@ -122,6 +119,7 @@ pickers.pickDevice()
```

Add any of these to your keymap for easy access:

```lua
vim.keymap.set("n", "<leader>ib", function()
require("simctl.api").boot()
Expand Down Expand Up @@ -253,8 +251,6 @@ local args = {
require("simctl.api").push(args)
```



### Shut down device

```lua
Expand Down Expand Up @@ -292,6 +288,7 @@ simctl.biometry.setEnrollment({ enrolled = true })
```

#### Get biometry enrollment status

```lua
local simctl = require("simctl.api")
simctl.biometry.isEnrolled({}, function(success, isEnrolled)
Expand All @@ -309,6 +306,7 @@ end)
```

#### Biometric authentication

```lua
local simctl = require("simctl.api")
simctl.biometry.authenticate() -- This is me
Expand Down
51 changes: 16 additions & 35 deletions lua/simctl/lib/simctl.lua
Original file line number Diff line number Diff line change
@@ -1,50 +1,31 @@
local M = {}

local Job = require("plenary.job")

M.errors = {
[3] = "App not found.",
[405] = "Cannot run command while Simulator is in this state.",
[3] = "App not found.",
[405] = "Cannot run command while Simulator is in this state.",
}

local extractedErrorCode = function(message)
local pattern = "code=(%d+)"
return tonumber(message:match(pattern))
local pattern = "code=(%d+)"
return tonumber(message:match(pattern))
end

local humaneMessage = function(message)
return M.errors[extractedErrorCode(message)]
return M.errors[extractedErrorCode(message)]
end

M.execute = function(args, callback)
local simctlArguments = { "simctl" }
for _, v in ipairs(args) do
table.insert(simctlArguments, v)
end

local stdoutBuffer = { "" }
local stderrBuffer = {}

Job:new({
command = "xcrun",
args = simctlArguments,
on_exit = function(j, return_val)
local stderr = table.concat(stderrBuffer, "\n")
local stdout = table.concat(stdoutBuffer, "\n")

callback(return_val, humaneMessage(stderr), stdout, stderr)
end,
on_stdout = function(j, data)
if data ~= "" then
table.insert(stdoutBuffer, data)
end
end,
on_stderr = function(j, data)
if data ~= "" then
table.insert(stderrBuffer, data)
end
end,
}):start()
local simctlArguments = { "simctl" }
for _, v in ipairs(args) do
table.insert(simctlArguments, v)
end

vim.system({
"xcrun",
unpack(simctlArguments),
}, { text = true }, function(result)
callback(result.code, humaneMessage(result.stderr), result.stdout, result.stderr)
end)
end

return M
72 changes: 34 additions & 38 deletions lua/simctl/lib/util.lua
Original file line number Diff line number Diff line change
@@ -1,65 +1,61 @@
local M = {}

local config = require("simctl.config")
local Job = require("plenary.job")

M.merge = function(args, defaults)
args = args or {}
defaults = defaults or {}
return vim.tbl_deep_extend("force", {}, defaults, args)
args = args or {}
defaults = defaults or {}
return vim.tbl_deep_extend("force", {}, defaults, args)
end

M.notify = function(message, level)
if not config.options.notify then
return
end
if not config.options.notify then
return
end

level = level or vim.log.levels.INFO
vim.notify("iOS Simulator: " .. message, level)
level = level or vim.log.levels.INFO
vim.notify("iOS Simulator: " .. message, level)
end

local simulatorAppStatus = function(callback)
Job:new({
command = "ps",
args = { "aux", "|", "grep", "-v", "grep", "|", "grep", "-c", "Simulator.app" },
on_exit = function(j, return_val)
callback(return_val == 1)
end,
on_stderr = function(j, data)
callback(false)
end,
}):start()
vim.system({
"sh",
"-c",
"ps aux | grep -c Simulator.app",
}, { text = true }, function(result)
callback(result.code == 1)
end)
end

M.openSimulatorApp = function()
simulatorAppStatus(function(isSimulatorRunning)
if not isSimulatorRunning then
os.execute("open -a Simulator.app")
end
end)
simulatorAppStatus(function(isSimulatorRunning)
if not isSimulatorRunning then
vim.system({ "open", "-a", "Simulator.app" })
end
end)
end

M.isValidKey = function(key, table)
if type(table) ~= "table" then
return false
end

for _, v in pairs(table) do
if v == key then
return true
end
end
return false
if type(table) ~= "table" then
return false
end

for _, v in pairs(table) do
if v == key then
return true
end
end
return false
end

M.trim = function(s)
return (s:gsub("^%s*(.-)%s*$", "%1"))
return (s:gsub("^%s*(.-)%s*$", "%1"))
end

M.defaultCallback = function(success, result)
if not success then
M.notify(result, vim.log.levels.ERROR)
end
if not success then
M.notify(result, vim.log.levels.ERROR)
end
end

return M
Loading