Use NeoVim anywhere on OSX
I often want to use NeoVim outside the terminal, when writing emails or notes. Luckily, I found Jamie Schembri’s post NeoVim everywhere on MacOS. I have made a few improvements with regards to stability and ““stability””.
‘Edit in NeoVim’ service
This workflow takes as input the current selection and outputs the text to replace it. It uses iTerm2 and NeoVim to edit the text.
If you haven’t used Automator before, I recommend following the official guide hon how to create a Quick Action workflow. You’ll want to set Workflow receives current to “text” and check the box Output replaces selected text. Then add a Run AppleScript action to the workflow with the below code.
on readFile(unixPath)
set fileDescriptor to (open for access (POSIX file unixPath))
set theText to (read fileDescriptor for (get eof fileDescriptor) as «class utf8»)
close access fileDescriptor
return theText
end readFile
on writeTextToFile(theText, filePath, overwriteExistingContent)
try
-- Convert the file to a string
set filePath to filePath as string
-- Open the file for writing
set fileDescriptor to (open for access filePath with write permission)
-- Clear the file if content should be overwritten
if overwriteExistingContent is true then set eof of fileDescriptor to 0
-- Write the new content to the file
set theText to theText as string
write theText to fileDescriptor starting at eof as «class utf8»
-- Close the file
close access fileDescriptor
-- Return a boolean indicating that writing was successful
return true
-- Handle a write error
on error errMessage
-- Close the file
try
close access file theFile
end try
display alert "Failed to write to file" message "Failed to write to file " & theFile & ": " & errMessage
-- Return a boolean indicating that writing failed
return false
end try
end writeTextToFile
on run {input, parameters}
-- Save the frontmost application for later.
tell application "System Events"
set activeProc to first application process whose frontmost is true
end tell
-- Write the selected text (input) to a temporary file.
set tempfile to do shell script "mktemp -t edit-in-vim"
if writeTextToFile(input, tempfile, true) is false then
-- Failed to write the input to the file. The function has already
-- displayed an error message, so let us just return the input unaltered.
return input
end if
-- Edit that temporary file with Neovim under iTerm2.
tell application "iTerm2"
-- If General>Closing>'Quit when all windows are closed' is enabled,
-- this will create two windows if iTerm2 was previosly closed.
--
-- We use a custom profile (with a descriptive name) to reduce the
-- risk of idiot Linus accidentally breaking something by changing
-- the default profile.
create window with profile "Rediger i Neovim (brugt af workflow)"
tell the current window
tell the current session
-- Edit the file using Neovim. We set 'nofixeol' to avoid inserting
-- extraneous linebreaks in the final output. We also set 'wrap' since
-- we seldom want to rewrite as we often don't want to manually break
-- lines in MacOS input fields.
write text "nvim -c 'set nofixeol' \"" & tempfile & "\""
-- Wait for the editing process to finish.
-- This requires shell-integration to be enabled.
delay 0.5
repeat while not is at shell prompt
delay 0.2
end repeat
end tell
-- Close the window we just created so it doesn't clutter up the desktop.
close
end tell
end tell
-- Switch back to the previously active application.
tell application "System Events"
set the frontmost of activeProc to true
end tell
-- The new text is stored in tempfile.
return readFile(tempfile)
end run
The functions readFile
and writeFile
come from the Mac Automation Scripting Guide.
Do beware that the original writeFile
linked before doesn’t handle Unicode text properly.
The code for restoring the focused application was taken from a patch on the pass
mail archives.
Neovim as a standalone application.
This next snippet wraps NeoVim in a proper Application™. Doing this means it will be recognized by MacOS in various places. For example, when opening files in Finder it is now possible to choose NeoVim. I have set it as the default for all markdown files on my computer.
A more robust – and probably all around better solution – would be to use VimR. I have yet to test it, but I might replace this script with VimR in the future.
on run {input, parameters}
if input is not {} then
set filePath to POSIX path of input
set cmd to "nvim \"" & filePath & "\""
else
set cmd to "nvim"
end if
tell application "iTerm2"
create window with default profile
tell the current window
tell the current session
write text cmd
-- Wait for command to finish.
repeat while not is at shell prompt
delay 0.2
end repeat
end tell
close
end tell
end tell
end run