Sublime Forum

Add file date/time to status bar

#1

Is there a way to show the file last modified date in the status bar? I work with many files and often need to check the last modified status of files when I make changes so I don’t overwrite or work on old files, meaning ones that haven’t been modified recently.

I keep backup versions of the files I edit and want to make sure I am editing a recent version without having to check the file manager or Beyond Compare which I use to compare changes in files I edit.

I have looked through these forums and online but have not see a way to display that although I see it is possible to display many other things associated with projects and file statuses like file size, line positions, etc.

Any help would be greatly appreciated.

0 Likes

#2

This is taken from my own status_bar.py module in User, which does more than just showing a clock, so I tried to extract only the relevant parts (but I didn’t test it). This will show a clock icon followed by “HH:MM” time format in the bottom left part of the sidebar.


import datetime

import sublime
import sublime_plugin


KEY_CLOCK = "0-clock"
CLOCK_ICON = "⏰"



def set_status(view, key, value):
    view.set_status(key, value)


def show_clock(view):
    now = datetime.datetime.now()
    secs = 60 - now.second  # secs until the next minute
    sublime.set_timeout_async(lambda: show_clock(view), secs * 1000)
    tstamp = now.strftime("%H:%M")
    set_status(view, KEY_CLOCK, f"{CLOCK_ICON} {tstamp}")


def compose_status_bar(view):
    show_clock(view)


def update_all():
    for window in sublime.windows():
        for view in window.views():
            compose_status_bar(view)


class StatusBarEvents(sublime_plugin.EventListener):
    def on_new_async(self, view):
        compose_status_bar(view)

    def on_load_async(self, view):
        compose_status_bar(view)

    def on_clone_async(self, view):
        compose_status_bar(view)

    def on_load_project_async(self, win):
        update_all()
0 Likes

#3

this worked for me (thanks @jfcherng)

0 Likes

#4

Thanks @giampaolo. As I do not have a status_bar.py already, where do I create this file? I tried in my …\packages\user directory but that didn’t add anything new in my status bar in ST3.

1 Like

#5

That is the correct place to put the file (check with View > Show Console; you should see a message about it reloading the plugin every time you save; make sure you don’t see any error).

The plugin works by adding to the status bar for files, but what is displayed there is unique per file. As defined, it will only add the information to new file tabs (which are otherwise empty), files when they load, files when you clone them (by using New view into file or similar) and when you open a project.

If you’re not doing any of those things, then the plugin won’t apply to any files you have open at the time unless you close and reopen them (unless the plugin is modified to trigger for all files at load time, but the closing and reopening is easier since going forward it will just work the way you want).

0 Likes

#6

Thanks @OdatNurd. I thought that is where the file would go. I am seeing it now but it is only showing the system time not the last modified date on the file.

In looking at the code above that is all, to my limited understanding at least, it appears to do and not retrieve and show the file system date/time of the loaded file.

Also, I have dozens of files loaded into ST3 when I start it and it would be difficult/time consuming to reload each one. What would the code be to trigger the plugin at load time?

Is there a modification to the initial code that will show the system date/time of the loaded file when it was last saved?

TIA, Chris

0 Likes

#7

The code below should be closer to doing what you want (in place of the plugin outlined above).

The code in set_modification_time() will determine the last modification time of the file associated with the view passed in (if that view is associated with a file on disk and that file actually exists) and add it to the status bar with the format defined at the top (as defined here you will get something like [Tue 03 Oct 2023, 02:36PM])

The function is executed:

  1. Whenever a new file is loaded
  2. A file that has previously been loaded is reloaded (e.g. its content changed on disk and Sublime noticed)
  3. The file was saved by you or on your behalf
  4. You make a clone of an existing file, say when doing a split

In addition, the on_init() will make the function execute across all views that exist at the point at which the plugin was originally loaded. In your case, that means that when you quit and restart Sublime, all of the files in all of the windows that are open at startup will have their modification times applied.

The on_load_project_async() will trigger whenever a new window is created as a result of loading a project file from disk, and will scan over all of the views in that window and update their status bars as well.

Note that due to the usage of Pathlib and the f"" string formats (and the use of on_init and on_load_project_async) this will only work in ST4 and up since those features require the 3.8 plugin host. This could be modified to work in earlier versions if strictly needed.

Note also that your User package always runs in the 3.8 plugin host in ST4, but if you want to move this out to its own separate package folder, you would need to include a .python-version file as outlined in the documentation on API environments

import sublime
import sublime_plugin

from pathlib import Path
from datetime import datetime


# The icon/text to appear prior to modification date of the file; set to be
# empty if you want no such text.
ICON = "⏰"

# The status key to use; keys in the status bar are ordered by key, so you can
# use this to juggle the relative order of the key in the status bar as needed.
STATUS_KEY = "0-clock"

# The format string to use to format the modification time of the file in the
# status bar. See this URL for details on codes that are available:
#   https://docs.python.org/3/library/datetime.html#strftime-and-strptime-format-codes
TIME_FORMAT = "[%a %d %b %Y, %I:%M%p]"


class StatusBarEvents(sublime_plugin.EventListener):
    """
    Listen for files being loaded, reloaded, saved and cloned and update the
    status bar for that file to track the last modification time of the file as
    it appears on disk.

    This will track any file as it is originally opened, and will update all
    views in all windows
    """
    def set_modification_time(self, view):
        """
        Given a view, check to see if it has a file associated with it on disk.

        If it does, then determine the last modification time of the file and
        add or update a status key in the status bar to display that data.
        """
        if view.file_name() is not None:
            file = Path(view.file_name())
            if file.exists():
                time = datetime.fromtimestamp(file.stat().st_mtime)
                view.set_status(STATUS_KEY, f"{ICON} {time.strftime(TIME_FORMAT)}")

    # Update the last modification time in a file whenever a file loads, is
    # reloaded from disk, saved to disk by the user, or a new clone of the
    # view is created (e.g. `File > Split View` and similar.)
    on_load = on_reload = on_post_save = on_clone = set_modification_time


    def on_init(self, views):
        """
        When the event listener is instantiated, scan over all files that are
        currently open and update their modification times in the status bar.
        """
        for view in views:
            self.set_modification_time(view)


    def on_load_project_async(self, window):
        """
        Whenever a new project is loaded from disk, scan over all of files that
        may be open inside of the window and update their status bars.
        """
        for view in window.views():
            self.set_modification_time(view)
2 Likes

#8

Thank you so much @OdatNurd! That works exactly as I had hoped with refresh/update at time of load or file save.

Best regards,
Chris

0 Likes

#9

Thanks for the detailed reply. I used your code and it also works on my end. Is it possible to write a code for sidebar date status like it looks in the screenshot, so you don’t have to open each file to then look at the bottom status bar before you can see the date last modified?

Basically, when you hover on a folder, it shows the date of creation or last modified

0 Likes

#10

This is not possible on hover, no; there’s not an API that allows you to know when hovering is happening in the side bar (only within an edited file).

That said, a potential way around that would something like the following, which would create a menu entry in the context menu of the side bar for a command that is always disabled but which alters its menu caption to show you the modification time.

import sublime
import sublime_plugin

from pathlib import Path
from datetime import datetime

# The format string to use to format the modification time of the file in the
# menu. See this URL for details on codes that are available:
#   https://docs.python.org/3/library/datetime.html#strftime-and-strptime-format-codes
TIME_FORMAT = "%a %d %b %Y, %I:%M%p"


class LastModifiedDisplayCommand(sublime_plugin.WindowCommand):
    def run(self, paths):
        """
        No implementation since the command does nothing
        """
        pass

    def description(self, paths):
        """
        When there is exactly one path selected in the side bar (file or
        folder), set the caption to be its modification time. If there is more
        than one, N/A is displayed instead.
        """
        modified = 'N/A'
        if len(paths) == 1:
            file = Path(paths[0])
            time = datetime.fromtimestamp(file.stat().st_mtime)
            modified = time.strftime(TIME_FORMAT)

        return f"Last Modified: {modified}"


    def is_enabled(self, paths):
        """
        Command is always disabled because it does not do anything.
        """
        return False

To use this, you need to either create User/Side Bar.sublime-menu with the following contents (or if the file already exists, just add the command). The item with the single caption of "-" will add a menu separator; not strictly needed but might make the result more visible.

[
    { "caption": "-" },
    { "command": "last_modified_display", "args": { "paths": [] } },
]

Now any time you open the context menu on anything in the side bar, so long as there is only a single item selected, the menu will tell you the modification date:

2 Likes