스왑 파일을 보유한 창 올리기


13

여러 프로젝트에서 작업하는 동안 때때로 그리고 / 또는 무엇이든, 그것은 너무 많은 Vim 인스턴스를 열어 놓았습니다.

[O]pen Read-only, (E)dit anyway, (R)ecover, (Q)uit, (A)bort

GUI / 터미널에서와 같이 열린 파일을 보유하여 인스턴스를 올리는 방법이 있습니까? 문제의 파일을 포 그라운드로 가져 오는 것이 이상적입니다 (버퍼가 여러 개인 경우).

현재 스왑에서 PID를 추출하는 bash 스크립트를 사용하고 있으며 PID가 Vim에 속하는지 확인하고 그렇다면 wmctrl창을 올리는 데 사용 합니다. 적어도 GUI와 X11 Linux에서는 이것이 잘 작동하지만 더 원시적 인 방법이 있는지 묻습니다.


4
마지막 단락을 제거하고 기존 솔루션을 자체 답변으로 게시하는 것이 좋습니다. 누군가 더 나은 답변을 얻을 수 있습니다.
200_success

1
스크립트 사본을 가질 수 있습니까?
6

@hildred : 당신이 그것에서 아무것도 얻을 확실하지 않지만 마지막에 그것을 게시 ...
Runium

답변:


4

한 가지 해결책은 프로젝트 당 하나의 vim 인스턴스를 사용하는 것입니다. 이렇게하면 여러 프로젝트에 파일이 겹치지 않는 한이 문제를 방지 할 수 있습니다.

그래도 동작 변경에 대한 제안 대신 자동 솔루션을 찾고 있다고 가정합니다.

FocusLost 에는 vim보다 더 고유 한 다른 솔루션이있을 수 있습니다 .

FocusLost 자동 명령 이벤트는 GUI Vim 및 일부 콘솔 터미널에서 작동합니다. 열려있는 vim 버전에서 파일로 전환하는 대신 (여러 GUI 창을 사용하는 경우 혼란 스럽습니다) vim의 다른 인스턴스에서 작성되지 않은 변경 사항은 유지되지 않습니다 (a 자식 분기를 분리하고 저장 한 다음 실행 취소하여 실행 취소 트리에 있거나 단순히 저장하십시오)) 이전에 열렸다는 표시와 함께 새 인스턴스에서 엽니 다.

vim 7에서 사용할 수있는 잠재적으로 유용한 또 다른 자동 명령 이벤트는 SwapExists 이며, 파일에 대한 스왑 파일이 있음을 나타냅니다 (IE가 열려 있음).

모든 것을 tmux 또는 화면에 보관했다면 적절한 창 / 창으로 전환하는 방법이있을 것입니다.

간단한 github 검색은 Xmonad와 같은 특정 창 관리자에서 작동하는 것처럼 보이는 https://github.com/lynnard/editexisting.vim 도 표시합니다.


3

길을 잃고 거의 잊었다.

코드 등을 리팩터링해야하지만 게시는 그대로입니다. 이 코드는 32 비트 시스템에서 사용됩니다. 64 비트 (또는 다른)에서 어떻게 작동하는지 확실하지 않습니다.

어딘가에 C 코드를 해킹하십시오 (PID 추출).

누구나 해킹하고 조정할 수있는 게시물로 남겨 두십시오. 내 현재 스크립트 전체 ( pid옵션으로 사용 하면 "GUI-PID / 프로그램" 및 사용 등의 모든 GUI에서 작동해야 wmctrl -l -p함) :

#!/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" "$1"
    fi
}

# Check if PID is a (G)Vim process
check_vim_pid()
{
    local comm=
    if ! [[ "$1" =~ ^[0-9]+$ ]];then
        printf "ERR: Some weird thing has happened (P: $1).\n" >&2
        exit 1
    fi
    comm="$(ps -p $1 -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="$1"

    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 "$1" | 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 "$1" ]]; then
    usage >&2
    exit 1
fi

# Loop arguments
while [[ "$1" ]]; do
    if [[ "$1" =~ ^[0-9]+$ ]]; then
        pid=$1
    else
        [[ "${1:0:1}" == "-" ]] && op=${1:1} || op=$1
        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 "$1" ]]; then
                usage >&2;
                printf "\nE006: Can't stat \`%s'\n" "$1" >&2
                exit 2
            fi
            vim_swp_pid "$1"
            ;;
        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" '$3 == p {print $1,"\t",$2}')

pikoli()
{
    local pp=$1
    while :; do
        awk '/^PPid:/{print $2;next}/^Name:/{print $2;next}' /proc/$pp/status 2>/dev/null || return
        pp=$(awk '/^PPid:/{print $2;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.
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.