Updating the tab/file status after saving in a Sublime Text Plugin - sublimetext

This may be an old bug; I found this report. I'm using Sublime 3 but I think this code also works on 2.
When I call self.view.run_command('save') within a plugin, the save does happen -- I can type the file in a console window and see the results. The dirty flag seems to get cleared. But the tab for the file contains a dot rather than an x, indicating the file hasn't been saved. And sure enough, if you try to close it, it asks if you want to save the file.
Is there any way to refresh the file window so it recognizes that the file has been saved?
Here's my plugin code: (This is my first plugin so please excuse obvious style issues)
# Sublime Text plugin to insert output in the OUTPUT_SHOULD_BE comment
# Bind to key with:
# { "keys": ["f12"], "command": "insert_output" },
import sublime, sublime_plugin, pprint, os, re
class InsertOutputCommand(sublime_plugin.TextCommand):
def run(self, edit):
outfile = self.view.file_name().rsplit('.')[0] + ".out"
if not os.path.exists(outfile):
sublime.error_message("Not Found: " + outfile)
return
out_data = open(outfile).read().strip()
region = self.view.find(r"/\* OUTPUT_SHOULD_BE\n", 0)
if region:
self.view.insert(edit, region.end(), out_data)
self.view.run_command('save')
self.view.window().focus_view(self.view)
else:
sublime.error_message("Not Found: OUTPUT_SHOULD_BE")

I'm sure this is probably a terrible hack, but it works:
self.view.run_command("save")
# Refresh the buffer and clear the dirty flag:
sublime.set_timeout(lambda: self.view.run_command("revert"), 10)
The revert command, which must be delayed in order to work, simply brings back whatever is stored in the file. Since the file was successfully saved on disk, this is just the same file that we already see on the screen. In the process, the dirty flag is cleared and the dot on the file tab becomes an x.
Feels very hacky to me and I'd love a more proper solution. But at least it works, ugly or not.

Related

after opening a file check if the file was modified on close

I am wondering if I am doing it the correct way.
def checkout
clone = system( "svn export #{file} tmp/" )
open_file = system( "start tmp/#{#file}" )
end
Now, I am able to open the file I want with the default editor but how to record if the file was modified before close.
Should I create a Process and do Process.wait or something?
Thanks for your help
Use File::mtime method for the same.
Returns the modification time for the named file as a Time object.
file_time_before_opening = File.mtime('your file/path')
# do file operation as you like
file_time_after_closing = File.mtime('your file/path')
# now compare file_time_before_opening and file_time_after_closing to know
# if it is modified or not.
If you mean you are using start in Windows, use /wait or /w option to make it wait until the editor termination.
Use IO::read to check file content modification. (before, after the editor execution).
before = IO.read('tmp/#{#file}', {mode: 'rb'})
system("start /wait tmp/#{#file}")
after = IO.read('tmp/#{#file}', {mode: 'rb'})
# Check the file content modification.
if before != after:
# File changed!
If you're editing a huge file, IO::read will consume memroy accordingly. Use File::mtime as Arup Rakshit suggested, if there's such huge file in your repository. (cons: false positive alarm for save without modification)

Completely disable IPython output caching

I'm dealing with some GB-sized numpy arrays in IPython. When I delete them, I definitely want them gone, in order to recover the memory. IPythons output cache is quite annoying there, as it keeps the objects alive even after deleting the last actively intended reference to them. I already set
c.TerminalInteractiveShell.cache_size = 0
in the IPython configuration, but this only disables caching of entries to _oh, the other variables like _, __ and so on are still created. I'm also aware of %xdel, but anyways, I'd prefer to disable it completely, as I rarely use the output history anyways, so that a plain del would work again right away.
Looking at IPython/core/displayhook.py Line 209-214 I would say that it is not configurable. You could try making a PR to add an option to disable it totally.
Enter
echo "__builtin__._ = True" > ~/.config/ipython/profile_default/startup/00-disable-history.py
and your history should be gone.
Edit:
Seems like the path to the config directory is sometimes a bit different, either ~/.config/ipython or just ~/.ipython/. So just check which one you got and adjust the path accordingly. The solution still works with jupyter console.
Seems that we can suppress the output cache by putting a ";" at the end of the line now.
See http://ipython.org/ipython-doc/stable/interactive/tips.html#suppress-output
Create an ipython profile:
!ipython profile create
The output might be (for ipython v4.0):
[ProfileCreate] Generating default config file: '/root/.ipython/profile_default/ipython_config.py'
[ProfileCreate] Generating default config file: '/root/.ipython/profile_default/ipython_kernel_config.py'
Then add the line 'c.InteractiveShell.cache_size = 0' to the ipython_kernel_config.py file by
!echo 'c.InteractiveShell.cache_size = 0' >> /root/.ipython/profile_default/ipython_kernel_config.py
Load another ipython kernel and check if this work
In [1]: 123
Out[1]: 123
In [2]: _1
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
<ipython-input-51-21553803e553> in <module>()
----> 1 _1
NameError: name '_1' is not defined
In [3]: len(Out)
Out[3]: 0

Copy yaml formatting (indent) from one file to another

A translator completely messed up a yaml file by copying everything into word (don't ask).
I have already cleaned up the file using regexes, but the indent (spacing) is now missing; everything starts at the first character:
es:
default_blocks:
thank_you_html: "thank you text"
instead of
en:
default_blocks:
thank_you_html: "thank you text"
Do you have a good idea on how to automatically copy the format/structure/indent from the correct file (say en.yml) to the corrupt one (say es.yml)? (I'm using textmate 2.0 as editor)
Thanks!
Assuming the original and the translation contain exactly the same strings per line (except for the indentation problem), a quick&dirty script scanning the leading whitespace may solve this:
#!/usr/bin/env ruby
# encoding: UTF-8
indented = File.readlines(ARGV[0]).map do |l|
l.scan(/^\s+/)[0]
end.zip(File.readlines(ARGV[1])).map { |e| e.join }.join
File.open(ARGV[1], "w") { |io| io.write(indented) }
Save it, make it executable and call
./script_name.rb en.yml es.yml
Wouldn't mess with Textmate if this is not a regular task, but you could easily transform this to a command and either prompt for the two files via a dialog or select both in the file browser, open one of them in the current tab and differentiate them via environment variables ($TM_FILEPATH, $TM_SELECTED_FILES)

Reopening closed file: Lua

I have a file called backup.lua, which the program should write to every so often in order to backup its status, in case of a failure.
The problem is that the program writes the backup.lua file completely fine first-time round, but any other times it refuses to write to the file.
I tried removing the file while the program was still open but Windows told me that the file was in use by 'CrysisWarsDedicatedServer.exe', which is the program. I have told the host Lua function to close the backup.lua file, so why isn't it letting me modify the file at will after it has been closed?
I can't find anything on the internet (Google actually tried to correct my search) and the secondary programmer on the project doesn't know either.
So I'm wondering if any of you folks know what we are doing wrong here?
Host function code:
function ServerBackup(todo)
local write, read;
if todo=="write" then
write = true;
else
read = true;
end
if (write) then
local source = io.open(Root().."Mods/Infinity/System/Read/backup.lua", "w");
System.Log(TeamInstantAction:GetTeamScore(2).." for 2, and for 1: "..TeamInstantAction:GetTeamScore(1))
System.LogAlways("[System] Backing up serverdata to file 'backup.lua'");
source:write("--[[ The server is dependent on this file; editing it will lead to serious problems.If there is a problem with this file, please re-write it by accessing the backup system ingame.--]]");
source:write("Backup = {};Backup.Time = '"..os.date("%H:%M").."';Backup.Date = '"..os.date("%d/%m/%Y").."';");
source:write(XFormat("TeamInstantAction:SetTeamScore(2, %d);TeamInstantAction:SetTeamScore(1, %d);TeamInstantAction:UpdateScores();",TeamInstantAction:GetTeamScore(2), TeamInstantAction:GetTeamScore(1) ));
source:close();
for i,player in pairs(g_gameRules.game:GetPlayers() or {}) do
if (IsModerator(player)) then
CMPlayer(player, "[!backup] Completed server backup.");
end
end
end
--local source = io.open(Root().."Mods/Infinity/System/Read/backup.lua", "r"); Can the file be open here and by the Lua scriptloader too?
if (read) then
System.LogAlways("[System] Restoring serverdata from file 'backup.lua'");
--source:close();
Backup = {};
Script.LoadScript(Root().."Mods/Infinity/System/Read/backup.lua");
if not Backup or #Backup < 1 then
System.LogAlways("[System] Error restoring serverdata from file 'backup.lua'");
end
end
end
Thanks all :).
Edit:
Although the file is now written to the disk fine, the system fails to read the dumped file.
So, now the problem is that the "LoadScript" function isn't doing what you expect:
Because I'm psychic, i have divined that you're writing a Crysis plugin, and are attempting to use it's LoadScript API call.
(Please don't assume everyone here would guess this, or be bothered to look for it. It's vital information that must form part of your questions)
The script you're writing attempts to set Backup - but your script, as written - does not separate lines with newline characters. As the first line is a comment, the entire script will be ignored.
Basicallty the script you've written looks like this, which is all treated as a comment.
--[[ comment ]]--Backup="Hello!"
You need to write a "\n" after the comment (and, I'd recommend in other places too) to make it like this. In fact, you don't really need block comments at all.
-- comment
Backup="Hello!"

How do I get the output of an Xcode user script to auto indent?

The Problem
I want to press a key when I have a line highlighted and convert from a single line:
JGLogEntry *logEntry = [JGLogEntry applicationNoWindowsFrom:date1 to:date2 intoMOC:mockRawMOC];
to a multiline statement:
JGLogEntry *logEntry = [JGLogEntry applicationNoWindowsFrom:date1
to:date2
intoMOC:mockRawMOC];
What I've Tried
I've got a simple ruby script that almost gets me there.
#!/usr/bin/env ruby
s = STDIN.read
s.gsub!(/(:.+?\w) (\w.+?)/,'\1' + "\n\t" +'\2')
print s
When I set the output to "Replace Selection", I get this:
JGLogEntry *logEntry = [JGLogEntry applicationNoWindowsFrom:date1
to:date2
intoMOC:mockRawMOC];
When I set the output to "Place on Clipboard", then paste it in, I get the desired result:
JGLogEntry *logEntry = [JGLogEntry applicationNoWindowsFrom:date1
to:date2
intoMOC:mockRawMOC];
However, this is two keypresses which is clumsy.
Any ideas how I can get the replaced text to obey Xcode's auto indent rules?
Check the pre-installed script for "Convert tabs to spaces", and how it executes an in-line applescript. Use that to tell XCode to perform the menu item
Edit > Format > Re-Indent
I'm not sure how you do that with ruby, nor the details about the applescript content, but I would wager it's fairly straight-forward..

Resources