Getting the Sublime Text recently closed file list with the API - sublime-text-plugin

Is there any way to get the list of recently closed files using the Sublime Text API?
The SO Where is the list of recent files stored? question says they are stored in the Session.sublime_session config file, although I think that file is only updated when ST closes and files closed during the current session are in Auto Save Session.sublime_session.
However the .sublime_session files can not be loaded using the API's load_settings(base_name) method. I am not at all sure it would be safe to open a .sublime_session file directly.
You can open the most recently closed files using the following command (indexed from 0)...
sublime.active_window().run_command('open_recent_file', {"index": 0})
...but is there a way of getting a list of the recently closed files instead (with the API)?
If not, would it be safe to open Auto Save Session.sublime_session for reading?
Thanks.

Firstly, as far as I can tell, it is safe to open Auto Save Session.sublime_session for reading.
Auto Save Session.sublime_session is the file which has the 'live' data in it for ST v3; it looks like ST v2 just uses Session.sublime_session and does not use an auto save equivalent.
The list of recently closed files is stored in the JSON using the file_history key. However it is more complex than I had realized. Recently closed file lists are held for each individual window, this can be seen easily if there are multiple ST windows open, Open Recent in the file menu will show you which files have been recently closed in that window only.
The recently closed file lists (note: plural) can be retrieved using something like the following:
win_index = 0
auto_save_session_path = "/path/to/Auto Save Session.sublime_session"
with open(auto_save_session_path) as session_data_file:
session_data = json.load(session_data_file)
recently_closed_files = session_data["windows"][win_index]["file_history"]
Clearly that retrieves just the first window's file_history, to get them all it would be necessary to loop through the list of window entries held in the windows key.
So which window in the JSON corresponds to the active ST window?
Unfortunately this turns out to be more tricky than I'd hoped. Each entry in the windows key list has a helpful sounding window_id, e.g. "window_id": 425, but its value does NOT correspond to the integer returned by the API's sublime.active_window().id() method. The JSON "window_id": 425 entry in my file corresponded to window id() number 3. Clearly ST holds (at least) two different IDs for each window, one for the .sublime_session files and one for the Python API.
The only way I can see to ID the active window is by using the window's currently open buffers. Each entry in the JSON windows key list has a buffers list which holds the currently open files in the window, these could be compared to the files open in the active window (which could be retrieved using the API) to determine which window entry in the JSON file contains the recently closed file list of the active ST window.
This method would have some theoretical pitfalls. For example it wouldn't work if there were 2 windows open with no open files in them or if a single file (the same one) was open in 2 windows. Of course in real world usage this wouldn't generally happen; multiple windows are opened by users so that they can have different files in them.
It turns out that there is a another problem; the frequency with which Auto Save Session.sublime_session is updated. I don't think there is a static fixed time interval. Saving a file triggers an immediate update, but opening and closing files and windows do not, and often there is a gap of at least several minutes between updates.
This means that a plugin that uses the recently closed file list from a .sublime_session file can not even guarantee to contain the most recently closed file.
Keith's suggestion to monitor file closures and maintain an independent list of recently closed files, as done by GotoRecent, would seem to be the way forward, until such time as the ST API adds the ability to get the recently closed files lists.
I hope this helps anyone looking into this issue or who wants to use a .sublime_session file for some other data.

Related

Editing the Registry for `.mp3` file

Editing the Registry for .mp3 file, with refrence from answer given here :
Create registry entry to associate file extension with application in C++
i wrote the following code in c++ , to add open_wihtNewAPp in contex menu for .mp3 files.
Registry::SetValue("HKEY_CURRENT_USER\\Software\\Classes\\mp3file\\shell\\open_wihtNewAPp\\command", nullptr, "C:\\Users\\Devansh\\Desktop\\GUI.exe \"%1\"");
Registry::SetValue("HKEY_CURRENT_USER\\Software\\Classes\\.mp3", nullptr, "mp3file");
But the option is not getting added in context menu.
I checked in regedit as well, the key has been added successfully.
EDIT:
snapshot of context menu on .mp3
I can't find anything in the linked question that looks like your approach. Computers are rather exact. If they look for HKEY_CURRENT_USER\Software\Classes\mp3file\shell\open\command, then do not expect HKEY_CURRENT_USER\Software\Classes\mp3file\shell\open_wihtNewAPp to work. Even a spelling error as small as "wiht" part is already too much, let alone the entire _wihtNewAPp part.

Can I queue a delete on a file?

I have data in memory that represents an image. I want to open the image in the default program to open images. Therefore, I create a temporary file, write the data to it, and then open the file with the default application. Currently, I am using Qt to do the last step via QDesktopServices::openUrl ( const QUrl & url ). The problem is that I now have this random file lying around on disk. Is there a way that I can queue a delete on the file so that after the app closes it gets deleted?
As far as OS is concerned, I'd prefer a os independent solution, but I am guessing that none probably exists. Therefore, if you could link to/post how to do it in linux/osx/windows, that would be really helpful.
On a POSIX system (any Unix or Linux machine), there's a nice trick you can take advantage of: you can remove the directory entry for the file with unlink after opening the file. As long as you keep an open filehandle on the file, it will not be removed, but once you've closed it, the filesystem will automatically reclaim the storage.

GetFileAttributes treat normal file as hidden file during frequent rename action

I am facing some issues with this function GetFileAttributes().
I am using C++ to get windows OS notifications and process them. For a particular case of frequent rename action on a single file, some times we are getting FILE_ATTRIBUTE_HIDDEN for those file. I am using Windows 7 Profession Service Pack 1.
Assume I have a pdf file say test.pdf. We are monitoring a directory say (D:\Test) using automatic directory monitoring in windows os. I am renaming the file (D:\Test\test.pdf) frequently as test1.pdf, test12.pdf, test123.pdf and so on.
I got rename notifications for each of the above actions. We used to check the file attributes for each notifications and if it is hidden file, we won't process further. While checking the file attributes, some times it shows as FILE_ATTRIBUTE_HIDDEN for the file. Is there any known issue with GetFileAttributes() ?
Is there any other thing I could try instead of GetFileAttributes ?

Custom folder icons with desktop.ini & instant refreshing

I am tasked with creating a book-keeping program that tracks some statistics of when files and folders are read. Similar to Google Drive and TortoiseSVN, the folder and file icons should reflect certain changes. For instance, a USB with files that haven't been viewed on a certain computer have an 'x', whereas viewed files get a 'o'.
I can track file usage with this Windows API, and icons (as well as some other nice options) can be changed by the desktop.ini files [1,2,3,4].
While manually messing around with desktop.ini files, I've successfully changed icons, descriptions, and other fun stuff. The problem is that the new changes don't update until Windows parses the desktop.ini file again. This tends to happen inconsistently between a few seconds to several minutes. F5 refreshes do not force a reparse, but will update the image if a reparse has occurred.
How do I force Windows to reparse desktop.ini files both manually and (more importantly) in a C++ program?
Is there an alternative C++ Windows API that can change folder icons immidiately?
If you edit desktop.ini, it Explorer won't refresh automatically. Use SHGetSetFolderCustomSettings to write to it:
SHFOLDERCUSTOMSETTINGS fcs = {0};
fcs.dwSize = sizeof(SHFOLDERCUSTOMSETTINGS);
fcs.dwMask = FCSM_ICONFILE;
fcs.pszIconFile = iconPath;
fcs.cchIconFile = 0;
fcs.iIconIndex = iconIndex;
SHGetSetFolderCustomSettings(&fcs, folderPath, FCS_FORCEWRITE);
If you wish to have different folder icons to indicate different states distinctively (similar to SVN) then you need icon overlays. Changing folder icons is not the suitable solution. The changes in folder icons will reflect instantaneously
If you need further details, Please let me know.

How do I reliably determine if a file is already opened in Microsoft Excel?

I am implementing an interface to Excel. I am using COM to automate Excel directly from C++. Most of my application is working reliably.
I however cannot detect if a file is already opened in Excel. If it is open, then I would like to inform the user to close it before running their simulation.
I am not using MFC, VB, or .NET. My solution has to work for Excel versions 97 to 2010. If I can know the version of Excel programmatically, it is OK to use different techniques for different excel versions.
I was looking for a file with the name "~$xxx" (where "xxx" is the original file name) in the same folder to determine if Excel has created a session lock. But this technique does not always work.
A similar question is once the simulation is started in my program, I want to prevent the user from opening the file in Write mode (read-only mode is OK).
I don't work with C++ but using the same logic from VB.net, this C++ code probably should do what you want? I haven't tested it though... This also wouldn't need you to check for any specific Excel version as such. For .xlsx or any other extension, simply replace the extension below.
std::ofstream ofs("MyFile.xls");
if(ofs.is_open())
{
//~~> File is ready for output
}
Else
{
//~~> File is NOT ready for output
}
EDIT:
You also might want to see this?
Topic: FileInfo::IsReadOnly Property
Link: http://msdn.microsoft.com/en-us/library/system.io.fileinfo.isreadonly.aspx#Y0
Quote From above link
Gets or sets a value that determines if the current file is read only.
Namespace: System.IO
Assembly: mscorlib (in mscorlib.dll)