-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathSessionSaver.cmd
More file actions
202 lines (195 loc) · 7.13 KB
/
SessionSaver.cmd
File metadata and controls
202 lines (195 loc) · 7.13 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
/*
C:\Windows\Microsoft.NET\Framework64\v4.0.30319\csc /target:winexe /platform:x86 "%~0"
exit /b
After running in windows. This SessionSaver.CMD file becomes SessionSaver.exe
It is one of 2 methods this one saves files with a date for mixed usage the other
is SessionSaverDialog which asks for a Folder to be used for -appdata collections.
The idea is to allow saving the current set of open tabs for edit and reuse.
See the example at https://github.com/sumatrapdfreader/sumatrapdf/issues/43
It should be run from advanced settings entry pointing to same folder as SumatraPDF-settings.txt
ExternalViewers [
[
CommandLine = C:\Users\ path to folder \SumatraPDF\SessionSaver.exe
Name = Session &Saver
Key = s
]
]
*/
using System;
using System.IO;
using System.Text;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
class SessionSaver
{
static void Main(string[] args)
{
string exeDir = AppDomain.CurrentDomain.BaseDirectory;
string settingsPath = Path.Combine(exeDir, "SumatraPDF-settings.txt");
if (!File.Exists(settingsPath))
{
MessageBox.Show(
"SumatraPDF-settings.txt not found in:\n" + exeDir,
"Session Saver Error", MessageBoxButtons.OK, MessageBoxIcon.Error
);
return;
}
string text = File.ReadAllText(settingsPath, Encoding.UTF8);
// Extract SessionData block
string sessionBlock = ExtractBlock(text, "SessionData");
if (sessionBlock == null)
{
MessageBox.Show(
"No SessionData block found.",
"Session Saver Error", MessageBoxButtons.OK, MessageBoxIcon.Error
);
return;
}
// Get all file paths from SessionData (TabStates)
List<string> sessionFiles = ExtractFilePaths(sessionBlock);
if (sessionFiles.Count == 0)
{
MessageBox.Show(
"No FilePath entries found in SessionData.",
"Session Saver Error", MessageBoxButtons.OK, MessageBoxIcon.Error
);
return;
}
// Extract FileStates block
string fileStatesBlock = ExtractBlock(text, "FileStates");
if (fileStatesBlock == null)
{
MessageBox.Show(
"No FileStates block found.",
"Session Saver Error", MessageBoxButtons.OK, MessageBoxIcon.Error
);
return;
}
// Extract individual FileStates child blocks
List<string> allFileStateBlocks = ExtractChildBlocks(fileStatesBlock);
// Filter FileStates to only those matching session filenames
List<string> matchingFileStates = FilterFileStates(allFileStateBlocks, sessionFiles);
// Build output
string output = BuildSessionFile(matchingFileStates, sessionBlock);
// Timestamp filename
string timestamp = DateTime.Now.ToString("yyyy-MM-dd-HH_mm_ss");
string outFile = Path.Combine(exeDir, "Session-" + timestamp + ".txt");
File.WriteAllText(outFile, output, Encoding.UTF8);
System.Windows.Forms.MessageBox.Show(
"Saved session to:\n" + outFile,
"Session Saver", MessageBoxButtons.OK, MessageBoxIcon.Information
);
}
// Extracts a named block like "SessionData [ ... ]" with nested brackets
static string ExtractBlock(string text, string blockName)
{
int nameIndex = text.IndexOf(blockName, StringComparison.Ordinal);
if (nameIndex < 0)
return null;
int firstBracket = text.IndexOf('[', nameIndex);
if (firstBracket < 0)
return null;
int depth = 0;
int i = firstBracket;
for (; i < text.Length; i++)
{
char c = text[i];
if (c == '[') depth++;
else if (c == ']') depth--;
if (depth == 0)
{
return text.Substring(nameIndex, i - nameIndex + 1);
}
}
return null;
}
// Extracts all FilePath = ... lines from a block
static List<string> ExtractFilePaths(string block)
{
var list = new List<string>();
using (var reader = new StringReader(block))
{
string line;
while ((line = reader.ReadLine()) != null)
{
int idx = line.IndexOf("FilePath", StringComparison.Ordinal);
if (idx < 0) continue;
int eq = line.IndexOf('=', idx);
if (eq < 0) continue;
string path = line.Substring(eq + 1).Trim();
if (path.Length > 0)
list.Add(path);
}
}
return list;
}
// Extracts child [ ... ] blocks inside a parent block (e.g. FileStates)
static List<string> ExtractChildBlocks(string parentBlock)
{
var blocks = new List<string>();
int i = 0;
bool skippedOuter = false;
while (i < parentBlock.Length)
{
int start = parentBlock.IndexOf('[', i);
if (start < 0) break;
if (!skippedOuter)
{
// Skip the outer "[“ that belongs to "FileStates ["
skippedOuter = true;
i = start + 1;
continue;
}
int depth = 0;
int j = start;
for (; j < parentBlock.Length; j++)
{
char c = parentBlock[j];
if (c == '[') depth++;
else if (c == ']') depth--;
if (depth == 0)
{
blocks.Add(parentBlock.Substring(start, j - start + 1));
i = j + 1;
break;
}
}
if (depth != 0)
break; // malformed
}
return blocks;
}
// Keep only FileStates whose filename matches any SessionData filename
static List<string> FilterFileStates(List<string> blocks, List<string> sessionFiles)
{
var result = new List<string>();
foreach (string block in blocks)
{
var paths = ExtractFilePaths(block);
if (paths.Count == 0) continue;
string filePath = paths[0];
string baseName = Path.GetFileName(filePath);
bool match = sessionFiles.Any(sf =>
string.Equals(Path.GetFileName(sf), baseName, StringComparison.OrdinalIgnoreCase));
if (match)
result.Add(block);
}
return result;
}
// Build final session file content
static string BuildSessionFile(List<string> fileStates, string sessionBlock)
{
var sb = new StringBuilder();
sb.AppendLine("FileStates [");
foreach (string fs in fileStates)
{
sb.AppendLine(fs);
}
sb.AppendLine("]");
sb.AppendLine();
sb.AppendLine(sessionBlock.TrimEnd());
sb.AppendLine();
return sb.ToString();
}
}