Tăng cửa sổ giữ tập tin hoán đổi


13

Thỉnh thoảng trong khi làm việc trên nhiều dự án và / hoặc bất cứ điều gì, nó cũng để lại cho tôi (nhiều) trường hợp Vim mở - như đã xảy ra, tôi mở một tệp đã được mở ở nơi khác, để lại cho tôi tùy chọn:

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

Có một số cách được xây dựng để nâng cao thể hiện, như trong GUI / terminal, giữ tệp đang mở không? Lý tưởng đưa tập tin được đề cập đến nền trước (nếu nhiều bộ đệm).

Cho đến bây giờ tôi đang sử dụng một tập lệnh bash trích xuất PID từ trao đổi, kiểm tra xem bộ PID đó có thuộc về Vim không và nếu có thì sử dụng wmctrlđể nâng cao cửa sổ. Mặc dù điều này hoạt động tốt, ít nhất là cho GUI và trên X11 Linux, tôi đang hỏi liệu có cách nào khác hơn không.


4
Tôi đề nghị bạn nên xóa đoạn cuối và đăng giải pháp hiện có của bạn dưới dạng tự trả lời. Ai đó có thể đi cùng với một câu trả lời tốt hơn.
200_success

1
Tôi có thể có một bản sao của kịch bản của bạn?
hildred 7/2/2015

@hildred: Không chắc bạn nhận được gì từ nó, nhưng cuối cùng đã đăng nó ...
Runium

Câu trả lời:


4

Một giải pháp sẽ là sử dụng một ví dụ vim cho mỗi dự án, điều này sẽ ngăn chặn vấn đề này trừ khi nhiều dự án của bạn có các tệp chồng lấp.

Tôi sẽ giả định rằng bạn đang tìm kiếm một giải pháp tự động, thay vì một gợi ý về việc thay đổi hành vi của bạn.

Có khả năng một giải pháp khác trong FocusLost có nguồn gốc từ vim hơn.

Sự kiện autocommand FocusLost hoạt động trong GUI Vim và trong một số thiết bị đầu cuối giao diện điều khiển. Bạn có thể, thay vì chuyển sang tệp trong phiên bản vim đang mở (mà nếu bạn đang sử dụng nhiều cửa sổ gui thì lộn xộn), hãy duy trì mọi thay đổi không được ghi trong ví dụ khác của vim không bị mất (a tách nhánh git, lưu rồi hoàn tác trong cây hoàn tác hoặc đơn giản là lưu nó) và mở nó trong trường hợp mới với một dấu hiệu cho thấy nó đã được mở trước đó.

Một sự kiện autocommand có khả năng hữu ích khác, có sẵn trong vim 7, là SwapExists , chỉ ra rằng một tệp hoán đổi tồn tại cho tệp, IE đang mở.

Nếu bạn giữ mọi thứ trong tmux hoặc màn hình, có thể có một cách để chuyển sang cửa sổ / khung thích hợp.

Một tìm kiếm github ngắn gọn cũng hiển thị https://github.com/lynnard/editex hiện.vim dường như hoạt động cho các trình quản lý cửa sổ cụ thể như Xmonad.


3

Mất lâu và gần như bị lãng quên.

Có nghĩa là để xác định lại mã, vv nhưng bài viết là như vậy. Mã này được sử dụng trên hệ thống 32 bit. Không chắc nó sẽ hoạt động như thế nào trên 64-bit (hoặc loại khác).

Có một hack trong mã C ở đâu đó, (trích xuất PID).

Để lại nó như một bài đăng cho bất cứ ai để hack và chỉnh. Toàn bộ tập lệnh hiện tại của tôi (sử dụng pidtùy chọn, nó sẽ hoạt động trên bất kỳ GUI nào được cung cấp bởi GUI GUI-PID / Chương trình và việc sử dụng wmctrl -l -p, v.v.):

#!/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.
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.