SublimeText可以在无须将文件存盘、保存更改的情况下将软件关闭,而不丢失会话状态,我养成了打开N个文件的习惯,其中很多都是未存盘的、未保存更改的;想要清理的时候发现不能方便地判断一些处于“未保存”状态的文件是否已被删除,所以写了个小插件,在状态栏显示已打开多少个文件,以及当前文件的具体状态:未存盘、已删除、已保存、未保存。
效果预览:

显示格式为[当前window打开的文件数量 ~ 文件状态],SAVED / UNSAVED / NONE / DEL 分别代表已保存、文件存在但未保存更改、文件不再盘上、文件之前在盘上但已被删除。当然,格式和代号你可以根据喜好修改。
本文插件以及更多插件已在github开源,此repo中还有表格转换、html处理、时间转换等一些小工具,欢迎使用、反馈。
实现方案
在SublimeText3\Data\Packages\User\目录下新建show_file_status.py文件,内容如下:
import os.path
import sublime
import sublime_plugin
class ShowFileStatus(sublime_plugin.EventListener):
    def update_file_status(self, view):
        if not view.file_name():
            status = "NONE"
        elif not os.path.exists(view.file_name()):
            status = "DEL"
        elif view.is_dirty():
            status = "UNSAVED"
        else:
            status = "SAVED"
        window = sublime.active_window()
        status = str(len(window.views())) + " ~ " + status
        view.set_status(self.KEY_SIZE, "[%s]" % status)
    on_post_save_async = update_file_status
    on_modified_async = update_file_status
    on_activated_async = update_file_status
	
另一种方案:
官方repo中的StatusBarFileSize这个package可以在状态栏显示当前文件的体积,它是结合文件编码进行计算的,稍微有一点耗性能,如果你需要它提供的这个功能的话,可在安装完成后,参考下面的代码进行一些修改,也可以实现本文主题的功能。
效果预览:

安装完毕后,替换SublimeText3\Data\Packages\StatusBarFileSize\下的StatusBarFileSize.py为以下内容:
import os.path
import sublime
import sublime_plugin
# Format a size in bytes into a nicer string value. Defaults to 1024 convention.
def file_size_str(size, divisor=1024):
    sizes = ["KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "ZiB", "YiB"]
    if size < divisor:
        return "%d %s" % (size, "Bytes" if size != 1 else "Byte")
    else:
        size_val = size / divisor
        for unit in sizes:
            if size_val >= divisor:
                size_val /= divisor
            else:
                return "%.2f %s" % (size_val, unit)
        return "%.2f %s" % (size_val * divisor, sizes[-1])
# Far from a perfect system, but seems to be the only way to get a usable Python
# encoding from Sublime Text.
SPECIAL_HEXADECIMAL = "special-hexadecimal"
ENCODING_MAP = {
    "Undefined": "ascii",
    "Hexadecimal": SPECIAL_HEXADECIMAL,
    "UTF-8": "utf-8",
    "UTF-16 LE": "utf-16le",
    "UTF-16 BE": "utf-16be",
    "Western (Windows 1252)": "windows-1252",
    "Western (ISO 8859-1)": "iso-8859-1",
    "Western (ISO 8859-3)": "iso-8859-3",
    "Western (ISO 8859-15)": "iso-8859-15",
    "Western (Mac Roman)": "mac_roman",
    "DOS (CP 437)": "cp-437",
    "Arabic (Windows 1256)": "windows-1256",
    "Arabic (ISO 8859-6)": "iso-8859-6",
    "Baltic (Windows 1257)": "windows-1257",
    "Baltic (ISO 8859-4)": "iso-8859-4",
    "Celtic (ISO 8859-14)": "iso-8859-14",
    "Central European (Windows 1250)": "windows-1250",
    "Central European (ISO 8859-2)": "iso-8859-2",
    "Cyrillic (Windows 1251)": "windows-1251",
    "Cyrillic (Windows 866)": "windows-866",
    "Cyrillic (ISO 8859-5)": "iso-8859-5",
    "Cyrillic (KOI8-R)": "koi8_r",
    "Cyrillic (KOI8-U)": "koi8_u",
    "Estonian (ISO 8859-13)": "iso-8859-13",
    "Greek (Windows 1253)": "windows-1253",
    "Greek (ISO 8859-7)": "iso-8859-7",
    "Hebrew (Windows 1255)": "windows-1255",
    "Hebrew (ISO 8859-8)": "iso-8859-8",
    "Nordic (ISO 8859-10)": "iso-8859-10",
    "Romanian (ISO 8859-16)": "iso-8859-16",
    "Turkish (Windows 1254)": "windows-1254",
    "Turkish (ISO 8859-9)": "iso-8859-9",
    "Vietnamese (Windows 1258)": "windows-1258",
}
CONSTANT_OVERHEAD = {
    # Apparently ST doesn't add BOMs.
    # "UTF-16 LE": 2,
    # "UTF-16 BE": 2,
}
# Ditto for line endings. At least there's only three forms here.
LINE_ENDINGS_MAP = {
    "Unix": "\n",
    "Windows": "\r\n",
    "CR": "\r",
}
BLOCK_SIZE = 1000
def ranges(start, end, bs):
    i = 0
    while i < end:
        yield (i, min(i + bs, end))
        i += bs
def count_hex_digits(s):
    # Count hexadecimal digits in s.
    return sum(1 for x in s if x in "abcdefABCDEF0123456789")
def estimate_file_size(view):
    tag = view.change_count()
    try:
        line_endings = LINE_ENDINGS_MAP[view.line_endings()]
        encoding = ENCODING_MAP[view.encoding()]
        overhead = CONSTANT_OVERHEAD.get(view.encoding(), 0)
    except KeyError:
        # Unknown encoding or line ending, so we fail.
        return None
    size = overhead
    for start, end in ranges(0, view.size(), BLOCK_SIZE):
        if view.change_count() != tag:
            # Buffer was changed, we abort our mission.
            return None
        r = sublime.Region(start, end)
        text = view.substr(r)
        if encoding == SPECIAL_HEXADECIMAL:
            # Special-case handling for the special-case Hexadecimal encoding.
            # The division doesn't truncate on purpose, to count half-bytes when
            # we have uneven numbers of hex digits. The result gets forced into
            # an int on return.
            size += count_hex_digits(text) / 2
        else:
            try:
                size += len(text.replace("\n", line_endings).encode(encoding))
            except UnicodeError:
                # Encoding failed, we just fail here.
                return None
    return int(size)
class StatusBarFileSize(sublime_plugin.EventListener):
    KEY_SIZE = "FileSize"
    SETTINGS = "StatusBarFileSize.sublime-settings"
    ESTIMATE_DEFAULT = True
    @property
    def setting_estimate_file_size(self):
        settings = sublime.load_settings(self.SETTINGS)
        return settings.get("estimate_file_size", self.ESTIMATE_DEFAULT)
    def update_file_size(self, view):
        if not view.file_name():
            status = "NONE"
        elif not os.path.exists(view.file_name()):
            status = "DEL"
        elif view.is_dirty():
            status = "UNSAVED"
        else:
            status = "SAVED"
        window = sublime.active_window()
        status = str(len(window.views())) + " ~ " + status
        if not view.file_name() or view.is_dirty():
            if self.setting_estimate_file_size:
                # Try to estimate the file size based on encoding and line
                # endings.
                size = estimate_file_size(view)
                pattern = "~%s"
            else:
                size = None
        else:
            try:
                size = os.path.getsize(view.file_name())
                pattern = "%s"
            except OSError:
                size = None
        if size is not None:
            view.set_status(self.KEY_SIZE, ("[%s] " % status + pattern % file_size_str(size)))
        else:
            view.set_status(self.KEY_SIZE, "[%s]" % status)
    on_post_save_async = update_file_size
    on_modified_async = update_file_size
    on_activated_async = update_file_size
参考资料
-- EOF --
本文最后修改于7年前 (2018-09-18)

 读取中...
读取中...