Sublime Forum

Automatically updated Timestamp?

#1

Hello,

Vim user moving to ST2 here. I was using a very simple Vim plugin that would add a time stamp next to “Created: TIMESTAMP” and another (updated automatically every time the file is changed) next to “Last Modified: TIMESTAMP”. The script is here: is.gd/LhEgJY

Has anybody seen similar functionality for ST2, and/or whether it would be possible to implement such a thing?

Thanks.

0 Likes

#2

Such a plugin is definitely possible, but I don’t know that one exists.

0 Likes

#3

So you can write a plugin that performs an action on saving a file?

0 Likes

#4

Yeah, declare an on_pre_save function and you can do whatever you want.

0 Likes

#5

maybe something like that…

#! python
"""
TextCommand:
    insert_timetamp
EventListener:
    on_pre_save: update_timestamp
"""
import datetime
import sublime
import sublime_plugin

TIMESTAMP_PATTERN = 'FILE_CHANGED_ON\\s*=\\s*\'"]201[0-9]-\\d+-\\d+\\s+\\d+:\\d+:\\d+(\\.\\d+)?\'"]'

class InsertTimestampCommand (sublime_plugin.TextCommand):
    """
    Replace selection with a current timestamp in ISO format.
    """
    def run (self, edit, **args):
        timestamp = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
        self.view.replace (edit, self.view.sel()[0], timestamp)

class UpdateTimestampListener (sublime_plugin.EventListener):
    """
    Search for a timestamp to update before saving the file.
    Maybe to simple.
    """
    def on_pre_save (self, view):
        region = view.find (TIMESTAMP_PATTERN, 1)
        if region :
            timestamp = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
            replacement = 'FILE_CHANGED_ON = "%s"' % timestamp
            edit = view.begin_edit()
            view.replace (edit, region, replacement)
            view.end_edit (edit)
0 Likes

#6

Thanks, guys.

0 Likes

#7

I have a similar plugin which inserts the hash of the file,

github.com/mmmpie/insert-hash-on-save

0 Likes

#8

Here’s a script I wrote for this (Code adapted from hintermair’s answer on:
https://stackoverflow.com/questions/28032780/automatic-update-date-in-sublime-by-save):

""" Command (with key-binding ctrl + s) that automatically updates
the date-last-modified section in a file with each save

Only thing the user has to change (if they so wish) is the variables
Header_Format and/or Date_Format """


import sublime, sublime_plugin
import time

class AddDateCommand(sublime_plugin.TextCommand):
    def run(self, args):
        content = self.view.substr(sublime.Region(0, self.view.size()))

        """Can change Header_Format if you so wish.
        Don't worry about whether you have to add an extra space 
        at the end of 'Header_Format'; the rest of the code already
        takes care of that. """
        Header_Format = 'Date Last Edited:'

        begin = content.find(Header_Format)
        if begin == -1:
            return

        """ If you want your date printed out in a different format
            (e.g. YYYY/mm/dd instead of dd mm YYYY), feel free to 
            play around with the parameters in strftime() """
        Date_Format = time.strftime("%d %b %Y %I:%M%p")

        # To update time/date last modified, command looks for the beginning
        # of the date-string (e.g. "D" if it's "Date Last Edited: 26 Jun 2017 05:38PM") and 
        # the end of the date-string (e.g. "M" if it's "Date Last Edited: 26 Jun 2017 05:38PM")
        # and replaces the whole string with an identical string (only change being the time/date)

        # "+ 1" is to take into account the space between Header_Format and Date_Format
        length_of_line = len(Header_Format) + 1 + len(Date_Format)
        end = begin + length_of_line

        target_region = sublime.Region(begin, end)
        self.view.sel().clear()
        self.view.sel().add(target_region)

        # The " " adds a space between Header_Format and Date_Format
        self.view.run_command("insert_snippet", { "contents": Header_Format + " " + Date_Format } )
    

# Command does 2 things; update the date, and save the file
class DateAndSaveCommand(sublime_plugin.WindowCommand):
    def run(self):
        self.window.run_command("add_date")
        self.window.run_command("save")
  1. Create a file called add_date.py and copy-paste the above-code into it.

  2. Save the file in Sublime Text -> Packages -> User

  3. Go to Sublime Text -> Preferences -> Key Bindings and add the below into User:

    [
    {“keys”: [“ctrl+s”], “command”: “date_and_save” }
    ]

  4. Now the file you’re working on should have the date auto-updated everytime you hit ctrl + s

So it will turn a file like this:

// Author: Me
// Date Last Edited: 26 Jun 2017 07:08PM
// Generic Program Description

#include <stdio.h>

int main (void) {
    //Some stuff happens here
	return 0;
}

into something like this after hitting ctrl + s :

// Author: Me
// Date Last Edited: 26 Jun 2017 07:39PM
// Generic Program Description

#include <stdio.h>

int main (void) {
    //Some stuff happens here
	return 0;
}

Should also work with other languages

NOTE: You DO need some date string in the file to begin with for the formatting to stay the same. If u try hitting ctrl + s on something like this:

// Author: Me
// Date Last Edited: 
// Generic Program Description

#include <stdio.h>

int main (void) {
	//Some stuff happens here
	return 0;
}

You’ll get something like this:

// Author: Me
// Date Last Edited: 26 Jun 2017 07:49PM Description

#include <stdio.h>

int main (void) {
	//Some stuff happens here
	return 0;
}

But at least you’ll only have to add the date format once (which I just use a snippet for anyways).

1 Like

#9

Edit: Improved the add_date.py code so that it wouldn’t move the view too much (which was annoying). The updated code is:

# -*- coding: utf-8 -*-

"""Key-binding-activated command that automatically updates the
date-last-modified section in a file with each save.

Only thing the user has to change (if they so wish) are the variables
Header_Format and/or Date_Format.

Code adapted from hintermair's answer on: https://stackoverflow.com/questions/28032780/automatic-update-date-in-sublime-by-save

NOTE: Only change the variables Header_Format and/or Date_Format.
The rest of the code should remain untouched.
"""

import sublime
import sublime_plugin
import time


class AddDateCommand(sublime_plugin.TextCommand):
    """To update time/date last modified, command looks for the beginning
    of the date-line (e.g. "L" if it's "// Last Edited: 26 Jun 2017
    05:38PM") and the end of the date-line (e.g. "M" if it's "// Last Edited:
    26 Jun 2017 05:38PM") and replaces the whole string with an identical
    string (only change being the time/date).
    """

    def run(self, args):
        content = self.view.substr(sublime.Region(0, self.view.size()))
        original_position = self.view.sel()[0]

        # Can change Header_Format to a different title if you so wish
        # (you don't have to add an extra space at the end of Header_Format;
        # the rest of the code already takes care of that for you).
        Header_Format = "Last Edited:"

        begin = content.find(Header_Format)

        # If there's no date-line in the file, nothing happens.
        if begin == -1:
            return
        # else:

        # If you want your date printed out in a different format
        # (e.g. YYYY/mm/dd instead of dd mm YYYY),
        # feel free to rearrange/play around with the parameters in strftime().
        Date_Format = time.strftime("%d %b %Y %I:%M%p")

        # The " " adds a space between Header_Format and Date_Format.
        date_line = Header_Format + " " + Date_Format
        end = begin + len(date_line)

        # Move the cursor to the region in the file where the header/date are.
        target_region = sublime.Region(begin, end)
        self.view.sel().clear()
        self.view.sel().add(target_region)

        # Update the date.
        self.view.run_command("insert_snippet", { "contents": date_line })

        # Move the cursor back to the original position the user was typing at
        # (so the screen doesn't move away too much from the user).
        self.view.sel().clear()
        self.view.sel().add(original_position)
        self.view.show(original_position)


class DateAndSaveCommand(sublime_plugin.WindowCommand):
    """Command does 2 things; save the file, and update the date-line."""

    def run(self):
        self.window.run_command("save")
        self.window.run_command("add_date")
        # We save again here, since the change-of-date itself needs to be saved
        self.window.run_command("save")

All the other info in my reply still remains the same.

1 Like

#10

Thanks Saeed. It worked like a charm.

Only update for Mac users, you may need to change Key Bindings to:

[
  {"keys": ["ctrl+s"], "command": "date_and_save" },
  {"keys": ["super+s"], "command": "date_and_save" }
]
0 Likes