• Stars
    star
    410
  • Rank 105,468 (Top 3 %)
  • Language
    Lua
  • License
    MIT License
  • Created about 1 year ago
  • Updated 7 months ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Neovim plugin to Build, Debug, and Test applications created for Apple devices (iOS, macOS, watchOS, etc.)

๐Ÿ› ๏ธ xcodebuild.nvim

A plugin designed to let you migrate your iOS, iPadOS, and macOS app development to Neovim. It provides all essential actions for development, including building, launching, and testing.

Xcodebuild Testing

Xcodebuild Debugging

ย 

โœจ Features

  • Support for iOS, iPadOS, and macOS apps built using Swift.
  • Project-based configuration.
  • Project Manager to deal with project files without using Xcode.
  • Test Explorer to visually present a tree with all tests and results.
  • Built using official command line tools like xcodebuild and xcrun simctl.
  • Actions to build, run, debug, and test apps on simulators and physical devices.
  • Buffer integration with test results (code coverage, success & failure marks, duration, extra diagnostics).
  • Code coverage report with customizable levels.
  • Browser of failing snapshot tests with a diff preview (if you use swift-snapshot-testing).
  • Advanced log parser to detect all errors, warnings, and failing tests.
  • nvim-tree and oil.nvim integration that automatically reflects all file tree operations and updates Xcode project.
  • nvim-dap integration to let you easily build, run, and debug apps.
  • nvim-dap-ui integration to show app logs in the console window.
  • lualine.nvim integration to show selected device, test plan, and other project settings.
  • Quick integration to show test results for tests written using Quick framework.
  • Auto-detection of the target membership for new files.
  • Picker with all available plugin actions.
  • Highly customizable (many config options, auto commands, highlights, and user commands).

ย 

๐ŸŒณ File Tree Integration

Xcodebuild.nvim is integrated with nvim-tree and oil.nvim to let you manage your project and files in a convenient way.

Every change in the file tree presented by these plugins will be automatically reflected in the Xcode project file.

Additionally, the Project Manager will try predicting targets for newly created files based on their location. If you prefer to select targets manually, you can always disable it in the configuration using integrations.nvim_tree.guess_target or integrations.oil_nvim.guess_target.

nvim-tree.mp4

ย 

โšก๏ธ Requirements

Neovim environment
External tools
  • xcbeautify to format Xcode logs (you can set a different tool or disable formatting in the config).
  • Xcodeproj to manage project files within Neovim.
  • Ruby to use Xcodeproj gem.
  • pymobiledevice3 to debug on physical devices and/or run apps on devices below iOS 17.
  • xcode-build-server to make LSP work properly with xcodeproj/xcworkspace.
  • codelldb to debug iOS and macOS Swift apps.
  • Xcode to build, run, and test apps. Make sure that xcodebuild and xcrun simctl work correctly. Tested with Xcode 15.
Availability of features
Device (iOS <17) Device (iOS 17+) via Network (<17 / 17+) Simulator MacOS
build ๐Ÿ› ๏ธ โœ… โŒ / โœ… โœ… โœ…
(un)install ๐Ÿ› ๏ธ โœ… ๐Ÿ› ๏ธ / โœ… โœ… โŒ
launch ๐Ÿ› ๏ธ โœ… ๐Ÿ› ๏ธ / โœ… โœ… โœ…
run tests ๐Ÿ› ๏ธ โœ… โŒ / โœ… โœ… โœ…
debug ๐Ÿ› ๏ธ ๐Ÿ” ๐Ÿ› ๏ธ โŒ โœ… โœ…
debug tests โŒ โŒ โŒ โœ… โœ…
app logs ๐Ÿชฒ ๐Ÿชฒ โŒ โœ… ๐Ÿชฒ

๐Ÿ” - requires passwordless sudo permission for tools/remote_debugger script (see below).

๐Ÿ› ๏ธ - available if pymobiledevice3 is installed.

๐Ÿชฒ - available while debugging.

ย 

๐Ÿ“ฆ Installation

Install the plugin using your preferred package manager.

๐Ÿ’ค lazy.nvim

return {
  "wojciech-kulik/xcodebuild.nvim",
  dependencies = {
    "nvim-telescope/telescope.nvim",
    "MunifTanjim/nui.nvim",
    "nvim-tree/nvim-tree.lua", -- (optional) to manage project files
    "stevearc/oil.nvim", -- (optional) to manage project files
    "nvim-treesitter/nvim-treesitter", -- (optional) for Quick tests support (required Swift parser)
  },
  config = function()
    require("xcodebuild").setup({
        -- put some options here or leave it empty to use default settings
    })
  end,
}

Install external tools:

brew install xcode-build-server
brew install xcbeautify
brew install ruby
gem install xcodeproj
python3 -m pip install -U pymobiledevice3

To quickly install all required tools you can run:

make install

Tip

Make sure to check out Tips & Tricks!

You will find there a collection of useful tips & tricks for iOS/macOS development in Neovim.

ย 

๐Ÿ“ฑ Setup Neovim For iOS Development

I wrote an article that gathers all the steps required to set up Neovim from scratch to develop iOS and macOS apps:

The Complete Guide To iOS & macOS Development In Neovim

You can also check out the sample Neovim configuration that I prepared for iOS development: ios-dev-starter-nvim

ย 

๐Ÿš€ Usage

Make sure to open your project's root directory and run XcodebuildSetup to configure it. The plugin needs several information like project file, scheme, config, device, and test plan to be able to run commands.

Remember, that all the information are available in the help :h xcodebuild. Every function is documented and described both in the help and in the code.

๐Ÿ”ง Commands

๐Ÿ‘‰ See all user commands

Xcodebuild.nvim comes with the following commands:

General

Command Description
XcodebuildSetup Run configuration wizard to select project configuration
XcodebuildPicker Show picker with all available actions
XcodebuildBuild Build project
XcodebuildCleanBuild Build project (clean build)
XcodebuildBuildRun Build & run app
XcodebuildBuildForTesting Build for testing
XcodebuildRun Run app without building
XcodebuildCancel Cancel currently running action
XcodebuildCleanDerivedData Deletes project's DerivedData
XcodebuildToggleLogs Toggle logs panel
XcodebuildOpenLogs Open logs panel
XcodebuildCloseLogs Close logs panel
XcodebuildOpenInXcode Open project in Xcode
XcodebuildQuickfixLine Try fixing issues in the current line
XcodebuildCodeActions Show code actions for the current line

Project Manager

Command Description
XcodebuildProjectManager Show picker with all Project Manager actions
XcodebuildCreateNewFile Create a new file and add it to target(s)
XcodebuildAddCurrentFile Add the active file to target(s)
XcodebuildRenameCurrentFile Rename the current file
XcodebuildDeleteCurrentFile Delete the current file
XcodebuildCreateNewGroup Create a new directory and add it to the project
XcodebuildAddCurrentGroup Add the parent directory of the active file to the project
XcodebuildRenameCurrentGroup Rename the current directory
XcodebuildDeleteCurrentGroup Delete the current directory including all files inside
XcodebuildUpdateCurrentFileTargets Update target membership of the active file
XcodebuildShowCurrentFileTargets Show target membership of the active file

๐Ÿ‘‰ To add a file to multiple targets use multi-select feature (by default tab).

Testing

Command Description
XcodebuildTest Run tests (whole test plan)
XcodebuildTestTarget Run test target (where the cursor is)
XcodebuildTestClass Run test class (where the cursor is)
XcodebuildTestFunc Run test (where the cursor is)
XcodebuildTestSelected Run selected tests (using visual mode)
XcodebuildTestFailing Rerun previously failed tests
XcodebuildFailingSnapshots Show a picker with failing snapshot tests

Code Coverage

Command Description
XcodebuildToggleCodeCoverage Toggle code coverage marks on the side bar
XcodebuildShowCodeCoverageReport Open HTML code coverage report
XcodebuildJumpToNextCoverage Jump to next code coverage mark
XcodebuildJumpToPrevCoverage Jump to previous code coverage mark

Test Explorer

Command Description
XcodebuildTestExplorerShow Show Test Explorer
XcodebuildTestExplorerHide Hide Test Explorer
XcodebuildTestExplorerToggle Toggle Test Explorer
XcodebuildTestExplorerRunSelectedTests Run Selected Tests
XcodebuildTestExplorerRerunTests Re-run recently selected tests

Configuration

Command Description
XcodebuildSelectScheme Show scheme picker
XcodebuildSelectDevice Show device picker
XcodebuildSelectTestPlan Show test plan picker
XcodebuildShowConfig Print current project configuration
XcodebuildBootSimulator Boot selected simulator
XcodebuildInstallApp Install application
XcodebuildUninstallApp Uninstall application

โŒ˜ Sample Key Bindings

vim.keymap.set("n", "<leader>X", "<cmd>XcodebuildPicker<cr>", { desc = "Show Xcodebuild Actions" })
vim.keymap.set("n", "<leader>xf", "<cmd>XcodebuildProjectManager<cr>", { desc = "Show Project Manager Actions" })

vim.keymap.set("n", "<leader>xb", "<cmd>XcodebuildBuild<cr>", { desc = "Build Project" })
vim.keymap.set("n", "<leader>xB", "<cmd>XcodebuildBuildForTesting<cr>", { desc = "Build For Testing" })
vim.keymap.set("n", "<leader>xr", "<cmd>XcodebuildBuildRun<cr>", { desc = "Build & Run Project" })

vim.keymap.set("n", "<leader>xt", "<cmd>XcodebuildTest<cr>", { desc = "Run Tests" })
vim.keymap.set("v", "<leader>xt", "<cmd>XcodebuildTestSelected<cr>", { desc = "Run Selected Tests" })
vim.keymap.set("n", "<leader>xT", "<cmd>XcodebuildTestClass<cr>", { desc = "Run This Test Class" })

vim.keymap.set("n", "<leader>xl", "<cmd>XcodebuildToggleLogs<cr>", { desc = "Toggle Xcodebuild Logs" })
vim.keymap.set("n", "<leader>xc", "<cmd>XcodebuildToggleCodeCoverage<cr>", { desc = "Toggle Code Coverage" })
vim.keymap.set("n", "<leader>xC", "<cmd>XcodebuildShowCodeCoverageReport<cr>", { desc = "Show Code Coverage Report" })
vim.keymap.set("n", "<leader>xe", "<cmd>XcodebuildTestExplorerToggle<cr>", { desc = "Toggle Test Explorer" })
vim.keymap.set("n", "<leader>xs", "<cmd>XcodebuildFailingSnapshots<cr>", { desc = "Show Failing Snapshots" })

vim.keymap.set("n", "<leader>xd", "<cmd>XcodebuildSelectDevice<cr>", { desc = "Select Device" })
vim.keymap.set("n", "<leader>xp", "<cmd>XcodebuildSelectTestPlan<cr>", { desc = "Select Test Plan" })
vim.keymap.set("n", "<leader>xq", "<cmd>Telescope quickfix<cr>", { desc = "Show QuickFix List" })

vim.keymap.set("n", "<leader>xx", "<cmd>XcodebuildQuickfixLine<cr>", { desc = "Quickfix Line" })
vim.keymap.set("n", "<leader>xa", "<cmd>XcodebuildCodeActions<cr>", { desc = "Show Code Actions" })

Tip

Press <leader>X to access the picker with all commands.

Press <leader>xf to access the picker with all Project Manager commands.

Press <C-r> when the picker with devices is presented to refresh the list.

๐Ÿ“‹ Logs Panel

  • Press o on a failed test in the summary section to jump to the failing location
  • Press q to close the panel

๐Ÿงช Test Explorer

  • Press o to jump to the test implementation
  • Press t to run selected tests
  • Press T to re-run recently selected tests
  • Press R to reload test list
  • Press [ to jump to the previous failed test
  • Press ] to jump to the next failed test
  • Press <cr> to expand or collapse the current node
  • Press <tab> to expand or collapse all classes
  • Press q to close the Test Explorer

ย 

โš™๏ธ Configuration

๐Ÿ”ฅ Customize Xcodebuild.nvim

See default Xcodebuild.nvim config
{
  restore_on_start = true, -- logs, diagnostics, and marks will be loaded on VimEnter (may affect performance)
  auto_save = true, -- save all buffers before running build or tests (command: silent wa!)
  show_build_progress_bar = true, -- shows [ ...    ] progress bar during build, based on the last duration
  prepare_snapshot_test_previews = true, -- prepares a list with failing snapshot tests
  test_search = {
    file_matching = "filename_lsp", -- one of: filename, lsp, lsp_filename, filename_lsp. Check out README for details
    target_matching = true, -- checks if the test file target matches the one from logs. Try disabling it in case of not showing test results
    lsp_client = "sourcekit", -- name of your LSP for Swift files
    lsp_timeout = 200, -- LSP timeout in milliseconds
  },
  commands = {
    cache_devices = true, -- cache recently loaded devices. Restart Neovim to clean cache.
    extra_build_args = "-parallelizeTargets", -- extra arguments for `xcodebuild build`
    extra_test_args = "-parallelizeTargets", -- extra arguments for `xcodebuild test`
    project_search_max_depth = 3, -- maxdepth of xcodeproj/xcworkspace search while using configuration wizard
    remote_debugger = nil, -- optional path to local copy of remote_debugger (check out README for details)
    remote_debugger_port = 65123, -- port used by remote debugger (passed to pymobiledevice3)
  },
  logs = { -- build & test logs
    auto_open_on_success_tests = false, -- open logs when tests succeeded
    auto_open_on_failed_tests = false, -- open logs when tests failed
    auto_open_on_success_build = false, -- open logs when build succeeded
    auto_open_on_failed_build = true, -- open logs when build failed
    auto_close_on_app_launch = false, -- close logs when app is launched
    auto_close_on_success_build = false, -- close logs when build succeeded (only if auto_open_on_success_build=false)
    auto_focus = true, -- focus logs buffer when opened
    filetype = "objc", -- file type set for buffer with logs
    open_command = "silent botright 20split {path}", -- command used to open logs panel. You must use {path} variable to load the log file
    logs_formatter = "xcbeautify --disable-colored-output", -- command used to format logs, you can use "" to skip formatting
    only_summary = false, -- if true logs won't be displayed, just xcodebuild.nvim summary
    show_warnings = true, -- show warnings in logs summary
    notify = function(message, severity) -- function to show notifications from this module (like "Build Failed")
      vim.notify(message, severity)
    end,
    notify_progress = function(message) -- function to show live progress (like during tests)
      vim.cmd("echo '" .. message .. "'")
    end,
  },
  console_logs = {
    enabled = true, -- enable console logs in dap-ui
    format_line = function(line) -- format each line of logs
      return line
    end,
    filter_line = function(line) -- filter each line of logs
      return true
    end,
  },
  marks = {
    show_signs = true, -- show each test result on the side bar
    success_sign = "โœ”", -- passed test icon
    failure_sign = "โœ–", -- failed test icon
    show_test_duration = true, -- show each test duration next to its declaration
    show_diagnostics = true, -- add test failures to diagnostics
  },
  quickfix = {
    show_errors_on_quickfixlist = true, -- add build/test errors to quickfix list
    show_warnings_on_quickfixlist = true, -- add build warnings to quickfix list
  },
  test_explorer = {
    enabled = true, -- enable Test Explorer
    auto_open = true, -- open Test Explorer when tests are started
    auto_focus = true, -- focus Test Explorer when opened
    open_command = "botright 42vsplit Test Explorer", -- command used to open Test Explorer, must create a buffer with "Test Explorer" name
    open_expanded = true, -- open Test Explorer with expanded classes
    success_sign = "โœ”", -- passed test icon
    failure_sign = "โœ–", -- failed test icon
    progress_sign = "โ€ฆ", -- progress icon (only used when animate_status=false)
    disabled_sign = "โธ", -- disabled test icon
    partial_execution_sign = "โ€", -- icon for a class or target when only some tests were executed
    not_executed_sign = " ", -- not executed or partially executed test icon
    show_disabled_tests = false, -- show disabled tests
    animate_status = true, -- animate status while running tests
    cursor_follows_tests = true, -- moves cursor to the last test executed
  },
  code_coverage = {
    enabled = false, -- generate code coverage report and show marks
    file_pattern = "*.swift", -- coverage will be shown in files matching this pattern
    -- configuration of line coverage presentation:
    covered_sign = "",
    partially_covered_sign = "โ”ƒ",
    not_covered_sign = "โ”ƒ",
    not_executable_sign = "",
  },
  code_coverage_report = {
    warning_coverage_level = 60,
    error_coverage_level = 30,
    open_expanded = false,
  },
  integrations = {
    xcode_build_server = {
      enabled = false, -- run "xcode-build-server config" when scheme changes
    },
    nvim_tree = {
      enabled = true, -- enable updating Xcode project files when using nvim-tree
      guess_target = true, -- guess target for the new file based on the file path
      should_update_project = function(path) -- path can lead to directory or file
        -- it could be useful if you mix Xcode project with SPM for example
        return true
      end,
    },
    oil_nvim = {
      enabled = true, -- enable updating Xcode project files when using oil.nvim
      guess_target = true, -- guess target for the new file based on the file path
      should_update_project = function(path) -- path can lead to directory or file
        -- it could be useful if you mix Xcode project with SPM for example
        return true
      end,
    },
    quick = { -- integration with Swift test framework: github.com/Quick/Quick
      enabled = true, -- enable Quick tests support (requires Swift parser for nvim-treesitter)
    },
  },
  highlights = {
    -- you can override here any highlight group used by this plugin
    -- simple color: XcodebuildCoverageReportOk = "#00ff00",
    -- link highlights: XcodebuildCoverageReportOk = "DiagnosticOk",
    -- full customization: XcodebuildCoverageReportOk = { fg = "#00ff00", bold = true },
  },
}

๐ŸŽจ Customize Highlights

See all highlights

Test File

Highlight Group Description
XcodebuildTestSuccessSign Test passed sign
XcodebuildTestFailureSign Test failed sign
XcodebuildTestSuccessDurationSign Test duration of a passed test
XcodebuildTestFailureDurationSign Test duration of a failed test

Test Explorer

Highlight Group Description
XcodebuildTestExplorerTest Test name (function)
XcodebuildTestExplorerClass Test class
XcodebuildTestExplorerTarget Test target
XcodebuildTestExplorerTestInProgress Test in progress sign
XcodebuildTestExplorerTestPassed Test passed sign
XcodebuildTestExplorerTestFailed Test failed sign
XcodebuildTestExplorerTestDisabled Test disabled sign
XcodebuildTestExplorerTestNotExecuted Test not executed sign
XcodebuildTestExplorerTestPartialExecution Not all tests executed sign

Code Coverage (inline)

Highlight Group Description
XcodebuildCoverageFullSign Covered line - sign
XcodebuildCoverageFullNumber Covered line - line number
XcodebuildCoverageFullLine Covered line - code
XcodebuildCoveragePartialSign Partially covered line - sign
XcodebuildCoveragePartialNumber Partially covered line - line number
XcodebuildCoveragePartialLine Partially covered line - code
XcodebuildCoverageNoneSign Not covered line - sign
XcodebuildCoverageNoneNumber Not covered line - line number
XcodebuildCoverageNoneLine Not covered line - code
XcodebuildCoverageNotExecutableSign Not executable line - sign
XcodebuildCoverageNotExecutableNumber Not executable line - line number
XcodebuildCoverageNotExecutableLine Not executable line - code

Code Coverage (report)

Highlight Group Description
XcodebuildCoverageReportOk Percentage color when above warning_coverage_level
XcodebuildCoverageReportWarning Percentage color when below warning_coverage_level
XcodebuildCoverageReportError Percentage color when below error_coverage_level

๐Ÿค– Customize Behaviors

See all auto commands

You can customize integration with xcodebuild.nvim plugin by subscribing to notifications.

Example:

vim.api.nvim_create_autocmd("User", {
  pattern = "XcodebuildTestsFinished",
  callback = function(event)
    print("Tests finished (passed: "
        .. event.data.passedCount
        .. ", failed: "
        .. event.data.failedCount
        .. ")"
    )
  end,
})

Use print(vim.inspect(event.data)) to see what is exactly provided in the payload.

Below you can find a list of all available auto commands.

Pattern Provided Data (event.data)
XcodebuildBuildStarted forTesting (Bool)
XcodebuildBuildStatus forTesting (Bool), progress (Int? [0-100]), duration (Int)
XcodebuildBuildFinished forTesting (Bool), success (Bool), cancelled (Bool), errors (ParsedBuildError[])
XcodebuildTestsStarted none
XcodebuildTestsStatus passedCount (Int), failedCount (Int)
XcodebuildTestsFinished passedCount (Int), failedCount (Int), cancelled (Bool)
XcodebuildApplicationLaunched none
XcodebuildActionCancelled none
XcodebuildProjectSettingsUpdated (ProjectSettings)
XcodebuildTestExplorerToggled visible (Bool), bufnr (Int?), winnr (Int?)
XcodebuildCoverageToggled (Bool)
XcodebuildCoverageReportToggled visible (Bool), bufnr (Int?), winnr (Int?)
XcodebuildLogsToggled visible (Bool), bufnr (Int?), winnr (Int?)

๐Ÿ“ฆ Swift Packages Development

This plugin supports only iOS and macOS applications. However, if you develop Swift Package for one of those platforms, you can easily use this plugin by creating a sample iOS/macOS project in your root directory and by adding your package as a dependency.

ย 

๐Ÿ”ฌ Debugger Configuration

nvim-dap plugin lets you debug applications like in any other IDE. On top of that nvim-dap-ui extension will present for you all panels with stack, breakpoints, variables, logs, etc.

To configure DAP for development:

  • Download codelldb VS Code plugin from: HERE. For macOS use darwin version.
  • Just unzip vsix file and set paths in the configuration below.
  • Install also nvim-dap-ui for a nice GUI to debug.
  • Make sure to enable console window from nvim-dap-ui to see simulator logs.
return {
  "mfussenegger/nvim-dap",
  dependencies = {
    "wojciech-kulik/xcodebuild.nvim"
  },
  config = function()
    local xcodebuild = require("xcodebuild.integrations.dap")
    -- SAMPLE PATH, change it to your local codelldb path
    local codelldbPath = os.getenv("HOME") .. "/tools/codelldb-aarch64-darwin/extension/adapter/codelldb"

    xcodebuild.setup(codelldbPath)

    vim.keymap.set("n", "<leader>dd", xcodebuild.build_and_debug, { desc = "Build & Debug" })
    vim.keymap.set("n", "<leader>dr", xcodebuild.debug_without_build, { desc = "Debug Without Building" })
    vim.keymap.set("n", "<leader>dt", xcodebuild.debug_tests, { desc = "Debug Tests" })
    vim.keymap.set("n", "<leader>dT", xcodebuild.debug_class_tests, { desc = "Debug Class Tests" })
    vim.keymap.set("n", "<leader>b", xcodebuild.toggle_breakpoint, { desc = "Toggle Breakpoint" })
    vim.keymap.set("n", "<leader>B", xcodebuild.toggle_message_breakpoint, { desc = "Toggle Message Breakpoint" })
    vim.keymap.set("n", "<leader>dx", xcodebuild.terminate_session, { desc = "Terminate Debugger" })
  end,
}

ย 

๐Ÿ“ฒ Debugging On iOS 17+ Device

Since iOS 17, a new secure connection between Mac and mobile devices is required. Xcodebuild.nvim uses pymobiledevice3 to establish a special trusted tunnel that is later used for debugging. However, this operation requires sudo (more details).

Showing a pop-up to enter a password every time you run a debugger would be quite annoying. That's why the plugin provides a small script (tools/remote_debugger) that wraps the only two operations requiring sudo (starting a secure tunnel and closing it).

This allows you to configure passwordless access just for this single file and make it work with xcodebuild.nvim. You can even make a local copy if you are worried that the content of this file could be changed in the future.

Passwordless access to remote_debugger

You can disable password requirement by updating /etc/sudoers file. Make sure to use the command below, otherwise you may break your sudo command:

sudo visudo -f /etc/sudoers

Append this line, but first update the path and the username:

YOUR_USERNAME ALL = (ALL) NOPASSWD: /Users/YOUR_USERNAME/.local/share/nvim/lazy/xcodebuild.nvim/tools/remote_debugger

Creating a local copy of remote_debugger

If you don't want to configure the passwordless permission to the file that could be changed in the future, you can make a local copy of this script, set your local path in the config commands.remote_debugger, and update /etc/sudoers accordingly.

Please remember that you will have to update this file manually if it changes in the future.

ย 

๐Ÿ› Application Logs

If you installed nvim-dap and nvim-dap-ui, you can easily track your app logs. The plugin automatically sends logs to the console window provided by nvim-dap-ui.

To see SIMULATOR logs you don't need to run the debugger. You can just show the console and run the app (remember that the app must be launched using xcodebuild.nvim).

:lua require("dapui").toggle()

Important

Logs printed by NSLog will appear only if the debugger is NOT attached.

You can always clear the console window by calling:

:lua require("xcodebuild.integrations.dap").clear_console()

Logs without using nvim-dap

If you don't want to use nvim-dap you can always print logs directly to your terminal by calling (from your root directory):

tail -f .nvim/xcodebuild/app_logs.log

This approach works especially well if you are using tmux.

ย 

๐Ÿšฅ Lualine Integration

You can also integrate this plugin with lualine.nvim.

Xcodebuild Lualine

See Lualine configuration
local function xcodebuild_device()
  if vim.g.xcodebuild_platform == "macOS" then
    return "๎˜ต macOS"
  end

  if vim.g.xcodebuild_os then
    return "๏„‹ " .. vim.g.xcodebuild_device_name .. " (" .. vim.g.xcodebuild_os .. ")"
  end

  return "๏„‹ " .. vim.g.xcodebuild_device_name
end

------

lualine_x = {
  { "'๏ฃ ' .. vim.g.xcodebuild_last_status", color = { fg = "Gray" } },
  { "'๓ฐ™จ ' .. vim.g.xcodebuild_test_plan", color = { fg = "#a6e3a1", bg = "#161622" } },
  { xcodebuild_device, color = { fg = "#f9e2af", bg = "#161622" } },
},

Global variables that you can use:

Variable Description
vim.g.xcodebuild_device_name Device name (ex. iPhone 15 Pro)
vim.g.xcodebuild_os OS version (ex. 16.4)
vim.g.xcodebuild_platform Device platform (macOS or iPhone Simulator)
vim.g.xcodebuild_scheme Selected project scheme (ex. MyApp)
vim.g.xcodebuild_test_plan Selected Test Plan (ex. MyAppTests)
vim.g.xcodebuild_last_status Last build/test status (ex. Build Succeeded [15s])

ย 

๐Ÿงช Code Coverage

Xcodebuild Code Coverage Report

See how to configure Using xcodebuild.nvim you can also check the code coverage after running tests.
  1. Make sure that you enabled code coverage for desired targets in your test plan.
  2. Enable code coverage in xcodebuild config:
code_coverage = {
  enabled = true,
}
  1. Toggle code coverage :XcodebuildToggleCodeCoverage or :lua require("xcodebuild.actions").toggle_code_coverage(true).
  2. Run tests - once they're finished, code coverage should appear on the sidebar with line numbers.
  3. You can jump between code coverage marks using :XcodebuildJumpToPrevCoverage and :XcodebuildJumpToNextCoverage.
  4. You can also check out the report using :XcodebuildShowCodeCoverageReport command.

The plugin sends XcodebuildCoverageToggled event that you can use to disable other plugins presenting lines on the side bar (like gitsigns). Example:

vim.api.nvim_create_autocmd("User", {
  pattern = "XcodebuildCoverageToggled",
  callback = function(event)
    local isOn = event.data
    require("gitsigns").toggle_signs(not isOn)
  end,
})

Coverage Report Keys:

Key Description
enter or tab Expand or collapse the current node
o Open source file

ย 

๐Ÿ“ธ Snapshot Tests Preview

This plugin offers a nice list of failing snapshot tests. For each test it generates a preview image combining reference, failure, and difference images into one. It works with swift-snapshot-testing library.

Run :XcodebuildFailingSnapshots to see the list.

Xcodebuild Snapshots

ย 

๐Ÿ‘จโ€๐Ÿ’ป API

If you want to use functions directly instead of user commands, then please see xcodebuild.actions module.

ย 

๐Ÿงฐ Troubleshooting

Important

The first thing you should do is to check the output of :checkhealth xcodebuild and fix all issues.

Run it from your project root directory.

Configuration

Processing the project configuration is a very complex task that relies on parsing multiple crazy outputs from xcodebuild commands. Those logs are a pure nightmare to work with. This process may not always work.

In case of any issues with, you can try manually providing the configuration file .nvim/xcodebuild/settings.json in your root directory.

See a sample settings.json file
{
  "bundleId": "com.company.bundle-id",
  "show_coverage": false,
  "deviceName": "iPhone 15",
  "destination": "28B52DAA-BC2F-410B-A5BE-F485A3AFB0BC",
  "config": "Debug",
  "testPlan": "YourTestPlanName",
  "projectFile": "/path/to/project/App.xcodeproj",
  "scheme": "App",
  "platform": "iOS Simulator",
  "productName": "App",
  "projectCommand": "-workspace '/path/to/project/App.xcworkspace'",
  "xcodeproj": "/path/to/project/App.xcodeproj",
  "lastBuildTime": 10,
  "os": "17.2",
  "appPath": "/Users/YOU/Library/Developer/Xcode/DerivedData/App-abafsafasdfasdf/Build/Products/Debug/App.app"
}
  • platform - macOS or iOS Simulator
  • destination - simulator ID
  • projectFile / projectCommand - can be xcodeproj or xcworkspace, the main project file that you use

Tests

If you encounter issues with test detection, you may want to read this: Test File Search - File Matching.

LSP

In most cases, it's enough to run the project in Xcode, clean it CMD+Shift+K, build again CMD+B, and run xcode-build-server config again.

Useful Help Tags

  • :h xcodebuild
  • :h xcodebuild.config
  • :h xcodebuild.keys
  • :h xcodebuild.tools
  • :h xcodebuild.commands
  • :h xcodebuild.events
  • :h xcodebuild.highlights
  • :h xcodebuild.dap

More Repositories

1

Swift-MVVMC-Demo

Sample iOS application in Swift presenting MVVM-C architecture
Swift
183
star
2

SwiftUI-Redux-Demo

SwiftUI application presenting Redux architecture and its mindblowing possibilities
Swift
55
star
3

ios-dev-starter-nvim

Bootstrap for iOS development in Neovim + LazyVim
Lua
52
star
4

Swift-MVVMC-SimpleExample

Simple example of MVVM pattern and MVVM with Coordinators
Swift
49
star
5

WidgetKit-Demo

Sample iOS project with iOS 14 widgets
Swift
21
star
6

SwiftBluetooth

Implementation of Bluetooth Low Energy communication using Flow Controllers to make asynchronous code clean
Swift
19
star
7

Sample-Projects

This repository contains my sample projects in C# for Windows Desktop and Windows Phone.
C#
16
star
8

Library-Manager

Simple desktop application written in C# (WPF) to manage a library.
C#
12
star
9

NugetAcknowledgementExporter

Exports automatically acknowledgements for all Nuget Packages included in .NET projects
C#
7
star
10

iCloud-Demo

Sample iOS project showing how to implement and use iCloud services.
Swift
7
star
11

CoreDataVsRealm

Sample usage of Core Data and Realm
Swift
6
star
12

RxBluetoothDemo

RxBluetoothKit pairing demo
Swift
6
star
13

ILTools

Simple Common Intermediate Language (IL) structure parser + viewer + obfuscator
C#
3
star
14

WKFramework

Small framework written in C#. Still working on it, so for now only settings, navigation and some utils are available.
C#
3
star
15

ReSwiftDemo

Swift
2
star
16

Algorithms

Repository contains my implementations of some algorithms and data structures.
C++
2
star
17

SPM-Sharing-Dependencies

This repository shows how to share dependencies between modules
Swift
1
star
18

Swift-RTFD-Bug

This bug shows an inconsistency in RTFD serialization.
1
star
19

DanceFloor

This game has been created to practice C# WPF. It's a simplified version of StepMania.
C#
1
star
20

Swift-Crazy-iBugs

Set of crazy bugs that I discovered on iOS, iPadOS, and macOS.
Swift
1
star