Sublime Forum

Easiest way to insert date/time with a single keypress?

#21

I’m not entirely sure how to fix the code presented, but I do have my own variation on this theme where I have a header that I replace a field in with the current time.

class vhdlModeInsertHeaderCommand(sublime_plugin.TextCommand):
    """
    This command is used to insert a predefined header into the
    current text file.
    """
    def run(self, edit):
        # Assigning this to a string to keep command shorter later.
        template = "Packages/vhdl_mode/Snippets/vhdl-header.sublime-snippet"

        # Getting a few fields from the settings file
        settings = sublime.load_settings('vhdl_mode.sublime-settings')
        # Looking for a name, first the buffer name, then the file name,
        # then finally a default value.
        buffname = self.view.name()
        longname = self.view.file_name()
        if buffname:
            filename = buffname
        elif longname:
            # Convert Windows slashes to Unix slashes (if any)
            longname = re.sub(r'\\', '/', longname)
            namechunks = longname.split('/')
            filename = namechunks[len(namechunks)-1]
        else:
            filename = '<filename>'
        author = settings.get("vhdl-user", "<user>")
        company = settings.get("vhdl-company", "<company>")
        date = time.ctime(time.time())
        year = time.strftime("%Y",time.localtime())

        # Moving insertion point to the beginning of the file.
        bof = self.view.text_point(0,0)
        self.view.sel().clear()
        self.view.sel().add(sublime.Region(bof))
        self.view.show(bof)

        # Inserting template/snippet
        self.view.run_command("insert_snippet",
            {
                "name"    : template,
                "FILENAME": filename,
                "AUTHOR"  : author,
                "COMPANY" : company,
                "CDATE"   : date,
                "MDATE"   : date,
                "YEAR"    : year
            })
        print('vhdl-mode: Inserted header template.')

And then the snippet I use with this is:

<snippet>
	<!--
		Current fields supported:
			FILENAME : Will fill in the current buffer name if found, if not
			           found, will fill in the file name, and if that's not
			           found will fill in a default value.
			AUTHOR   : This uses the vhdl-author setting in the settings file.
			COMPANY  : This uses the vhdl-company setting in the settings file.
			CDATE    : Automatically filled in when the header is created.
			MDATE    : Automatically filled in when the header is created and
			           updated when file is saved.
			YEAR     : Automatically filled in when the header is created.

		Numeric fields are tabbed between when snippet is inserted.

		TODO: Take project name, platform, and standard from project
		file.

		Edit header to taste and need.
	-->
	<content><![CDATA[
-------------------------------------------------------------------------------
-- Title       : ${1:<Title Block>}
-- Project     : ${2:<Project Name>}
-------------------------------------------------------------------------------
-- File        : ${FILENAME}
-- Author      : ${AUTHOR}
-- Company     : ${COMPANY}
-- Created     : ${CDATE}
-- Last update : ${MDATE}
-- Platform    : Generic (No device specific behavior specified.)
-- Standard    : VHDL'93, Math Packages
-------------------------------------------------------------------------------
-- Copyright (c) ${YEAR} ${COMPANY}
--
-- This document contains controlled technology or technical data under the
-- jurisdiction of the Export Administration Regulations (EAR), 15 CFR 730-774.
-- It cannot be transferred to any foreign third party without the specific
-- prior approval of the U.S. Department of Commerce Bureau of Industry and
-- Security (BIS). Violations of these regulations are punishable by fine,
-- imprisonment, or both.
-------------------------------------------------------------------------------
-- Description: $4
-------------------------------------------------------------------------------
-- Revisions:  Revisions and commentary regarding such are controlled by
-- the revision control system in use (Rational Team Concert / Jazz).  That
-- tool should be consulted on revision history.
-------------------------------------------------------------------------------
$0
]]></content>
	<tabTrigger>header</tabTrigger>
	<scope>source.vhdl</scope>
</snippet>

Hope that helps. It’s probably slightly more elaborate than desired, but maybe it’s got something useful in it.

3 Likes

#22

Just to clear up any possible confusion, the technique mentioned in the linked post only works when you are manually invoking the insert_snippet command yourself to insert a snippet into the buffer. That is to say, you can’t use it to add your own variables to snippets that are invoked automatically by Sublime via tab triggers because in that case it’s Sublime that’s invoking the insert_snippet command on your behalf.

The insert_snippet command accepts the following arguments (see here):

  • name lets you specify the name of the snippet file to get the contents from
  • contents lets you specify the contents of the snippet on the fly instead of using a snippet file

If you pass it any other arguments, the name of those arguments become the name of extra variables that can be expanded in the snippet, and the values of the arguments become the value of the variables. This is why you can’t use this for “standard” snippet expansions; Sublime can’t know what arguments to pass or what their values should be unless you tell it explicitly.

The command insert_date_one executes the insert_snippet command to insert the snippet you provided in your post above. It passes the extra argument DATE with a value that is the current date and time, so when the snippet expands ${DATE} gets expanded.

import sublime, sublime_plugin, time

class InsertDateOne(sublime_plugin.TextCommand):
    def run(self, edit):
        date = time.strftime("<%d-%m-%Y  %H:%M>")
        self.view.run_command("insert_snippet", {
            "name": "Packages/User/testdatumu.sublime-snippet",
            "DATE": date
            })

The command insert_date_two is functionally identical, only here instead of specifying the name of a snippet that exists on disk it specifies the content of the snippet inline instead, so no snippet file needs to exist for this one to work. It still works the same way, by providing an extra DATE argument that becomes a DATE variable.

import sublime, sublime_plugin, time

class InsertDateTwo(sublime_plugin.TextCommand):
    def run(self, edit):
        date = time.strftime("<%d-%m-%Y  %H:%M>")
        self.view.run_command("insert_snippet", {
            "contents": "Date - {$DATE}",
            "DATE": date
            })

For the sake of completeness, insert_date_three does the same thing except it uses insert instead of insert_snippet. The main reason for using a snippet is that you can specify fields (providing optional default values) for the user to tab through. Your example doesn’t do that and just wants to insert text, so insert_snippet isn’t technically needed.

import sublime, sublime_plugin, time

class InsertDateThree(sublime_plugin.TextCommand):
    def run(self, edit):
        date = time.strftime("<%d-%m-%Y  %H:%M>")
        self.view.run_command("insert", {
            "characters": "Date - %s" % date
            })

In all three cases, the plugin creates a command that inserts the date, but you still need to be able to run the command to make the insertion happen. There are a variety of ways that you can go, depending on what you’re trying to do and/or how often you need to do this. Some examples are:

Create a key binding to invoke the command:

    { "keys": ["ctrl+alt+d"], "command": "insert_date_one" },

Add it to the command palette by creating a Default.sublime-commands file in your User package:

[
    { "caption": "Insert Current Date", "command": "insert_date_one"},
]

Add it to the main menu (here in the Edit menu) by creating a Main.sublime-menu file in your User package:

[
   {
     "id": "edit",
     "children":
     [
        { "caption": "-" },
        { "caption": "Insert Current Date", "command": "insert_date_one"},
     ]
   },
]

Add it to the context menu of all edit windows by creating a Context.sublime-menu file in your User package:

[
    { "caption": "-", "id": "end" },
    { "caption": "Insert Current Date", "command": "insert_date_one"},
]

As a final note, the original plugin code iterates over all of the selections replacing them (or inserting if there is no selection) inserting the date and time. The insert_snippet and insert commands do that internally as well, so all of the sample commands here will work the same way as your example code does.

5 Likes

How to auto insert current date time in snippet
#23

I’m beginner with ST3, I know only html and css and my english is bad. So, thank you for your patience and good replies without flame. Now it works how I need and now I know what I must to do in future.
Sublimetext have best and kindly community. My problem is solved.

0 Likes

#24

Thanks!

I think there might be missing an opening bracket for keybinding string. Mine worked with { “keys”: [“f5”], “command”: “insert_datetime”}

0 Likes

#25

I added date and time in my snippets using custom plugin, Check this video:

0 Likes

#27

For what it’s worth, EnhancedSnippets can also do this out of the box as well.

0 Likes