‹ BackHN Continuity

Thread

On caring for user data: NeoVim caused Vim undo files to be deleted

384 points · 346 comments · jandeboevrie

  1. gavinhoward · · focus · HN ↗
    As a Neovim user, this stopped me dead with painful realization: I may have suffered the same thing but didn't realize it. There was a time when I could not undo something, and it was after a Neovim upgrade.

    Unlike Dr. Chisnall, I started my editor journey on Neovim, so it wasn't a transition that bit me. However, if the format of the persistent undo file is unstable, and Neovim just deletes it when it doesn't recognize the previous format, then it seems conceivable (to me) that an upgrade after changing the format would delete the file too.

    Ouch. This is making me think about getting off of Neovim. Yes, FOSS comes as-is, but if there's an alternative...

    1. cdmckay · · focus · HN ↗
      It’s such an odd design decision.

      I could see ignoring the old undo data or warning before discarding it but just silently wiping it is so user hostile it’s hard to comprehend.

      1. loeg · · focus · HN ↗
        If you ignore it, do you continue allowing edits to the file? Now undo history is corrupt and useless anyway. Or do you disallow editing until the user manually deletes some hidden, implementation-detail file for a feature they probably never use?
        1. xoa · · focus · HN ↗
          If making a breaking change to the format of the file, why in root's name would neovim not just make its own new file!? Import the vim version if that's desired into persistent-undo.neovim and then just go from there. I don't understand their choice here at all nor why you're acting like this is complicated or there was some need for them to reuse the exact same file as vim?
          1. [deleted] · · focus · HN ↗

            [deleted]

          2. bot403 · · focus · HN ↗
            To support you further, why would neovim users have any illusion there would be cross compatibility between undo files? Separate undo files seems the obvious and expected choice.
        2. physicalecon · · focus · HN ↗

          [dead]

      2. 59percentmore · · focus · HN ↗
        It's some sort of industry standard, though, isn't it? Google Chrome on Android auto-deletes the history database silently if it deems it corrupted (e.g., due to a bad write on a system with low storage). You just open your browser one day and it's all gone.

        If not, I wonder how Google justifies it.

        1. jwr · · focus · HN ↗
          Google is the epitome of design that doesn't care at all about the user and user experience.
        2. diendiencjejd · · focus · HN ↗
          If Google does something in X way, you can almost always be certain that X way is the wrong way to do that.

          Google is abysmal. In every sense of the word and in every product they touch.

      3. rcxdude · · focus · HN ↗
        It feels like a mismatch in expectations. It's fairly obvious the developers consider the persistent undo feature to be a convenience for short-term continuity if you are exiting and re-entering the editor over a single edit session, not a long-term storage of the history of the file. All of their decisions make perfect sense in that context, but it seems that expectation is not shared by some of their users, who considered it to be an important piece of data meant to be kept long-term. This feels a bit odd to me, given the tendency for undo systems to be fragile anyway, and the documented fragility of this persistence. The author of this article even had deliberate workarounds for some of this fragility which I feel would put me in 'should I even trust this feature?' mode. To me the main fix would be updating the documentation to scream even more loudly "Don't expect this to stay around!".

        To me it's a bit like storing your important files in a ramfs and then complaining that your OS doesn't respect user data when it crashes. Sure, it's not exactly a documented behaviour of the system, but you're also not storing your data in a place the developers of the OS expected you to put important data.

        1. eviks · · focus · HN ↗
          > but you're also not storing your data in a place the developers of the OS expected you to put important data.

          So exactly the opposite of persistent undo?

          The short-termism changes little here, losing weeks' worth of work just because you deleted it recently by mistake and then upgraded with the app deleting the undo, is also bad

          1. rcxdude · · focus · HN ↗
            That's the point, though, undo (in most applications) is a fragile place to hold much work, regardless of whether it normally survives restarting the app. You could argue about whether it should be that way (infinite, robust, persistent undo is a nice safety net in general), but I would not assume that is the case unless it's very well documented otherwise (and the UI is adjusted accordingly: you really need an undo tree, else a large series of undos followed by an accidental edit will also wipe out a lot of data), and neovim's documentation does not say that it is intended to work that way.
    2. antonkochubey · · focus · HN ↗
      Sorry for my ignorance, but what is the usefulness of undo persistence after a IDE restart? Don't you normally save your changes and finish a piece of work before exiting an DE?

      Edit: some great examples in the replies here, thanks! Perhaps I should start using it in editors that support it, never gave it a thought before.

      1. jeremyjh · · focus · HN ↗
        The whole point of undo is that you realize you made a mistake later. If you've done that after you've saved your changes and exited the program, you'd have no expectation of undo still working unless you've enabled this feature.

        It doesn't matter whether or not you can think of a reason you would want to enable it, but it should be pretty trivial to do so. Once you've enabled it, it should work.

      2. dezgeg · · focus · HN ↗
        If your session / computer crashes, for one.
      3. traverseda · · focus · HN ↗
        I often use it to edit system config files, often on embedded devices where I don't have my git credentials setup, or on servers. In these cases we're already not in an ideal world, I don't have good reliable version control or change management in place. In those less-than-ideal worlds, having proper undo history is nice.
        1. Joker_vD · · focus · HN ↗

              #!/bin/sh
              
              errecho() {
                  >&2 printf '%s\n' "$@"
              }
              
              if [ "$#" != 1 ] || [ -z "$1" ]
              then
                  errecho 'Requires a single filename as the argument'
                  exit 1
              fi
              
              ORIGINAL=$1
              if [ "${ORIGINAL#./}" == "$ORIGINAL" ] && [ "${ORIGINAL#/}" == "$ORIGINAL" ]
              then
                  ORIGINAL=./"$ORIGINAL"
              fi
              
              # because of course the output of dirname can't be blindly joined with slash and the basename
              DIRNAME=$(dirname -- "$ORIGINAL")
              if [ "$DIRNAME" = / ]
              then
                  DIRNAME=
              fi
              
              FILENAME=$(basename -- "$ORIGINAL")
              # because of course extracting the filename's extension is not supported out of the box
              case "$FILENAME" in
                  .*.* )
                      EXTENSION=.${FILENAME#.*.}
                      BASENAME=$(printf '%s' "$FILENAME" | cut -c-$((${#FILENAME} - ${#EXTENSION})) )
                      ;;
                  .* )
                      EXTENSION=
                      BASENAME=$FILENAME
                      ;;
                  *.[^.]* )
                      BASENAME=${FILENAME%%.*}
                      EXTENSION=${FILENAME#*.}
                      ;;
                  * )
                      BASENAME=${FILENAME%%.*}
                      EXTENSION=$(printf '%s' "$FILENAME" | cut -c$((${#BASENAME} + 1))- )
                      ;;
              esac
              
              if [ "$FILENAME" != "$BASENAME$EXTENSION" ] || [ -z "$BASENAME" ]
              then
                  errecho 'Failed to properly split the extension from the filename:' "$FILENAME"
                  exit 1
              fi
              
              TIMESTAMP=$(date --utc --date=@"$(stat --format %Y "$ORIGINAL")" +'_%Y-%m-%d_%H%M%S')
              if [ -z "$TIMESTAMP" ]
              then
                  errecho 'Failed to get the timestamp of the file:' "$ORIGINAL"
                  exit 1
              fi
              
              NEW_FILENAME=$(printf '%s/%s_%s%s' "$DIRNAME" "$BASENAME" "$TIMESTAMP" "$EXTENSION")
              
              if [ "$NEW_FILENAME" = "$ORIGINAL" ]
              then
                  errecho 'Somehow the name for the backup is the same as the original file'
                  exit 1
              fi
              
              # this preserves the timestamps somewhat better
              if ! mv --no-clobber --no-copy -- "$ORIGINAL" "$NEW_FILENAME"
              then
                  errecho 'Failed to backup the file: ' "$ORIGINAL" "$NEW_FILENAME"
                  exit 1
              fi
              
              if ! cp -- "$NEW_FILENAME" "$ORIGINAL"
              then
                  errecho 'Failed to backup the file: ' "$ORIGINAL" "$NEW_FILENAME"
                  mv --no-clobber --no-copy -- "$NEW_FILENAME" "$ORIGINAL"
              fi
          
          Actually, nevermind that bullshit, you know what? I think I'd prefer to have an editor with locally persisted edit history instead.
        2. PunchyHamster · · focus · HN ↗
          First, you need backups

          Second (for servers), etckeeper

          1. traverseda · · focus · HN ↗
            I mean I already responded to the comment

            > In these cases we're already not in an ideal world, I don't have good reliable version control or change management in place.

            Most of the stuff I work on is properly scripted idempotent deploys, with good backups and all that. Or it's a one-off demo, or a prototype. Not having full undo history is never going to actually kill a project, it's just going to make early stage projects and one-offs more inconvenient.

      4. prerok · · focus · HN ↗
        Most apps don't have it, so you might not be used to it, but have you never wished that you could undo the changes you made after you restarted the program?

        Moreover, the vim history tracking is amazingly advanced. It's almost like a mini version control system. I highly recommend getting to know it.

      5. drfloyd51 · · focus · HN ↗
        The article gave 2 examples.

        I can give some as well. IDE crashes. Computer reboots at an undesired time. Even if my work is saved, I am not “finished”. I would like my undo history to extend before file / open time.

      6. schmichael · · focus · HN ↗
        The reason why this feature is particularly useful in vi-likes is because they are not IDEs. I hop in and out of vi all day long. Depending on the task I might create a new tab, run a command in vi, or exit vi to run it. Vi’s appeal is that it is “just” an editor and your terminal and workstation form your un-integrated development environment.
      7. kelnos · · focus · HN ↗
        One silly example: sometimes I'll open up source or config file to make a quick, temporary change in order to test something. But then instead of ctrl+z backgrounding it, I'll accidentally quit vim. Then I start it back up to undo the change, and find that there's no undo history.

        I didn't know about persistent undo until seeing this posted here on HN, but now I've enabled it! Of course, turns out it's an unreliable feature on nvim... maybe I'll consider switching back to the original (for that and other reasons).

      8. tommyage · · focus · HN ↗
        Another one:

        `:earlier 1d`.

        persistant undo is like a second brain to consolidate.

Open on Hacker News to reply ↗

Unofficial Hacker News client; not affiliated with Y Combinator.