Pertahankan cap waktu yang dimodifikasi setelah diedit

20

Untuk file dalam folder tertentu, saya ingin vim untuk tidak pernah menyentuh stempel waktu "dimodifikasi" sama sekali.

Latar belakangnya adalah saya menggunakan Bloxsom untuk blogging, yang menggunakan file teks biasa ~/bloxsomsebagai sumber semua artikel. Tanggal artikel (dan karena itu urutan penampilan) didasarkan pada tanggal modifikasi file teks. Saya tidak ingin artikel muncul seperti jika ini baru setiap kali saya memperbaiki kesalahan ketik. (Saya melakukan banyak dari mereka ...: D)

Sejauh ini, vim mengubah stempel waktu dan stempel asli hilang selamanya. Ini OK dan saya ingin tetap seperti itu untuk sebagian besar file di sistem. Tapi saya tidak ingin itu untuk file blog - saya selalu bisa touchfile jika saya perlu.

Ada ide tentang cara mengubah vim ke perilaku ini?

Alois Mahdal
sumber
2
vim.wikia.com/wiki/... - Anda tentu saja dapat menggunakan binding perl sebagai gantinya
Ulrich Dangel

Jawaban:

22

Saya tidak berpikir vim memiliki fitur ini. Salah satu alternatif adalah memodifikasi salinan dan mengatur cap waktu dengan tepat, misalnya:

cp -p post temp
vim temp
touch -r post temp
cp -p temp post

Atau lebih baik lagi:

touch -r post timestamp
vim post
touch -r timestamp post
Thor
sumber
7

Jika Anda perlu bersenang-senang:

file=path; mtime=$(stat -c %y "$file"); vi "$file"; touch -d "$mtime" "$file"

Ganti jalur dengan jalur file Anda yang sebenarnya

Shâu Shắc
sumber
5

Saya menulis naskah Perl untuk itu.

Ini adalah pembungkus di sekitar vim, disimpan ~/bin/vim-nomtime.pldan mulai digunakan alias vim='~/bin/vim-nomtime.pl'di .bashrc saya.

#!/usr/bin/perl
use strict;
use warnings;
use Cwd qw/ abs_path /;

my @dirs = qw( ~/blosxom /srv/relief/blosxom );

s/^~/$ENV{HOME}/ foreach @dirs;

# do we want to preserve stamp on this file?
sub fits {
    my $dir = abs_path($_[0]);
    my $fits = 0;
    foreach (@dirs) {
        my $preserved_dir = abs_path($_);
        $fits++ if $dir =~ m|^$preserved_dir|;
    }
    return $fits != 0;
}

# store original stamps
my $original_stamp;
foreach (@ARGV) {
    if ( -f $_ and fits($_) ) {
        $original_stamp->{$_} = (stat($_))[9];
    }
}

# run vim as you would
my $cmd = join ' ', 'vim', @ARGV;  
system($cmd) == 0
    or die "vim failed: $!";

# restore stamps if they have changed
foreach (keys %$original_stamp) {
    next unless -f $_;
    my $current_stamp = (stat($_))[9];
    unless ($current_stamp == $original_stamp->{$_}) {
        utime $original_stamp->{$_}, $original_stamp->{$_}, $_;
    }
}

Beberapa fitur bagus:

  • mendukung banyak nama file

  • mendukung beberapa dir "ditonton"

  • mendukung dir symlinked

  • dapat ditingkatkan dengan kriteria lain

sebagian besar yang mungkin dapat juga dicapai dengan versi vim murni. Kerugian dari solusi ini dibandingkan dengan solusi pure-vim yang saya inginkan adalah:

  • mengembalikan cap hanya setelah vim telah berhenti, jadi jika saya melakukan edit lama dan menyimpan secara teratur, file vill "pop-up" seperti baru sampai saya berhenti vim

  • ini mendukung banyak file pada command line, tetapi dengan cara yang cukup naif - hanya memeriksa apakah yang aktif @ARGVadalah file. Ini mungkin tidak akan berfungsi dengan wildcard (mis. vim note-*.txt) Atau hal-hal lucu lainnya

  • itu bukan crash proof, bahkan mungkin bukan HUP-proof (yang bisa dilakukan)

  • ... yah, itu pembungkus. (Maksudku, jika kita menyelesaikan semuanya melalui pembungkus, berapa banyak pembungkus yang akan kita miliki sebelum sesuatu yang buruk terjadi?)

Alois Mahdal
sumber
3 Mei 2019, dan saya baru saja memodifikasi file dari 11 November 2017 dan memiliki modifikasi dan mempertahankan cap waktu asli. :)
jmort253
1

Script pendek ini akan menghemat waktu yang dimodifikasi jika ada dir induk dari file berisi .nomtimefile:

#!/bin/bash

dir="${1%/*}"
[ "$dir" = "$1" ] && dir=.
dir=$( readlink -f "$dir" )

nomtime=
while [ -n "$dir" ]; do
    if [ -f "$dir/.nomtime" ]; then
        nomtime=1
        break
    fi
    dir="${dir%/*}"
done

if [ "$nomtime" = 1 ]; then
    T=`tempfile`
    touch -r "$1" $T
fi

vi "$1"

if [ "$nomtime" = 1 ]; then
    touch -r $T "$1"
    rm $T
fi
Xiè Jìléi
sumber
1

Coba bashfungsi ini (berdasarkan jawaban Shâu Shắc )

vi-preserve-time () {
    for file in "$@"; do
        local mtime=$(stat -c %y "$file")
        vi "$file"
        touch -d "$mtime" "$file"
    done
}

Sekarang kita dapat mengedit file dan menghemat waktu yang dimodifikasi menggunakan ini

vi-preserve-time file1.txt file2.txt
Steely Wing
sumber
(1) Ini hampir identik dengan jawaban Shâu Shắc dari lima tahun yang lalu. (2) Ini mengasumsikan bahwa pengguna vihanya meminta satu file pada satu waktu; itu tidak akan berhasil vi file1 file2. (3) Tak perlu dikatakan bahwa, jika pengguna beralih ke file yang berbeda dengan :e, itu tidak akan ditangani.
G-Man Mengatakan 'Reinstate Monica'
Maaf tentang lupa referensi, sekarang saya menambahkan tautan referensi ke jawaban Shâu Shắc.
Steely Wing
Tentang pertanyaan Anda # 3, saya pikir jika Anda membuka file lain tidak ada di baris perintah, itu masalah Anda.
Steely Wing
1
Maksud saya adalah, jika pertanyaannya bertanya "Bagaimana saya bisa membuat vim berperilaku seperti yang saya inginkan?", Dan Anda memberikan fungsi yang sepertinya membuat vim berperilaku seperti yang diinginkan pengguna, Anda bertanggung jawab untuk mendokumentasikan segala batasan Anda menjawab. OK, mungkin komentar saya sedikit tidak adil, karena semua jawaban lain tampaknya memiliki batasan yang sama, dan tidak ada dari mereka yang menyebutkannya, sejauh yang saya tahu. Saya baru mengulas jawaban Anda karena itu baru; Saya tidak menghabiskan banyak waktu untuk melihat jawaban yang lain.
G-Man Mengatakan 'Reinstate Monica'
1

Ada opsi untuk menyalin cap waktu dari file lain.

touch -m -r file_source file_target

Contoh:

[oracle@es abc]$ ls -tlr
total 4
-rw-r--r--. 1 oracle oinstall 102 May  8 20:35 aa.txt
[oracle@es abc]$ echo "hi hi" > b
[oracle@es abc]$ ls -ltr
total 4
-rw-r--r--. 1 oracle oinstall 102 May  8 20:35 aa.txt
-rw-r--r--. 1 oracle oinstall   6 May 13 18:58 b
[oracle@es abc]$ touch -m -r aa.txt b
[oracle@es abc]$ ls -tlr
total 8
-rw-r--r--. 1 oracle oinstall   6 May  8 20:35 b
-rw-r--r--. 1 oracle oinstall 102 May  8 20:35 aa.txt
[oracle@es abc]$ cat b
hi hi
pengguna352752
sumber
1

Saya menemukan solusi hebat di halaman web ini , yang menciptakan fungsi vim untuk menyimpan file saat ini sambil menjaga waktu modifikasi yang ada, dan mengikat fungsi ini ke tombol F4fungsi:

Namun, saya menemukan bahwa fungsi asli berisi bug kecil, memicu peringatan berikut jika F4digunakan dua kali pada file yang sama, karena vim menjadi bingung ketika waktu modifikasi berubah:

WARNING: The file has been changed since reading it!!!
Do you really want to write to it (y/n)?

Untungnya, ini mudah untuk diperbaiki: Saya menambahkan perintah "edit" ke fungsi asli untuk memuat ulang file setelah mengembalikan timestamp, jadi vim tahu waktu modifikasi apa yang diharapkan dari file tersebut.

Berikut adalah fungsi vim yang dimodifikasi dengan perbaikan bug ini, yang dapat ditambahkan ke ~/.vimrc:

function! WriteSmall()
    let mtime = system("date -d @`stat -c %Y ".shellescape(expand('%:p')) . "`")
    write
    call system("touch --date='".mtime."' ".shellescape(expand('%:p')))
    edit
endfunction
map <F4> :call WriteSmall()<CR>

Catatan: Fungsi ini bergantung pada versi GNU date, statdan touch.

Deven T. Corzine
sumber
0

Menggunakan beberapa konsep yang dijelaskan di atas, berikut adalah alias one-liner yang sangat cepat dan kotor untuk CSH yang membuat perintah "edit" tersedia untuk tujuan ini:

alias edit 'touch -r \!:1 /tmp/~mtime ; vim \!:1 ; touch -r /tmp/~mtime \!:1 ; rm /tmp/~mtime'

Anda dapat dengan mudah menggunakan variabel lingkungan $ VISUAL atau $ EDITOR sebagai pengganti "vim". Dengan cara ini Anda dapat mengeluarkan perintah berikut untuk mengubah editor default

setenv VISUAL nano

Sekarang alias itu sendiri tidak perlu didefinisikan ulang untuk mengakomodasi editor yang berbeda, membuatnya agak lebih portabel. Jika Anda menggunakan shell selain CSH atau TCSH, tentu saja, contoh di atas dapat disesuaikan.

Leslie Krause
sumber