From 842cd7e2a8340e05206c51d625789c9e54c9bad9 Mon Sep 17 00:00:00 2001 From: Yee Cheng Chin Date: Wed, 15 Mar 2023 15:50:41 -0700 Subject: [PATCH] Fix :hardcopy not working in macOS 13 Ventura MacVim's `:hardcopy` implementation just uses Preview to show the generated PostScript file and lets the user decide what to do with it. macOS 13 Ventura removed PostScript support from Preview, so we now have to manually convert it to PDF first using `pstopdf` (which is thankfully bundled with macOS). While we are at it, update the script so that we actually delete the file after sending it to Preview. Previously MacVim never did that and therefore leaks the file in a temp folder until Vim closes, which isn't ideal for privacy. Now, just set a 10 sec timer to delete the file after it's opened (we just need enough time to allow Preview to open and load the file, which doesn't take much time. The 10 sec timer is to account for slow computers). Fix #1347 --- runtime/autoload/macvim.vim | 39 ++++++++++++++++++++++++++++++++++++- runtime/doc/gui_mac.txt | 4 ++-- runtime/doc/print.txt | 11 +++++++++-- src/MacVim/gvimrc | 5 ++--- 4 files changed, 51 insertions(+), 8 deletions(-) diff --git a/runtime/autoload/macvim.vim b/runtime/autoload/macvim.vim index da8396a49a..05a7344c9f 100644 --- a/runtime/autoload/macvim.vim +++ b/runtime/autoload/macvim.vim @@ -1,7 +1,7 @@ vim9script # Support scripts for MacVim-specific functionality # Maintainer: Yee Cheng Chin (macvim-dev@macvim.org) -# Last Change: 2022-10-14 +# Last Change: 2023-03-15 # Retrieves the text under the selection, without polluting the registers. # This is easier if we could yank, but we don't know what the user has been @@ -76,4 +76,41 @@ export def ShowDefinitionUnderCursor() endif enddef +# Print functionality. We simply show the file in Preview and let the user +# decide what to do. This allows for more control instead of immediately +# piping the file to lpr which will actually print the file. +# +# PreviewConvertPostScript: +# Convert the provided PostScript file to PDF, then show in Preview. This is +# necessary in macOS 13+ as Preview doesn't support .ps files anymore. +# PreviewPostScript: +# Directly open PostScript file in Preview. Can use this if +# PreviewConvertPostScript doesn't work. +export def PreviewConvertPostScript(deltimer = 10000): number + # Convert PS to PDF because Preview can't use PS files in macOS 13+ + system($"pstopdf {v:fname_in} -o {v:fname_in}.pdf") + if v:shell_error != 0 + return v:shell_error + endif + system($"open -a Preview {v:fname_in}.pdf") + delete(v:fname_in) + + # Delete the file after it's opened in Preview for privacy. We don't have an + # easy way to detect that Preview has opened the file already (unless we use + # `open -W` which will stall Vim), so we just use a generous 10 secs timer. + var to_delete_file = $"{v:fname_in}.pdf" + timer_start(deltimer, (timer) => delete(to_delete_file)) + + return v:shell_error +enddef + +export def PreviewPostScript(deltimer = 10000): number + system($"open -a Preview {v:fname_in}") + + var to_delete_file = v:fname_in + timer_start(deltimer, (timer) => delete(to_delete_file)) + + return v:shell_error +enddef + # vim: set sw=2 ts=2 et : diff --git a/runtime/doc/gui_mac.txt b/runtime/doc/gui_mac.txt index 43b6d33493..cb09c22c5e 100644 --- a/runtime/doc/gui_mac.txt +++ b/runtime/doc/gui_mac.txt @@ -930,8 +930,8 @@ prominent bugs/missing features. - Sometimes multibyte characters look "too wide", i.e. they overlap the following character. It might help to change 'ambiwidth', or override the automatic font substitution by setting 'guifontwide' manually. -- Printing. As a temporary solution creates a PostScript file which is - then opened in Preview where it may be printed. See |hardcopy|. +- Built-in printing. |:hardcopy| / creates a PDF file which is then + opened in Preview where it may be printed. See |pexpr-option|. General bugs and issues are tracked on Github. If you find new bugs or have feature requests then please file an issue there: diff --git a/runtime/doc/print.txt b/runtime/doc/print.txt index 53f17e1545..f35f3cf0a9 100644 --- a/runtime/doc/print.txt +++ b/runtime/doc/print.txt @@ -47,6 +47,8 @@ Note: If you have problems printing with |:hardcopy|, an alternative is to use paper size, duplex, etc. Note: If you want PDF, there are tools such as "ps2pdf" that can convert the PostScript to PDF. + On macOS, you can also use "pstopdf" which comes + bundled with the system. :[range]ha[rdcopy][!] >{filename} As above, but write the resulting PostScript in file @@ -136,8 +138,13 @@ The arguments to the ":hardcopy" command are in |v:cmdarg|. The expression must take care of deleting the file after printing it. When there is an error, the expression must return a non-zero number. If there is no error, return zero or an empty string. -The default for non MS-Windows or VMS systems is to simply use "lpr" to print -the file: > + +The default for MacVim is to convert the PostScript file to PDF and then open +it in Preview.app where you can print from there, using the function +`macvim#PreviewConvertPostScript()`. + +The default for other non MS-Windows or VMS systems is to simply use "lpr" to +print the file: > system('lpr' .. (&printdevice == '' ? '' : ' -P' .. &printdevice) .. ' ' .. v:fname_in) .. delete(v:fname_in) + v:shell_error diff --git a/src/MacVim/gvimrc b/src/MacVim/gvimrc index 20150308e7..ef557ec37c 100644 --- a/src/MacVim/gvimrc +++ b/src/MacVim/gvimrc @@ -32,9 +32,8 @@ if empty(&guitablabel) set guitablabel=%M%t endif -" Send print jobs to Preview.app. This does not delete the temporary ps file -" that is generated by :hardcopy. -set printexpr=system('open\ -a\ Preview\ '.v:fname_in)\ +\ v:shell_error +" Send print jobs to Preview.app. The user can then print from it. +set printexpr=macvim#PreviewConvertPostScript() " askpass let $SSH_ASKPASS = simplify($VIM . '/../../Resources') . '/macvim-askpass'