How can we write an alfred workflow to open a file from finder to a vim editor?
This is my first attempt to create a workflow in Alfred.
I am still learning and wanted to start with a simple workflow.
Here, I first created Hotkey and Keyword.
Open the Alfred3
Go to Workflows
Click + sign at the bottom left sidebar
Choose Blak Workflow
Name: Vim Launcher
Description: Opens a file in the terminal inside vim editor
1. Right-click > Trigger > press cmd-alt-v
2. Right-click > Inputs > Keyword > open in vim and title also open in vim
3. Right-click > Actions > Run NSAppleScipt
The copy and paste following contents inside Run NSAppleScipt
on alfred_script(q)
tell application "Terminal"
activate
do script "vim '" & q & "'"
end tell
end alfred_script
This workflow works but opens two terminals instead of one.
How can we fix this make so that it opens only one window?
The workflow summary is given below.
You want a Terminal Command action.
Just connect this object to your triggers and use vim "{query}" on it.
EDIT:
I'm editing the answer to reply a comment asking a follow-up question:
The workflow now create new termnial for each file, can we make it open in the same terminal if a terminal is already running?
In this case the Run NSAppleScript object could be used with the difference that we have to specify a location where do script should run, since it always open a new window if no location is specified:
on alfred_script(q)
tell application "Terminal"
if not (exists window 1) then reopen
activate
do script "vim '" & q & "'" in window 1
end tell
end alfred_script
Related
There are many posts that explain how to drag-and-drop things into an open Terminal window. But what I would like to do is to tell Terminal to drag-and-drop a previously selected directory onto another application like VSCode or Renamer. I have not found any documentation for that. Is it at all possible? And if so, would somebody please point me to a documentation?
UPDATE:
I'd like to clarify my question with what I intend to do:
Pre requisites:
a "work folder" contains folders and files that shall be renamed
the renaming is done by an application called "A better finder renamer" (which allows presets)
An "Automator" (MacOS app) action shall imitate these steps:
the "work folder" is right clicked
the folder is drag-and-dropped onto the ABFR, which initiates the currently active preset
other actions via bash (like 'mv .//.* ./') ...
It is the "drag-and-drop" part of the Automator action that presents a riddle for me.
The "drag-and-drop" operation is manual operation. In AppleScript, instead the command to open the file or folder is given to the destination application itself.
Second thing to keep in mind. Getting Terminal's current working directory is easy with its do script "pwd" command. But the result of the do script Terminal command returned to the script is always the window tab, not the result of the pwd shell command. One solution is to redirect (remember) the result of pwd in a temporary text file.
set tempFolder to (path to temporary items folder from user domain)
set temp to POSIX path of tempFolder & "workingDirectory.txt"
tell application "Terminal" to do script ("pwd > " & temp) in selected tab of window 1
set curDirPosixPath to paragraph 1 of (read file ((tempFolder as text) & "workingDirectory.txt"))
set curDirHFSPath to curDirPosixPath as POSIX file as Unicode text
tell application "Visual Studio Code" to open curDirHFSPath
.
NOTE: other possible solution (I don't like) is parsing the text contents of Terminal window after pwd command execution. You can get contents using property contents (of selected tab of front window).
Open Automator, choose create New Document.
Choose create new Quick Action (service).
Set workflow receives current folders in any application.
From library Add Run AppleScript action. Edit it contents:
on run {input, parameters}
set curDirHFSPath to (item 1 of input) as text
tell application "Visual Studio Code" to open curDirHFSPath
end run
Save this Quick Action as service. Now when right-clicking the folder, opens the context menu, where you can choose and run this service.
Is there a way to make NeoVim as default text/code editor (without any bad side effects) ?Trust me, I looked to lots of StackOverflow question/answers and tried a few things but nothing worked for me.
Note: I'm on macOS Big Sur (version 11.2.1). What I want is when I click on files to open in NeoVim.
--> For example, in ~/.zshrc (and added to ~/.bash_profile also just in case) I have:
Note: zsh is my default shell
alias nvim=$HOME/nvim-osx64/bin/nvim
export EDITOR="nvim"
export VISUAL="nvim"
When I do set in Terminal it shows:
EDITOR=nvim
VISUAL=nvim
And yes, I quit and started the terminal (I'm using iTerm2). I even reboot.
--> I will place my $PATH here just in case it has anything to do it that. When I do echo $PATH it shows:
--> And, just in case someone suggests:
I can't Select a File > Open With... and select NeoVim as default text editor, since that option doesn't show and I can't do Choose Other since I can't select NeoVim in that way.
If anyone needs more information, please say and I will edit the question with that info. Thanks!
Setting variables in the terminal will not affect the GUI file associations. To do that you have to change the OS's file associations.
Though it appears to be a small project and unsupported, I've had a good experience using duti. It's a wrapper around the Apple file extension API. The configuration did take me a minute to figure out. I'll post it if I can find it.
After a while I found the answer to my own question, here it is how you can set NeoVim in Mac as the default text editor. Now, you will be able click on files and opening them in NeoVim:
Some people recommended me to have a look at the follow links:
https://gist.github.com/Huluk/5117702
https://superuser.com/questions/139352/mac-os-x-how-to-open-vim-in-terminal-when-double-click-on-a-file
That didn't work for me but it served as a reference to look up related topics (automator + neovim).
After a while, I discover this blog:
https://blog.schembri.me/post/neovim-everywhere-on-macos/
Go and have a look at the blog, but here it is how you do it:
Launch Automator (Finder -> Applications -> Automator)
New Document -> Choose a type for your document: Application
In Actions search for Run AppleScript and drag that to where it says something like "Drag actions here..."
Delete the default example of AppleScript
Copy and Paste the code in the blog (where it says NeoVim.app) to where it previous had the default code
Save the new Automator app (save as aplicattion format). Save it in the Applications folder
Right-Click a file type you wish to open every time you click on them (e.g. .php file). Select Get Info or do cmd + i, it will open informations about that file. Scroll to wher it says Open With and select Other. Then just go to Aplicattions folder and select your new NeoVim "app".
Do the same to other file types if you wish.
You can now double click on your PHP files (or others if you did the same) and open them in NeoVim. Enjoy!
Note: You really need to do Right-Click, Get Info and look for Open With to change in all files with that extension. If you skip Get Info and just Right-Click + Open With, it will only work for that specific file...
This is the code from the blog:
on run {input, parameters}
set cmd to "nvim"
if input is not {} then
set filePath to POSIX path of input
set cmd to "nvim \"" & filePath & "\""
end if
tell application "iTerm"
create window with default profile
tell the current window
tell the current session to write text cmd
end tell
end tell
end run
This would open a new window even if you already had one open.
I change it so that it would open in a tab:
on run {input, parameters}
set cmd to "nvim"
if input is not {} then
set filePath to POSIX path of input
set cmd to "nvim \"" & filePath & "\""
end if
tell application "iTerm"
tell the current window
create tab with default profile
tell the current session to write text cmd
end tell
end tell
end run
Note: I'm using iTerm2. If you are using another Terminal Emulator, change where it says iTerm to the name of your terminal...
For anyone using Kitty on MacOS, I found a pretty simple way to accomplish this using the remote control feature.
First you need the following set in your kitty.conf:
allow_remote_control yes
listen_on unix:/tmp/mykitty
Using Automator like in #DGF's answer, I created an Application with the "Run Shell Script" action, and this is the script:
if [ -z "$(pgrep kitty)" ]
then
open /Applications/kitty.app
sleep 3 # allow ample time to startup and start listening
fi
/usr/local/bin/kitty # --to=unix:/tmp/mykitty-$(pgrep kitty) launch --type=os-window nvim "$#"
Save that as an application somewhere, and select it from "Open with"!
Note: to be honest, the logic to handle starting up kitty if it's not already running is a little flaky. But it seems to work great when kitty is already running, which of course it is most of the time for me. Also, it doesn't work at all if kitty is running but has no windows. :\
Choose nvim as the default application by means of a txt file sub-menu like here with Preview for PDFs:
Probably a minor syntax issue that I'm getting wrong, but can't find the solution in the ITerm2 documentation. I'd like to create an applescript that opens an ITerm window with three tabs, each running various shell commands (ls, cd, echo, etc.) with the tab the remaining open after those commands have run. The opening tabs part is working fine, but it appears that as soon as the commands run, the tab closes (if I don't provide any commands, the tab will remain open.) For my script here:
tell application "iTerm2"
create window with default profile
tell current window
create tab with default profile command "echo abc"
create tab with default profile
end tell
end tell
Instead of "echo abc" what should I put there so the echo command will run in the tab, but leave me with a cursor for me to type in more commands instead of the tab immediately closing thereafter?
Instead of using the create tab ... command, use a separate write text command. For example, this is a script I use to open a terminal to a specific directory:
tell application "iTerm"
create window with default profile
tell current session of current window
write text "cd " & directory & "; clear"
end tell
end tell
Using the "write text" suggested by whereswalden I settled on the following, works well:
tell application "iTerm2"
create window with default profile
tell current window
tell current session
write text "echo abc"
end tell
create tab with default profile
tell current session
write text "ls -la"
end tell
create tab with default profile
tell current session
write text "cd mydir"
end tell
end tell
end tell
I need to do a .command file script/batch. Launching it (double-click) it has to to those things:
Open a terminal window (A)
Launching a command that open the folder where the file is (maybe this cd "dirname "$0"")
Launch a command
Open a terminal window (B)
Launching same command at point 2
Launch a command
Given that you explicitly want to create terminal windows, consider creating an application using AppleScript:
Open Script Editor (up to 10.9, AppleScript Editor)
Paste the code below.
Save as an application (via the pop-up list in the Save As dialog) to the desired folder.
# Determine the folder in which this app is located.
set thisFolder to do shell script "dirname " & quoted form of POSIX path of (path to me)
# Sample commands to execute in the new windows.
set cmds to {"date", "echo $$"}
tell application "Terminal"
# Create 2 new windows, change to the
# this app's folder, and execute the respective command.
repeat with i from 1 to 2
do script "cd " & quoted form of thisFolder & "; " & item i of cmds
end repeat
# Activate Terminal.app
activate
end tell
The reason that I recommend using an application over a *.command file is that the latter would itself open in a Terminal window first, before creating the desired windows, which is visually disruptive (and, depending on your Terminal.app preferences, may leave the extra window open).
Alternatively, you could turn that into a virtue and use the *.command file's own window as your 1st terminal window, and only create one additional one.
Is there a way to close a Terminal window from within a shell script? I have a .command file that should just get out of the way once it's done.
Using exit 0 will cleanly terminate the script.
Whether Terminal window stays open is user-configurable. The default is to always stay open. To change this:
Terminal.app > Preferences > Profiles > Shell
- "When the shell exists:"
> Close if the shell exited cleanly
- "Ask before closing:"
(•) Never
-- OR --
(•) Only if there are....
When "Close if shell exited cleanly" is used, the script will close the window if the exit result is 0, which is the default if nothing went wrong.
Since you don't want to delete all Terminal windows, first change the name of your window from "Terminal" to something else:
echo -n -e "\033]0;My Window Name\007"
Then at the end of the script, use:
osascript -e 'tell application "Terminal" to close (every window whose name contains "My Window Name")' &
You can use apple script to quit the terminal app. Add the following to your script -
osascript -e 'tell application "Terminal" to quit'
This will give you a popup confirming to close the app. You can disable this in Terminal preferences.
Alternatively, you can also use killall command to quit the app. The following would work just as well.
killall Terminal
Note:
Just as a side note, you can freely add the above commands to your script and it would work as you want. However, there are few caveats. First being you will limit the ability of your script to work on different boxes. Secondly, it would be safer to use nohup so that any commands that are currently running won't quit due to quitting of the Terminal app.
This works for me:
#!/bin/sh
{your script here}
osascript -e 'tell application "Terminal" to close (every window whose name contains ".command")' &
exit
This will work for closing just your windows opened with a .command file but leave things already running in other terminal windows. I know that I almost always have either sass or grunt watch something so I don't want to quit terminal totally.
closeWindow() {
/usr/bin/osascript << _OSACLOSE_
tell application "Terminal"
close (every window whose name contains "YourScriptName")
end tell
delay 0.3
tell application "System Events" to click UI element "Close" of sheet 1 of window 1 of application process "Terminal"
_OSACLOSE_
}
This will close the Terminal window for your script and keep any other Terminal windows open as long as their window titles don't match. For it to work Terminal will have to be added to the list of applications permitted to use the Accessibility framework. You can also cycle through Terminal windows with a repeat command and close every window x that contains a UI element "Close" on sheet 1.
I find the best solution for this is to use Automator to create a true OSX application which will work the same way regardless of how your system is configured. You can have the Automator run your shell script, or you can embed the shell script itself in Automator.
Here is how you do it:
Run Automator (in Applications).
Choose "New Document" and when it
asks "Choose a type for your document" choose "Application"
In the
left panel, select "Utilities" then "Run Shell Script".
Type in your
script commands in the workflow item in the right panel. You can either call another
shell script, or just put your commands in their directly.
Save the
Application, which will be a full-fledged Mac App. You can even
cut-and-paste icons from other apps to give your script some
personality.
#!/bin/bash -x
{your script here}
. exit 0
kill -9 $PPID
you can also create a shortcut for your script:
cp yourscript.sh ~/bin/yourshortcutnamewhateveryouwant
then type
yourshortcutnamewhateveryouwant
will run whatever is writen into script at any directory.