Skip to content

Commit

Permalink
Added gzip calculation
Browse files Browse the repository at this point in the history
  • Loading branch information
twolfson committed Oct 3, 2015
1 parent cde737e commit 682d974
Show file tree
Hide file tree
Showing 2 changed files with 77 additions and 15 deletions.
87 changes: 73 additions & 14 deletions StatusBarFileSize.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import gzip
import io
import os.path
import sublime
import sublime_plugin
Expand Down Expand Up @@ -73,8 +75,8 @@ def file_size_str(size, divisor=1024):

CONSTANT_OVERHEAD = {
# Apparently ST doesn't add BOMs.
# "UTF-16 LE": 2,
# "UTF-16 BE": 2,
# "UTF-16 LE": b"\xFF\xFE",
# "UTF-16 BE": b"\xFE\xFF",
}

# Ditto for line endings. At least there's only three forms here.
Expand All @@ -99,23 +101,33 @@ def count_hex_digits(s):
return sum(1 for x in s if x in "abcdefABCDEF0123456789")


def get_view_info(view):
line_endings = LINE_ENDINGS_MAP[view.line_endings()]
encoding = ENCODING_MAP[view.encoding()]
overhead = CONSTANT_OVERHEAD.get(view.encoding(), "")
return line_endings, encoding, overhead


def iterate_view_blocks(view):
for start, end in ranges(0, view.size(), BLOCK_SIZE):
r = sublime.Region(start, end)
yield r


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)
line_endings, encoding, overhead = get_view_info(view)
except KeyError:
# Unknown encoding or line ending, so we fail.
return None

size = overhead
for start, end in ranges(0, view.size(), BLOCK_SIZE):
size = len(overhead)
for r in iterate_view_blocks(view):
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:
Expand All @@ -134,36 +146,83 @@ def estimate_file_size(view):
return int(size)


def calculate_gzip_size(view):
tag = view.change_count()

try:
line_endings, encoding, overhead = get_view_info(view)
except KeyError:
# Unknown encoding or line ending, so we fail.
return None

byte_content = io.BytesIO()
with gzip.GzipFile(fileobj=byte_content, mode="wb") as f:
f.write(overhead)
for r in iterate_view_blocks(view):
if view.change_count() != tag:
# Buffer was changed, we abort our mission.
return None
text = view.substr(r)

if encoding == SPECIAL_HEXADECIMAL:
# TODO: Figure out what to do for hexadecimal
return None
else:
try:
f.write(text.replace("\n", line_endings).encode(encoding))
except UnicodeError:
# Encoding failed, we just fail here.
return None
return int(byte_content.tell())


class StatusBarFileSize(sublime_plugin.EventListener):
KEY_SIZE = "FileSize"
SETTINGS = "StatusBarFileSize.sublime-settings"
ESTIMATE_DEFAULT = True
CALCULATE_GZIP_DEFAULT = False

@property
def setting_estimate_file_size(self):
settings = sublime.load_settings(self.SETTINGS)
return settings.get("estimate_file_size", self.ESTIMATE_DEFAULT)

@property
def setting_calculate_gzip(self):
settings = sublime.load_settings(self.SETTINGS)
return settings.get("calculate_gzip", self.CALCULATE_GZIP_DEFAULT)

def update_file_size(self, view):
view.erase_status(self.KEY_SIZE)

size = None
gzip_size = None
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
pattern = "~{size}"
if self.setting_calculate_gzip:
gzip_size = calculate_gzip_size(view)
gzip_pattern = "~{size} ({gzip_size})"
else:
try:
size = os.path.getsize(view.file_name())
pattern = "%s"
pattern = "{size}"
if self.setting_calculate_gzip:
# Faster to use content from buffer than reading on disk
gzip_size = calculate_gzip_size(view)
gzip_pattern = "{size} ({gzip_size})"
except OSError:
size = None
pass

if size is not None:
view.set_status(self.KEY_SIZE, pattern % file_size_str(size))
if gzip_size is not None:
status = gzip_pattern.format(size=file_size_str(size), gzip_size=file_size_str(gzip_size))
else:
status = pattern.format(size=file_size_str(size))
view.set_status(self.KEY_SIZE, status)

on_post_save_async = update_file_size
on_modified_async = update_file_size
Expand Down
5 changes: 4 additions & 1 deletion StatusBarFileSize.sublime-settings
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,8 @@
// contents with the file encoding whenever the buffer is modified, it might
// have a noticeable performance impact when working with large files on
// slower machines.
"estimate_file_size": true
"estimate_file_size": true,
// As a web developer, you might be interested in the gzip size of a file
// use this to calculate said gzip size
"calculate_gzip": false
}

0 comments on commit 682d974

Please sign in to comment.