[O]pen Read-only, (E)dit anyway, (R)ecover, (Q)uit, (A)bort
是否有一些内置的方式来引发实例,例如在GUI /终端中,以保存打开的文件?理想情况下,将有问题的文件放到前台(如果有多个缓冲区)。
到目前为止,我正在使用bash脚本,该脚本从swap提取PID,检查该PID是否属于Vim,如果使用,则使用
wmctrl
升高窗口。尽管这很好用,但至少对于GUI和X11 Linux而言,我在问是否还有一种更本地的方法。#1 楼
一种解决方案是每个项目使用一个vim实例,除非您的多个项目有重叠的文件,否则这将避免此问题。我假设您正在寻找一种自动化的解决方案,而不是建议您更改行为。
FocusLost可能有另一种解决方案
FocusLost自动命令事件在GUI Vim和某些控制台终端中起作用。您可以,而不是切换到已打开的vim版本中的文件(如果您使用多个GUI窗口,则该文件是乱七八糟的),则可以保留未在其他vim实例中编写的任何更改都不会丢失(a单独的git分支,保存然后撤消,使其处于撤消树中,或者干脆将其保存),并在新实例中将其打开,并指出之前已将其打开。
另一个潜在有用的自动命令事件是SwapExists,在vim 7中可用,它表示该文件存在交换文件,即IE已打开。 tmux或屏幕,可能有一种方法可以切换到适当的窗口/窗格。
简短的github搜索也会显示https://github.com/lynnard/editexisting.vim,它似乎可以正常工作适用于Xmonad之类的特定窗口管理器。
#2 楼
长期丢失并且几乎被遗忘。只能重构代码等,但是发布是不变的。此代码在32位系统上使用。不确定在64位(或其他)上的运行方式。
在某处也有C代码的入侵(提取PID)。
将其保留为任何人都可以修改的帖子。我当前的脚本总体而言(使用
pid
作为选项,鉴于其“ GUI-PID /程序”以及使用wmctrl -l -p
等,它应该可以在任何GUI上运行):#!/bin/bash
# Please leave in place:
# http://vi.stackexchange.com/q/562/220
declare -i debug=1
declare -i pid=0
opt=j
# Usage
usage()
{
printf "Usage: %s [[opt] <PID>] | [[opt] <SWP>]\n" "${0/*\//}"
printf "\nopt:\n"
printf " j : Jump to window. (Default)\n"
printf " g : Get window. (E.g. from other workspace.)\n"
printf " l : List windows.\n"
printf " p : Only print. (With some extra info.)\n"
printf " s : Alias for j. (switch)\n"
printf " i : Alias for p. (information)\n"
printf " h : This help.\n"
printf "\n"
printf " <PID>: Process ID.\n"
printf " <SWP>: Read PID from Vim swap file.\n"
if (($#)); then
printf "\nERR: Unknown option %s\n" ""
fi
}
# Check if PID is a (G)Vim process
check_vim_pid()
{
local comm=
if ! [[ "" =~ ^[0-9]+$ ]];then
printf "ERR: Some weird thing has happened (P: ).\n" >&2
exit 1
fi
comm="$(ps -p -o comm=)"
[[ "$comm" =~ ^g?vim$ ]] && return 0 || return 1
}
# First two bytes should be b0, bc or bC
# Or in hex 0x6230, 0x6263 or 0x6243
check_b0()
{
local b01="${1:0:2}"
local b02="${1:2:2}"
if [[ $b01 != '62' ]] ||
([[ "$b02" != '30' && "$b02" != '63' && "$b02" != '43' ]]); then
return 1
fi
return 0
}
# Read PID from swap file.
# Se notes below for information.
vim_file=""
vim_swp_pid()
{
local swp=""
if ! [[ -r "$swp" ]]; then
printf "ERR: Not able to read $swp.\n" >&2
exit 2
fi
# Read b0 ID
local b0_id="$(xxd -l 2 -p "$swp")"
if ! check_b0 "$b0_id"; then
printf "ERR: Bad b0 ID in file (Not Vim-swap?): %s\n" "$b0_id" >&2
exit 3
fi
# Read PID from .swp file
local -a opid=($(xxd -s 24 -l 4 -p -c 1 "$swp"))
# Read int magic from .swp file
local magic=$(xxd -s 1008 -l 8 -p "$swp")
if [[ "${magic:0:8}" == "33323130" ]]; then
# Intel (LittleEndian)
pid=$(printf "%d" "0x${opid[3]}${opid[2]}${opid[1]}${opid[0]}")
elif [[ "${magic:0:8}" == "30313233" ]] ||
[[ "${magic:8:8}" == "30313233" ]]; then
# Motorola (BigEndian)
pid=$(printf "%d" "0x${opid[0]}${opid[1]}${opid[2]}${opid[3]}")
else
printf "ERR: Unknown byteroder: %s\n" "$magic" >&2
exit 4
fi
if ! check_vim_pid $pid; then
printf "N010: PID %d is not a Vim process.\n" "$pid" >&2
exit 10
fi
# Read file name
vim_file="$(xxd -s 108 -l 800 -ps "" | xxd -r -p)"
}
list_windows()
{
local winid desk pid host title comm
printf "%-10s %-3s %-6s %-16s %s\n" "WINID" "DSK" "PID" "COMM" "TITLE"
while IFS=$' \n' read -r winid desk pid host title; do
cf="/proc/$pid/comm"
[[ -r "$cf" ]] && read -r comm < "$cf"
printf "%10s %3d %6d %-16s %s\n" "$winid" "$desk" "$pid" "$comm" "$title"
done <<< "$(wmctrl -lp)"
}
# ------------------------- RUN -------------------------------------------- #
# Check if any arguments (a bit redundant, but OK)
if [[ -z "" ]]; then
usage >&2
exit 1
fi
# Loop arguments
while [[ "" ]]; do
if [[ "" =~ ^[0-9]+$ ]]; then
pid=
else
[[ "${1:0:1}" == "-" ]] && op=${1:1} || op=
case "$op" in
l) list_windows; exit 0;;
d) debug=1;;
h|-help) usage; exit 0;;
j|s|g|p|i) opt=$op;;
*)
if ! [[ -e "" ]]; then
usage >&2;
printf "\nE006: Can't stat \`%s'\n" "" >&2
exit 2
fi
vim_swp_pid ""
;;
esac
fi
shift
done
# Check if PID is set
if !(($pid)); then
usage >&2
printf "E011: PID required / Not found.\n" >&2
exit 11
fi
# Read WindowID, Workspace, PID of all-windows then filter by PID
read -r wid ws <<<$(wmctrl -l -p | awk -v p="$pid" ' == p {print ,"\t",}')
pikoli()
{
local pp=
while :; do
awk '/^PPid:/{print ;next}/^Name:/{print ;next}' /proc/$pp/status 2>/dev/null || return
pp=$(awk '/^PPid:/{print ;next}' /proc/$pp/status)
done
}
if ! [[ "$wid" ]]; then
pikoli $pid
printf "ERR: Window not fround from PID %d.\n" "$pid" >&2
exit 12
fi
# As most DM's names desktops from 1 and not 0, a more user-friendly number.
((dmws=ws + 1))
# Do the action!
((debug)) && printf "PID=%d, WID=%s, WS=%d\n" "$pid" "$wid" "$ws"
case "$opt" in
j|s) printf "Swithching to workspace %d raising window %s by PID %d.\n" \
"$dmws" "$wid" "$pid";
wmctrl -ia "$wid"
;;
g) printf "Getting window %s by PID %d from workspace %d.\n" \
"$wid" "$pid" "$dmws";
wmctrl -iR "$wid"
;;
i|p) printf "Window is on workspace %d having window ID %s by PID %d.\n" \
"$dmws" "$wid" "$pid";
xwininfo -id $wid
;;
esac
exit 0
#############################################################################
# ----------------- Vim swap file block zero format ----------------------- #
#############################################################################
#
# No script / bash code beyond here
#
NOTES 'memline.c:139':
:62
#define BLOCK0_ID0 'b' /* block 0 id 0 */
#define BLOCK0_ID1 '0' /* block 0 id 1 */
#define BLOCK0_ID1_C0 'c' /* block 0 id 1 'cm' 0 */
#define BLOCK0_ID1_C1 'C' /* block 0 id 1 'cm' 1 */
:124
#define B0_FNAME_SIZE_ORG 900 /* what it was in older versions */
#define B0_FNAME_SIZE_NOCRYPT 898 /* 2 bytes used for other things */
#define B0_FNAME_SIZE_CRYPT 890 /* 10 bytes used for other things */
#define B0_UNAME_SIZE 40
#define B0_HNAME_SIZE 40
/*
* Restrict the numbers to 32 bits, otherwise most compilers will complain.
* This won\'t detect a 64 bit machine that only swaps a byte in the top 32
* bits, but that is crazy anyway.
*/
#define B0_MAGIC_LONG 0x30313233L
#define B0_MAGIC_INT 0x20212223L
#define B0_MAGIC_SHORT 0x10111213L
#define B0_MAGIC_CHAR 0x55
:139
/*
* Block zero holds all info about the swap file.
*
* NOTE: DEFINITION OF BLOCK 0 SHOULD NOT CHANGE! It would make all existing
* swap files unusable!
*
* If size of block0 changes anyway, adjust MIN_SWAP_PAGE_SIZE in vim.h!!
*
* This block is built up of single bytes, to make it portable across
* different machines. b0_magic_* is used to check the byte order and size of
* variables, because the rest of the swap file is not portable.
*/
struct block0
{
char_u b0_id[2]; /* id for block 0: BLOCK0_ID0 and BLOCK0_ID1,
* BLOCK0_ID1_C0, BLOCK0_ID1_C1 */
char_u b0_version[10]; /* Vim version string */
char_u b0_page_size[4];/* number of bytes per page */
char_u b0_mtime[4]; /* last modification time of file */
char_u b0_ino[4]; /* inode of b0_fname */
char_u b0_pid[4]; /* process id of creator (or 0) */
char_u b0_uname[B0_UNAME_SIZE]; /* name of user (uid if no name) */
char_u b0_hname[B0_HNAME_SIZE]; /* host name (if it has a name) */
char_u b0_fname[B0_FNAME_SIZE_ORG]; /* name of file being edited */
long b0_magic_long; /* check for byte order of long */
int b0_magic_int; /* check for byte order of int */
short b0_magic_short; /* check for byte order of short */
char_u b0_magic_char; /* check for last char */
};
offs len what
0 2 id
2 10 version
12 4 bytes per page
16 4 mtime
20 4 inode
24 4 PID or 0
28 40 name of user or uid
68 40 host name
108 900 fname
1008 4/8/ magic long*
1012 4/8/ magic int*
1016 2/ magic short*
1018 1/ magic char*
Length of magics is arch dependant.
Offset for magic, in example above, is by standard 32 bit.
评论
我建议您删除最后一段,并将现有解决方案发布为自我解答。可能会有更好的答案。我可以拿一份你的剧本吗?
@hildred:不确定您从中得到什么,但最后将其发布了...
注意:Vim带有可编辑的插件