runtime(zip): Customizable zip/unzip commands - #20832
Conversation
|
this also requires an update to |
|
The default commands use let g:zip_browse= ["printf", "'';",
\ "7zlbaf() { 7z l -ba \"$@\" | awk '{print ($3 ~ /D[^[:space:]]{4}/ ? $6 \"/\" : $6)}'; }",
\ " && ", "7zlbaf"] " or save command as a file with `#!/bin/sh`
let g:zip_read= ["7z", "x", "-so"]
let g:zip_extract= ["7z", "x"]
let g:zip_delete= ["7z", "d"]
let g:zip_update= ["7z", "u"]I found that 7z behaviors different on file names with special characters, such as $ ls zipglob
'a[a].txt' 'a*.txt' 'a?.txt' 'a\.txt' 'a\\.txt'
$ wc -l 'zipglob/a*.txt'
1 zipglob/a*.txt
$ unzip -p exp.zip 'zipglob/a\*.txt' | wc -l
1
$ 7z x -so exp.zip 'zipglob/a\*.txt' | wc -l
2This means the behavior of visiting(read/write) files that contains special character in a zip file without |
Not only that, the zip/unzip command line parser is already insane. There is no sane way to handle strange characters robustly. That would mean we would need a custom escape function like what is done for powershell using |
|
I found there's no support for Windows PowerShell 5, only PowerShell Core. So the CI test fails. I'll fix it. |
When the commands to open/edit zip files are customizable, the resposibility to guarantee the correctness are transmit to the users. Based on this opinion, us developers should ensure the default behaviors are correct. |
|
As for my above example: let g:zip_browse= ["printf", "'';",
\ "7zlbaf() { 7z l -ba \"$@\" | awk '{print ($3 ~ /D[^[:space:]]{4}/ ? $6 \"/\" : $6)}'; }",
\ " && ", "7zlbaf"]This hack is not good since one more meanless command is executed. There's another example (on Windows): let g:zip_browse = ["7zlbaf"]
let g:zip_read = ["7z", "x", "-so"]
let g:zip_extract = ["7z", "x"]
let g:zip_delete = ["7z", "d"]
let g:zip_update = ["7z", "u"]while the @7z l -ba %* | awk.exe "{ gsub(/\\/, \""/\"", $6); print ($3 ~ /D[^[:space:]]{4}/ ? $6 \""/\"" : $6)}"They are still not elegant. Maybe we should provide an API to let users to format the outputs of commands, which may solve special character problem. |
|
so you think this is worthwhile? or shall we rather drop it? |
There was a problem hiding this comment.
Pull request overview
This PR refactors Vim’s built-in zip.vim plugin to make the external zip/unzip tooling configurable (moving from single-string command variables to List-based command+args variables), and extends/clarifies the PowerShell fallback behavior on Windows. It also updates the zip plugin documentation and adjusts the zip plugin test coverage accordingly.
Changes:
- Replace hard-coded
zip/unzipoption usage with new configurable List variables (g:zip_browse,g:zip_read,g:zip_extract,g:zip_delete,g:zip_update). - Add a new
g:zip_pwshknob and internal selection logic to support both Windows PowerShell andpwsh. - Update
pi_zip.txtdocs andtest_plugin_zip.vimto match the new configuration model and fallback behavior.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 4 comments.
| File | Description |
|---|---|
| src/testdir/test_plugin_zip.vim | Updates tests for new List-based command variables and adds Windows/PowerShell-related coverage. |
| runtime/doc/pi_zip.txt | Documents the new configuration variables and updated PowerShell fallback behavior. |
| runtime/autoload/zip.vim | Implements new configurable command lists, adjusts GNU/PowerShell execution flow, and adds g:zip_pwsh selection logic. |
Comments suppressed due to low confidence (6)
runtime/autoload/zip.vim:130
- s:SafeExecutable() checks executable(g:zip_update[0]) instead of the passed-in executable (a:exe). This makes zip.vim abort on systems without "zip" even when only "unzip" is needed (e.g. browsing/reading), and defeats the per-command checks for g:zip_browse/read/extract.
if !executable(g:zip_update[0]) && !s:isPS()
runtime/autoload/zip.vim:110
- echohl will error for unknown highlight groups; "Note" is not a standard group. Use an existing group (e.g. MoreMsg) to avoid E411 when &shell is cmd.exe.
call s:Mess('Note', "***note*** (zip) you can set shell option or `g:zip_pwsh` to enable powershell fallback")
runtime/autoload/zip.vim:423
- The zip#Write() missing-executable error message incorrectly labels itself as (zip#Read), which is confusing when troubleshooting.
call s:Mess('Error', "***error*** (zip#Read) sorry, your system doesn't appear to have the ".join(g:zip_update)." program")
runtime/autoload/zip.vim:506
- This redraw is only needed when PowerShell is used (see the comment about PowerShell ProgressAction output). The current condition runs it when PowerShell is NOT used.
if !s:isPS()
src/testdir/test_plugin_zip.vim:25
- This test mutates the global 'shell' option but never restores it, which can leak state into subsequent tests. Prefer configuring the new g:zip_pwsh knob for the PowerShell fallback, or save/restore &shell.
### Windows OS: PowerShell fallback should be manually set up
if &shell =~? 'cmd'
set shell=powershell
endif
runtime/doc/pi_zip.txt:84
- Minor punctuation/wording issues in the updated PowerShell fallback description (extra space before comma, and missing double-space after the sentence) reduce readability and don't match typical help style.
using PowerShell , the plugin will fall back to a PowerShell cmdlet.
The PowerShell cmdlets are limited: they cannot write or extract files
within subdirectories of a zip archive. The advantage, however, is that
no separate unzip binary needs to be installed. The 'shell' option will
be checked whether to choose "pwsh" or "powershell", or use 'g:zip_pwsh'
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| ### Windows OS: PowerShell fallback should be manually set up | ||
| if &shell =~? 'cmd' | ||
| set shell=powershell | ||
| endif |
There was a problem hiding this comment.
So I added a function below g:Test_zip_windows_powershell().
I thnk at least (runtime(zip): Compatability for both powershell 5 and pwsh 7) is meaningful. |
I tested providng a new API on my device (which is not committed): if !exists("g:zip_browse_format")
let g:zip_browse_tailcmd= [""]
endif
" ...
let gnu_cmd = 'keepj sil r! ' . join(g:zip_browse) . ' ' . s:Escape(a:zipfile, 1) . ' ' . join(g:zip_browse_tailcmd)And the configuration becomes to(on Windows): let g:zip_browse = ["7z l -ba"]
let g:zip_browse_format = ["|", "awk", "'" . '{ gsub(/\\/, \\\"/\\\", $6); print ($3 ~ /D[^[:space:]]{4}/ ? $6 \\\"/\\\" : $6) }' . "'"]It's kind of painful to debug to right codes because of escape characters. Or provide a customizable function So do not provide this API is better. Users can do some hack on the new global variables ( |
|
Okay. I merged in The thing I do not like about the new variables is, that you are changing the default types to a list. That will bite each user who has been customizing those variables, so I left that out. Have a look at it and see if this works for you. Thanks! |
related: #20832 Co-Authored-By: curbe454 <asu454@outlook.com> Signed-off-by: Christian Brabandt <cb@256bit.org>
… 5 and pwsh 7 related: vim/vim#20832 vim/vim@b0e0b22 Co-authored-by: curbe454 <asu454@outlook.com> Co-Authored-By: curbe454 <asu454@outlook.com>
runtime(zip): Improve Compatibility for powershell 5 and pwsh 7 related: vim#20832 Co-Authored-By: curbe454 <asu454@outlook.com> Signed-off-by: Christian Brabandt <cb@256bit.org>
I'm glad to know your attitude to destructive changes. But my original purpose is to introduce customizable zip/unzip commands. I found a hard encoding issue, then found this API is not reasonable. Line 252 in 975e191 If anyone configure to If destructive changes are not expected, we can cosider another way to implement the functionality. For example, expose more variables. Lines 59 to 81 in 1068ea2 |
|
Well, the other alternative would be to use vim variarbles, that are set by the existing variables if those exists, something like this: if !exists('g:zip_zipcmd_list')
if exists('g:zip_zipcmd')
let g:zip_zipcmd_list = [g:zip_zipcmd, '-d']
else
let g:zip_zipcmd_list = ['zip', '-d']
endif
endif |
… 5 and pwsh 7 related: vim/vim#20832 vim/vim@b0e0b22 Co-authored-by: curbe454 <asu454@outlook.com> Co-Authored-By: curbe454 <asu454@outlook.com>
… 5 and pwsh 7 related: vim/vim#20832 vim/vim@b0e0b22 Co-authored-by: curbe454 <asu454@outlook.com> Co-Authored-By: curbe454 <asu454@outlook.com>
I'd like to change another program other than
zip/unzipto open a zip file such as7z.According to the doc, I changed the global variable
g:zip_unzipcmdin my.vimrc:It didn't work. This is because this plugin is primarily only for these two
zipandunzipbinary executable files, with some CLI options hard encoded. For example, this below codes inruntime/autoload/zip.vim:In this pr, these hard coded options are eliminated, so that users can choose their program to open
.zipfiles.