Skip to content

Commit

Permalink
Fix :hardcopy not working in macOS 13 Ventura
Browse files Browse the repository at this point in the history
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
  • Loading branch information
ychin committed Mar 18, 2023
1 parent 988f8b5 commit e3a5374
Show file tree
Hide file tree
Showing 4 changed files with 54 additions and 8 deletions.
42 changes: 41 additions & 1 deletion runtime/autoload/macvim.vim
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -76,4 +76,44 @@ 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, so we just
# use a generous 10 secs timer.
# Note that we can't use `open -W` instead because 1) it will block
# synchronously, and 2) it will only return if Preview.app has closed, which
# may not happen for a while if it has other unrelated documents opened.
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 :
4 changes: 2 additions & 2 deletions runtime/doc/gui_mac.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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 <D-p> creates a PostScript file which is
then opened in Preview where it may be printed. See |hardcopy|.
- Built-in printing. |:hardcopy| / <D-p> 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:
Expand Down
11 changes: 9 additions & 2 deletions runtime/doc/print.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
5 changes: 2 additions & 3 deletions src/MacVim/gvimrc
Original file line number Diff line number Diff line change
Expand Up @@ -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'
Expand Down

0 comments on commit e3a5374

Please sign in to comment.