Check-in [41b3d45087]
Not logged in

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Implemented command-line help.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | develop
Files: files | file ages | folders
SHA1: 41b3d45087ad8d7ef349bf5ca87300e434268a83
User & Date: tinus 2018-03-23 21:16:55
Context
2018-05-31
05:59
Bugfix: /? help now works. Enhanced: when the /verbose flag is specified, show the full stack track for exceptions. Refactor: increased code readability by not using `var` when it's not apparent at first glance what the type is going to be. check-in: b80ceff467 user: tinus tags: develop
2018-03-23
21:16
Implemented command-line help. check-in: 41b3d45087 user: tinus tags: develop
2018-03-22
20:36
If the /home parameter is not an existing directory, continue looking at the other possibilities. check-in: e4d5f7bb08 user: tinus tags: develop
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to ZTUpdater/Program.cs.

1
2
3
4
5

6
7
8
9
10
11
12
..
35
36
37
38
39
40
41
42
43
44
45
46


47
48
49
50
51
52
53
54
55
56
57
..
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
..
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












using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;


namespace ZTUpdater
{
    class Program
    {
        [STAThread]
        static int Main(string[] args)
................................................................................
                    else if (arg == "/H" || arg == "/home")
                        OptName = "home";
                    else if (arg == "/b" || arg == "/backup")
                        OptName = "backup";
                    else if (arg == "/a" || arg == "/archive")
                        OptName = "archive";
                    else if (arg.StartsWith("/"))
                        WriteLog(MinimumLevel)($"Unrecognized option '{arg}'", TraceLevel.Warning);
                    else
                        Arguments.Add(arg);
                }



                // Initialize the updater component
                var Updater = new ZTWUpdater()
                {
                    OnLog = WriteLog(MinimumLevel)
                };
                if (Updater.ZTreeHome == null)
                {
                    // ask for folder (using dialog?)
                    var Dialog = new System.Windows.Forms.FolderBrowserDialog
                    {
                        SelectedPath = @"C:\ZTree",
................................................................................
                }
                else
                {
                    var UpdateTask = Updater.UpdateAsync();
                    UpdateTask.Wait();
                    FilesUpdated = UpdateTask.Result;
                }
                WriteLog(MinimumLevel)($"{FilesUpdated} files updated.", TraceLevel.Info);
                return FilesUpdated > 0 ? 0 : 1;
            }
            catch (Exception ex)
            {
                var BackupColor = Console.ForegroundColor;
                Console.ForegroundColor = ConsoleColor.Magenta;
                if (ex is AggregateException)
................................................................................
                Console.ForegroundColor = BackupColor;
                return 255;
            }
        }

        private static void ShowHelp()
        {
            // TODO
            throw new NotImplementedException();








        }

        private static Dictionary<TraceLevel, ConsoleColor> _levelColors = new Dictionary<TraceLevel, ConsoleColor>();











































        private static Action<string, TraceLevel> WriteLog(TraceLevel minimumLevel)
        {
            return (message, level) =>
            {
                if (level <= minimumLevel)
                {









                    if (_levelColors.Count == 0)
                    {
                        _levelColors.Add(TraceLevel.Verbose, ConsoleColor.DarkGray);
                        _levelColors.Add(TraceLevel.Warning, ConsoleColor.Yellow);
                        _levelColors.Add(TraceLevel.Error, ConsoleColor.Red);
                    }
                    var Output = level >= TraceLevel.Warning ? Console.Error : Console.Out;
                    var BackupColor = Console.ForegroundColor;
                    if (_levelColors.TryGetValue(level, out var Color))
                        Console.ForegroundColor = Color;
                    Output.WriteLine(message);
                    Console.ForegroundColor = BackupColor;
                }
            };
        }
    }
}















|
|
>







 







|




>
>



|







 







|







 







|
|
>
>
>
>
>
>
>
>
|

<
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|





>
>
>
>
>
>
>
>
>
|
|
|
|
|
|
|
|
|
|
|
|
|
<
|

|
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
..
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
..
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
..
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
203
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Text;
using System.Text.RegularExpressions;

namespace ZTUpdater
{
    class Program
    {
        [STAThread]
        static int Main(string[] args)
................................................................................
                    else if (arg == "/H" || arg == "/home")
                        OptName = "home";
                    else if (arg == "/b" || arg == "/backup")
                        OptName = "backup";
                    else if (arg == "/a" || arg == "/archive")
                        OptName = "archive";
                    else if (arg.StartsWith("/"))
                        Program.WriteLog($"Unrecognized option '{arg}'", TraceLevel.Warning);
                    else
                        Arguments.Add(arg);
                }

                var WriteLog = CreateLogWriter(MinimumLevel);

                // Initialize the updater component
                var Updater = new ZTWUpdater()
                {
                    OnLog = WriteLog
                };
                if (Updater.ZTreeHome == null)
                {
                    // ask for folder (using dialog?)
                    var Dialog = new System.Windows.Forms.FolderBrowserDialog
                    {
                        SelectedPath = @"C:\ZTree",
................................................................................
                }
                else
                {
                    var UpdateTask = Updater.UpdateAsync();
                    UpdateTask.Wait();
                    FilesUpdated = UpdateTask.Result;
                }
                WriteLog($"{FilesUpdated} files updated.", TraceLevel.Info);
                return FilesUpdated > 0 ? 0 : 1;
            }
            catch (Exception ex)
            {
                var BackupColor = Console.ForegroundColor;
                Console.ForegroundColor = ConsoleColor.Magenta;
                if (ex is AggregateException)
................................................................................
                Console.ForegroundColor = BackupColor;
                return 255;
            }
        }

        private static void ShowHelp()
        {
            string Name = Path.GetFileNameWithoutExtension(typeof(Program).Assembly.Location);
            var Lines = new List<string>
            {
                $@"{Name} [/v | /verbose] [/home ZTHOMEDIR] [/backup BACKUPDIR] [/archive ARCHIVEDIR] [UPDATEZIPFILE]",
                "",
                $@"/verbose             Display more messages.",
                $@"/home ZTHOMEDIR      ZTreeWin's installation directory. If not specified, {Name} attempts to determine it automatically. Failing that, it must be browsed interactively.",
                $@"/backup BACKUPDIR    Where to save backups of files replaced during an update. Default is %#ZTHome%\Backup.",
                $@"/archive ARCHIVEDIR  Where to save downloaded update files. Default is the user's Downloads directory.",
                $@"UPDATEZIPFILE        A zip file containing a version of ZTreeWin to install. If not specified, {Name} will check for an update online, and if one is found, will automatically download it, and install that."
            };


            // Scale the text to fit the console width
            int TabPos = 0;
            var rexPos = new Regex(@"^((.*?) {2,})(.*)$", RegexOptions.Compiled | RegexOptions.IgnoreCase);
            foreach (var Line in Lines)
            {
                var Match = rexPos.Match(Line);
                if (Match.Success && Match.Groups[1].Length > TabPos)
                    TabPos = Match.Groups[1].Length;
            }
            bool TooSmall = TabPos + 10 > Console.BufferWidth;
            string Prefix = new string(' ', TabPos);
            foreach (var Line in Lines)
            {
                var Match = rexPos.Match(Line);
                if (!Match.Success || TooSmall)
                {
                    Console.WriteLine(Line);
                }
                else
                {
                    string Argument = Match.Groups[2].Value;
                    var Description = new StringBuilder(Match.Groups[3].Value);
                    Console.Write(Argument);
                    Console.Write(new string(' ', TabPos - Argument.Length));
                    if (TabPos + Description.Length < Console.BufferWidth)
                    {
                        Console.WriteLine(Description);
                    }
                    else
                    {
                        // TODO: break on word boundaries, and omit spaces at the start of a new line?
                        Console.Write(Description.Extract(0, Console.BufferWidth - TabPos));
                        while (Description.Length > 0)
                        {
                            Console.Write(Prefix);
                            Console.Write(Description.Extract(0, Console.BufferWidth - TabPos));
                        }
                        Console.WriteLine();
                    }
                }
            }
        }

        private static Action<string, TraceLevel> CreateLogWriter(TraceLevel minimumLevel)
        {
            return (message, level) =>
            {
                if (level <= minimumLevel)
                {
                    WriteLog(message, level);
                }
            };
        }

        private static Dictionary<TraceLevel, ConsoleColor> _levelColors = new Dictionary<TraceLevel, ConsoleColor>();

        private static void WriteLog(string message, TraceLevel level)
        {
            if (_levelColors.Count == 0)
            {
                _levelColors.Add(TraceLevel.Verbose, ConsoleColor.DarkGray);
                _levelColors.Add(TraceLevel.Warning, ConsoleColor.Yellow);
                _levelColors.Add(TraceLevel.Error, ConsoleColor.Red);
            }
            var Output = level >= TraceLevel.Warning ? Console.Error : Console.Out;
            var BackupColor = Console.ForegroundColor;
            if (_levelColors.TryGetValue(level, out var Color))
                Console.ForegroundColor = Color;
            Output.WriteLine(message);
            Console.ForegroundColor = BackupColor;
        }


    }

    static class StringBuilderExtension
    {
        public static string Extract(this StringBuilder sb, int startIndex, int length)
        {
            if (startIndex + length > sb.Length)
                length = sb.Length - startIndex;
            var Result = sb.ToString(startIndex, length);
            sb.Remove(startIndex, length);
            return Result;
        }
    }
}