Skip to content

Instantly share code, notes, and snippets.

@JLChnToZ
Last active December 13, 2025 18:05
Show Gist options
  • Select an option

  • Save JLChnToZ/b744103f50e2e75596d495749bfa8442 to your computer and use it in GitHub Desktop.

Select an option

Save JLChnToZ/b744103f50e2e75596d495749bfa8442 to your computer and use it in GitHub Desktop.
Classic Notepad Clone (Partially) Implementation in PowerShell
using namespace System.IO;using namespace System.IO.Compression;$s=New-Object StreamReader((New-Object DeflateStream((New-Object MemoryStream -ArgumentList @(,[Convert]::FromBase64String('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'))),[CompressionMode]::Decompress)),[Text.Encoding]::UTF8);$d=$s.ReadToEnd();$s.Close();iex $d
using namespace System.IO;using namespace System.Text;using namespace System.Text.RegularExpressions;using namespace System.Drawing;using namespace System.Windows.Forms;$an="LitePad";if($args.Count -gt 0){$Script:fil=$args[0]}$Script:df="Text Files (*.txt)|*.txt|All Files (*.*)|*.*";$Script:enc=[Encoding]::UTF8;Add-Type -AssemblyName System.Drawing;Add-Type -AssemblyName System.Windows.Forms;sal -Name new -Value New-Object;[Application]::EnableVisualStyles();[Application]::SetCompatibleTextRenderingDefault($false);$Script:f=new Form -Property @{Size=new Size(800,600);Icon=[SystemIcons]::Application;MinimumSize=new Size(400,300);Add_FormClosing={$args[1].Cancel=-not(sim)}};$fc=$Script:f.Controls;[void]$fc.Add(($Script:tb=new TextBox -Property @{Dock="Fill";BorderStyle="None";ScrollBars="Both";Multiline=$true;WordWrap=$false;AcceptsTab=$true;AllowDrop=$true;Add_TextChanged={$Script:ui.Enabled=$Script:tb.CanUndo;udv};Add_DragEnter={$args[1].Effect=if($args[1].Data.GetDataPresent([DataFormats]::FileDrop)){[DragDropEffects]::Copy}else{[DragDropEffects]::None}};Add_DragDrop={$files=$args[1].Data.GetData([DataFormats]::FileDrop);if($files.Count -le 0){return}if(-not(sim)){return}$Script:fil=$files[0];opf;udv};Add_KeyUp={udv};Add_MouseUp={udv}}));[void]$fc.Add(($Script:sb=new StatusStrip));$sbi=$Script:sb.Items;[void]$sbi.Add(($Script:stl=new ToolStripButton -Property @{TextAlign="MiddleLeft";Add_Click={sgt}}));[void]$sbi.Add((new ToolStripStatusLabel -Property @{Spring=$true}));[void]$sbi.Add((new ToolStripSeparator));[void]$sbi.Add(($Script:encl=new ToolStripDropDownButton -Property @{Text=$Script:enc.EncodingName}));[void]$fc.Add(($Script:f.MainMenuStrip=(new MenuStrip -Property @{RenderMode=[ToolStripRenderMode]::System})));$m=$Script:f.MainMenuStrip.Items;[void]$m.Add(($sm=new ToolStripMenuItem("&File")));$sm=$sm.DropDownItems;[void]$sm.Add((new ToolStripMenuItem("&New") -Property @{ShortcutKeys=[Keys]::Control -bor [Keys]::N;Add_Click={if(-not(sim)){return}$Script:tb.Clear();$Script:fil=$null;$Script:tb.Modified=$false;$Script:f.Icon=[SystemIcons]::Application;udv}}));[void]$sm.Add((new ToolStripMenuItem("&Open") -Property @{ShortcutKeys=[Keys]::Control -bor [Keys]::O;Add_Click={if(-not(sim)){return}$dlg=new OpenFileDialog -Property @{Filter=$Script:df};if($dlg.ShowDialog() -ne [DialogResult]::OK){return}$Script:fil=$dlg.FileName;opf;udv}}));[void]$sm.Add((new ToolStripMenuItem("&Save") -Property @{ShortcutKeys=[Keys]::Control -bor [Keys]::S;Add_Click={sav $false}}));[void]$sm.Add((new ToolStripMenuItem("Save &As...") -Property @{Add_Click={sav $true}}));[void]$sm.Add((new ToolStripSeparator));[void]$sm.Add((new ToolStripMenuItem("&Exit") -Property @{ShortcutKeys=[Keys]::Control -bor [Keys]::Q;Add_Click={$Script:f.Close()}}));[void]$m.Add(($sm=new ToolStripMenuItem("&Edit")));$sm=$sm.DropDownItems;[void]$sm.Add(($Script:ui=new ToolStripMenuItem("&Undo") -Property @{ShortcutKeys=[Keys]::Control -bor [Keys]::Z;Enabled=$false;Add_Click={if(-not $Script:tb.CanUndo){return}$Script:tb.Undo();$Script:ui.Enabled=$Script:tb.CanUndo}}));[void]$sm.Add((new ToolStripSeparator));[void]$sm.Add((new ToolStripMenuItem("&Cut") -Property @{ShortcutKeys=[Keys]::Control -bor [Keys]::X;Add_Click={$Script:tb.Cut()}}));[void]$sm.Add((new ToolStripMenuItem("C&opy") -Property @{ShortcutKeys=[Keys]::Control -bor [Keys]::C;Add_Click={$Script:tb.Copy()}}));[void]$sm.Add((new ToolStripMenuItem("&Paste") -Property @{ShortcutKeys=[Keys]::Control -bor [Keys]::V;Add_Click={$Script:tb.Paste()}}));[void]$sm.Add((new ToolStripSeparator));[void]$sm.Add((new ToolStripMenuItem("&Select All") -Property @{ShortcutKeys=[Keys]::Control -bor [Keys]::A;Add_Click={$Script:tb.SelectAll()}}));[void]$sm.Add((new ToolStripSeparator));[void]$sm.Add((new ToolStripMenuItem("&Find And Replace...") -Property @{ShortcutKeys=[Keys]::Control -bor [Keys]::F;Add_Click={if($null -ne $Script:ff -and -not $Script:ff.IsDisposed){$Script:ff.Focus();return}$sel=$Script:tb.SelectedText;if(-not [string]::IsNullOrEmpty($sel)){$Script:se=if($Script:fre){[Regex]::Escape($sel)}else{$sel}}elseif($Script:se -eq $null){$Script:se=""}if($Script:re -eq $null){$Script:re=""}$Script:ff=new Form -Property @{Text="Find and Replace";Size=new Size(400,200);MinimumSize=new Size(400,200);MaximumSize=new Size(9999,200);MaximizeBox=$false;MinimizeBox=$false;ShowInTaskbar=$false;ShowIcon=$false;Owner=$Script:f};$Script:ff.Controls.Add(($l=new TableLayoutPanel -Property @{Dock="Fill";RowCount=6;ColumnCount=3}));$ls=$l.ColumnStyles;$ls.Add((new ColumnStyle([SizeType]::Absolute,100)));$ls.Add((new ColumnStyle([SizeType]::Percent,100)));$ls.Add((new ColumnStyle([SizeType]::Absolute,100)));$ls=$l.RowStyles;$ls.Add((new RowStyle([SizeType]::Absolute,30)));$ls.Add((new RowStyle([SizeType]::Absolute,30)));$ls.Add((new RowStyle([SizeType]::Absolute,30)));$ls.Add((new RowStyle([SizeType]::Absolute,30)));$ls.Add((new RowStyle([SizeType]::Absolute,30)));$ls.Add((new RowStyle([SizeType]::Percent,100)));$l=$l.Controls;$l.Add((new Label -Property @{Text="&Find What:";TextAlign="MiddleRight"}),0,0);$l.Add((new TextBox -Property @{Dock="Fill";Text=$Script:se;Add_TextChanged={$Script:se=$args[0].Text}}),1,0);$l.Add(($Script:ff.AcceptButton=new Button -Property @{Text="Find &Next";FlatStyle=[FlatStyle]::System;Add_Click={fin}}),2,0);$l.Add((new Label -Property @{Text="Replace &With:";TextAlign="MiddleRight"}),0,1);$l.Add((new TextBox -Property @{Dock="Fill";Text=$Script:re;Add_TextChanged={$Script:re=$args[0].Text}}),1,1);$l.Add((new Button -Property @{Text="&Replace";FlatStyle=[FlatStyle]::System;Add_Click={if($Script:fre){if($null -ne $Script:lm){$newText=$Script:lm.Result($Script:re);$Script:tb.Select($Script:lm.Index+$Script:lms,$Script:lm.Length);$Script:tb.SelectedText=$newText}}elseif($Script:tb.SelectedText -ieq $Script:se){$Script:tb.SelectedText=$Script:re}fin}}),2,1);$l.Add((new CheckBox -Property @{Text="Search &Backward";Dock="Fill";Checked=$Script:fb -eq $true;FlatStyle=[FlatStyle]::System;Add_CheckedChanged={$Script:fb=$args[0].Checked}}),1,2);$l.Add((new Button -Property @{Text="Replace &All";FlatStyle=[FlatStyle]::System;Add_Click={if([string]::IsNullOrEmpty($Script:se) -or [string]::IsNullOrEmpty($Script:re)){return}if([MessageBox]::Show("Are you sure you want to replace all occurrences of '$Script:se' with '$Script:re'?","Replace All",[MessageBoxButtons]::YesNo,[MessageBoxIcon]::Question) -ne [DialogResult]::Yes){return}$fl=gcf;$mod=$Script:tb.Modified;try{$Script:tb.Text=if($Script:fre){[Regex]::Replace($Script:tb.Text,$Script:se,$Script:re,$fl)}else{$Script:tb.Text.Replace($Script:se,$Script:re,$fl)}}catch{[MessageBox]::Show("An error occurred while performing the replacement.`n`n$($_.Exception.Message)","Replace All",[MessageBoxButtons]::OK,[MessageBoxIcon]::Error)}if($mod){$Script:tb.Modified=$true}}}),2,2);$l.Add((new CheckBox -Property @{Text="Case &Sensitive";Dock="Fill";FlatStyle=[FlatStyle]::System;Checked=$Script:fcs -eq $true;Add_CheckedChanged={$Script:fcs=$args[0].Checked}}),1,3);$l.Add(($Script:ff.CancelButton=new Button -Property @{Text="&Cancel";FlatStyle=[FlatStyle]::System;Add_Click={$Script:ff.Close()}}),2,3);$l.Add((new CheckBox -Property @{Text="Use Regular &Expressions";Dock="Fill";FlatStyle=[FlatStyle]::System;Checked=$Script:fre -eq $true;Add_CheckedChanged={$Script:fre=$args[0].Checked}}),1,4);$Script:ff.Show()}}));[void]$m.Add(($sm=new ToolStripMenuItem("&View")));$sm=$sm.DropDownItems;[void]$sm.Add((new ToolStripMenuItem("&Status Bar") -Property @{Checked=$true;CheckOnClick=$true;Add_Click={$Script:sb.Visible=$args[0].Checked}}));[void]$sm.Add((new ToolStripMenuItem("&Word Wrap") -Property @{Checked=$Script:tb.WordWrap;ShortcutKeys=[Keys]::Alt -bor [Keys]::Z;CheckOnClick=$true;Add_Click={$Script:tb.WordWrap=$args[0].Checked}}));[void]$sm.Add((new ToolStripMenuItem("&Font...") -Property @{Add_Click={$dlg=new FontDialog -Property @{Font=$Script:tb.Font};if($dlg.ShowDialog() -eq [DialogResult]::OK){$Script:tb.Font=$dlg.Font}}}));[void]$sm.Add((new ToolStripSeparator));[void]$sm.Add(($Script:gtl=new ToolStripMenuItem("&Go To Line...") -Property @{ShortcutKeys=[Keys]::Control -bor [Keys]::G;Enabled=$false;Add_Click={sgt}}));[void]$sm.Add((new ToolStripSeparator));[void]$sm.Add(($Script:en=new ToolStripMenuItem("&Encoding")));[void]$m.Add(($sm=new ToolStripMenuItem("&Help")));$sm=$sm.DropDownItems;[void]$sm.Add((new ToolStripMenuItem("&About $an...") -Property @{Add_Click={[MessageBox]::Show("$an`n`n(C)2025","About $an",[MessageBoxButtons]::OK,[MessageBoxIcon]::Information)}}));[Encoding]::GetEncodings()|ForEach-Object{$p=@{Text="$($_.DisplayName)($($_.CodePage))";Tag=$_;Checked=$Script:enc.CodePage -eq $_.CodePage;Add_Click={$ei=$args[0].Tag;$pre=$Script:enc;$Script:enc=$ei.GetEncoding();$Script:encl.Text=$Script:enc.EncodingName;foreach($item in $Script:en.DropDownItems){$item.Checked=$item.Tag.CodePage -eq $ei.CodePage}foreach($item in $Script:encl.DropDownItems){$item.Checked=$item.Tag.CodePage -eq $ei.CodePage}if([MessageBox]::Show("Do you want to re-encode current document to '$($ei.DisplayName)'?","Change Encoding",[MessageBoxButtons]::YesNo,[MessageBoxIcon]::Question) -ne [DialogResult]::Yes){return}$Script:tb.Text=if(-not $Script:tb.Modified -and $null -ne $Script:fil){[File]::ReadAllText($Script:fil,$Script:enc)}else{$Script:enc.GetString($pre.GetBytes($Script:tb.Text))}}};[void]$Script:en.DropDownItems.Add((new ToolStripMenuItem -Property $p));[void]$Script:encl.DropDownItems.Add((new ToolStripButton -Property $p))};function opf{$Script:tb.Text=[File]::ReadAllText($Script:fil,$Script:enc);$Script:tb.SelectionStart=0;$Script:tb.SelectionLength=0;$Script:f.Icon=[Icon]::ExtractAssociatedIcon($Script:fil)}function sim{if(-not $Script:tb.Modified){return $true}switch([MessageBox]::Show("Do you want to save changes to your document?",$an,[MessageBoxButtons]::YesNoCancel,[MessageBoxIcon]::Warning)){([DialogResult]::Yes){return sav}([DialogResult]::No){return $true}Default{return $false}}}function sav{param($sa);if($null -eq $Script:fil -or $sa){$dlg=new SaveFileDialog -Property @{Filter=$Script:df};if($null -ne $Script:fil){$dlg.FileName=[Path]::GetFileName($Script:fil);$dlg.InitialDirectory=[Path]::GetDirectoryName($Script:fil)}if($dlg.ShowDialog() -ne [DialogResult]::OK){return $false}$Script:fil=$dlg.FileName}[File]::WriteAllText($Script:fil,$Script:tb.Text,$Script:enc);$Script:tb.Modified=$false;udv;return $true}function udv{$t=$an;if($null -ne $Script:fil){$t+=" - $([Path]::GetFileName($Script:fil))"}if($Script:tb.Modified){$t+="*"}$Script:f.Text=$t;$s=$Script:tb.SelectionStart;$sl=$Script:tb.SelectionLength;$l=$Script:tb.GetLineFromCharIndex($s);$c=$s-$Script:tb.GetFirstCharIndexFromLine($l)+1;$l++;$t="Ln $l, Col $c";if($sl -gt 0){$ec=$s+$sl;$el=$Script:tb.GetLineFromCharIndex($ec);$ec-=$Script:tb.GetFirstCharIndexFromLine($el)+1;$el++;$t+=" - Ln $el, Col $ec ($sl Selected)"}$Script:stl.Text=$t;$Script:gtl.Enabled=$Script:tb.Lines.Count -gt 0}function fin{if([string]::IsNullOrEmpty($Script:se)){return}$s=$Script:tb.SelectionStart;if(-not $Script:fb){$s+=$Script:tb.SelectionLength}elseif($s -gt 0){$s--}else{$s=0}$fl=gcf;if($Script:fre){try{$t=$Script:tb.Text;if($Script:fb){$Script:lms=0;$ll=$s;$fl=$fl -bor [RegexOptions]::RightToLeft}else{$Script:lms=$s;$ll=$t.Length-$s}$t=$t.Substring($Script:lms,$ll);$Script:lm=[Regex]::Match($t,$Script:se,$fl);if($Script:lm.Success){$i=$Script:lm.Index+$Script:lms}else{$Script:lm=$null;$i=-1}}catch{[MessageBox]::Show("An error occurred while performing the search.`n`n$($_.Exception.Message)","Find",[MessageBoxButtons]::OK,[MessageBoxIcon]::Error);return}}else{$i=if($Script:fb){$Script:tb.Text.LastIndexOf($Script:se,$s,$fl)}else{$Script:tb.Text.IndexOf($Script:se,$s,$fl)}}if($i -ge 0){$Script:tb.Select($i,$Script:se.Length);$Script:tb.ScrollToCaret();$Script:tb.Focus()}else{[MessageBox]::Show("The specified text was not found.","Find",[MessageBoxButtons]::OK,[MessageBoxIcon]::Information)}}function sgt{$tl=$Script:tb.Lines.Count;if($tl -eq 0){return}$ln=$Script:tb.GetLineFromCharIndex($Script:tb.SelectionStart)+1;$f=new Form -Property @{Text="Go To Line";Size=new Size(300,120);FormBorderStyle=[FormBorderStyle]::FixedDialog;MaximizeBox=$false;MinimizeBox=$false;ShowInTaskbar=$false;StartPosition="CenterParent"};$f.Controls.Add(($l=new TableLayoutPanel -Property @{Dock="Fill";RowCount=2;ColumnCount=2}));$ls=$l.ColumnStyles;$ls.Add((new ColumnStyle([SizeType]::Absolute,80)));$ls.Add((new ColumnStyle([SizeType]::Percent,100)));$ls=$l.RowStyles;$ls.Add((new RowStyle([SizeType]::Absolute,30)));$ls.Add((new RowStyle([SizeType]::Absolute,30)));$l=$l.Controls;$l.Add((new Label -Property @{Text="&Line Number:";TextAlign="MiddleRight"}),0,0);$l.Add(($Script:li=new NumericUpDown -Property @{Dock="Fill";Minimum=1;Maximum=$tl;Value=$ln}),1,0);$l.Add(($f.AcceptButton=new Button -Property @{Text="&Go!";DialogResult=[DialogResult]::OK;Add_Click={$ln=[int]$Script:li.Value;if($ln -le 0){return}$tl=$Script:tb.Lines.Count;if($ln -gt $tl){$ln=$tl}$ci=$Script:tb.GetFirstCharIndexFromLine($ln-1);if($ci -ge 0){$Script:tb.Select($ci,0);$Script:tb.ScrollToCaret();$Script:tb.Focus()}}}),1,1);$f.ShowDialog()}function gcf{if($Script:fre){if($Script:fcs){return [RegexOptions]::None}else{return [RegexOptions]::IgnoreCase}}elseif($Script:fcs){return [StringComparison]::Ordinal}else{return [StringComparison]::OrdinalIgnoreCase}}if($null -ne $Script:fil){opf}udv;[Application]::Run($Script:f)
# Classic Notepad Implementation in PowerShell
using namespace System.IO
using namespace System.Text
using namespace System.Text.RegularExpressions
using namespace System.Drawing
using namespace System.Windows.Forms
$an = "LitePad"
if ($args.Count -gt 0) { $Script:fil = $args[0] }
$Script:df = "Text Files (*.txt)|*.txt|All Files (*.*)|*.*"
$Script:enc = [Encoding]::UTF8
Add-Type -AssemblyName System.Drawing
Add-Type -AssemblyName System.Windows.Forms
Set-Alias -Name new -Value New-Object
[Application]::EnableVisualStyles()
[Application]::SetCompatibleTextRenderingDefault($false)
$Script:f = new Form -Property @{
Size = new Size(800, 600)
Icon = [SystemIcons]::Application
MinimumSize = new Size(400, 300)
Add_FormClosing = { $args[1].Cancel = -not (Save-IfModified) }
}
$fc = $Script:f.Controls
[void]$fc.Add(($Script:tb = new TextBox -Property @{
Dock = "Fill"
BorderStyle = "None"
ScrollBars = "Both"
Multiline = $true
WordWrap = $false
AcceptsTab = $true
AllowDrop = $true
Add_TextChanged = {
$Script:ui.Enabled = $Script:tb.CanUndo
Update-View
}
Add_DragEnter = {
$args[1].Effect = if ($args[1].Data.GetDataPresent([DataFormats]::FileDrop)) {
[DragDropEffects]::Copy
} else {
[DragDropEffects]::None
}
}
Add_DragDrop = {
$files = $args[1].Data.GetData([DataFormats]::FileDrop)
if ($files.Count -le 0) { return }
if (-not (Save-IfModified)) { return }
$Script:fil = $files[0]
Open-File
Update-View
}
Add_KeyUp = { Update-View }
Add_MouseUp = { Update-View }
}))
[void]$fc.Add(($Script:sb = new StatusStrip))
$sbi = $Script:sb.Items
[void]$sbi.Add(($Script:stl = new ToolStripButton -Property @{
TextAlign = "MiddleLeft"
Add_Click = { Show-GTL }
}))
[void]$sbi.Add((new ToolStripStatusLabel -Property @{ Spring = $true }))
[void]$sbi.Add((new ToolStripSeparator))
[void]$sbi.Add(($Script:encl = new ToolStripDropDownButton -Property @{ Text = $Script:enc.EncodingName }))
[void]$fc.Add(($Script:f.MainMenuStrip = (new MenuStrip -Property @{ RenderMode = [ToolStripRenderMode]::System })))
$m = $Script:f.MainMenuStrip.Items
[void]$m.Add(($sm = new ToolStripMenuItem("&File")))
$sm = $sm.DropDownItems
[void]$sm.Add((new ToolStripMenuItem("&New") -Property @{
ShortcutKeys = [Keys]::Control -bor [Keys]::N
Add_Click = {
if (-not (Save-IfModified)) { return }
$Script:tb.Clear()
$Script:fil = $null
$Script:tb.Modified = $false
$Script:f.Icon = [SystemIcons]::Application
Update-View
}
}))
[void]$sm.Add((new ToolStripMenuItem("&Open") -Property @{
ShortcutKeys = [Keys]::Control -bor [Keys]::O
Add_Click = {
if (-not (Save-IfModified)) { return }
$dlg = new OpenFileDialog -Property @{ Filter = $Script:df }
if ($dlg.ShowDialog() -ne [DialogResult]::OK) { return }
$Script:fil = $dlg.FileName
Open-File
Update-View
}
}))
[void]$sm.Add((new ToolStripMenuItem("&Save") -Property @{
ShortcutKeys = [Keys]::Control -bor [Keys]::S
Add_Click = { Save-File $false }
}))
[void]$sm.Add((new ToolStripMenuItem("Save &As...") -Property @{
Add_Click = { Save-File $true }
}))
[void]$sm.Add((new ToolStripSeparator))
[void]$sm.Add((new ToolStripMenuItem("&Exit") -Property @{
ShortcutKeys = [Keys]::Control -bor [Keys]::Q
Add_Click = { $Script:f.Close() }
}))
[void]$m.Add(($sm = new ToolStripMenuItem("&Edit")))
$sm = $sm.DropDownItems
[void]$sm.Add(($Script:ui = new ToolStripMenuItem("&Undo") -Property @{
ShortcutKeys = [Keys]::Control -bor [Keys]::Z
Enabled = $false
Add_Click = {
if (-not $Script:tb.CanUndo) { return }
$Script:tb.Undo()
$Script:ui.Enabled = $Script:tb.CanUndo
}
}))
[void]$sm.Add((new ToolStripSeparator))
[void]$sm.Add((new ToolStripMenuItem("&Cut") -Property @{
ShortcutKeys = [Keys]::Control -bor [Keys]::X
Add_Click = { $Script:tb.Cut() }
}))
[void]$sm.Add((new ToolStripMenuItem("C&opy") -Property @{
ShortcutKeys = [Keys]::Control -bor [Keys]::C
Add_Click = { $Script:tb.Copy() }
}))
[void]$sm.Add((new ToolStripMenuItem("&Paste") -Property @{
ShortcutKeys = [Keys]::Control -bor [Keys]::V
Add_Click = { $Script:tb.Paste() }
}))
[void]$sm.Add((new ToolStripSeparator))
[void]$sm.Add((new ToolStripMenuItem("&Select All") -Property @{
ShortcutKeys = [Keys]::Control -bor [Keys]::A
Add_Click = { $Script:tb.SelectAll() }
}))
[void]$sm.Add((new ToolStripSeparator))
[void]$sm.Add((new ToolStripMenuItem("&Find And Replace...") -Property @{
ShortcutKeys = [Keys]::Control -bor [Keys]::F
Add_Click = {
if ($null -ne $Script:ff -and -not $Script:ff.IsDisposed) {
$Script:ff.Focus()
return
}
$sel = $Script:tb.SelectedText
if (-not [string]::IsNullOrEmpty($sel)) {
$Script:se = if ($Script:fre) { [Regex]::Escape($sel) } else { $sel }
} elseif ($Script:se -eq $null) {
$Script:se = ""
}
if ($Script:re -eq $null) { $Script:re = "" }
$Script:ff = new Form -Property @{
Text = "Find and Replace"
Size = new Size(400, 200)
MinimumSize = new Size(400, 200)
MaximumSize = new Size(9999, 200)
MaximizeBox = $false
MinimizeBox = $false
ShowInTaskbar = $false
ShowIcon = $false
Owner = $Script:f
}
$Script:ff.Controls.Add(($l = new TableLayoutPanel -Property @{
Dock = "Fill"
RowCount = 6
ColumnCount = 3
}))
$ls = $l.ColumnStyles
$ls.Add((new ColumnStyle([SizeType]::Absolute, 100)))
$ls.Add((new ColumnStyle([SizeType]::Percent, 100)))
$ls.Add((new ColumnStyle([SizeType]::Absolute, 100)))
$ls = $l.RowStyles
$ls.Add((new RowStyle([SizeType]::Absolute, 30)))
$ls.Add((new RowStyle([SizeType]::Absolute, 30)))
$ls.Add((new RowStyle([SizeType]::Absolute, 30)))
$ls.Add((new RowStyle([SizeType]::Absolute, 30)))
$ls.Add((new RowStyle([SizeType]::Absolute, 30)))
$ls.Add((new RowStyle([SizeType]::Percent, 100)))
$l = $l.Controls
$l.Add((new Label -Property @{
Text = "&Find What:"
TextAlign = "MiddleRight"
}), 0, 0)
$l.Add((new TextBox -Property @{
Dock = "Fill"
Text = $Script:se
Add_TextChanged = { $Script:se = $args[0].Text }
}), 1, 0)
$l.Add(($Script:ff.AcceptButton = new Button -Property @{
Text = "Find &Next"
FlatStyle = [FlatStyle]::System
Add_Click = { Find-Next }
}), 2, 0)
$l.Add((new Label -Property @{
Text = "Replace &With:"
TextAlign = "MiddleRight"
}), 0, 1)
$l.Add((new TextBox -Property @{
Dock = "Fill"
Text = $Script:re
Add_TextChanged = { $Script:re = $args[0].Text }
}), 1, 1)
$l.Add((new Button -Property @{
Text = "&Replace"
FlatStyle = [FlatStyle]::System
Add_Click = {
if ($Script:fre) {
if ($null -ne $Script:lm) {
$newText = $Script:lm.Result($Script:re)
$Script:tb.Select($Script:lm.Index + $Script:lms, $Script:lm.Length)
$Script:tb.SelectedText = $newText
}
} elseif ($Script:tb.SelectedText -ieq $Script:se) {
$Script:tb.SelectedText = $Script:re
}
Find-Next
}
}), 2, 1)
$l.Add((new CheckBox -Property @{
Text = "Search &Backward"
Dock = "Fill"
Checked = $Script:fb -eq $true
FlatStyle = [FlatStyle]::System
Add_CheckedChanged = { $Script:fb = $args[0].Checked }
}), 1, 2)
$l.Add((new Button -Property @{
Text = "Replace &All"
FlatStyle = [FlatStyle]::System
Add_Click = {
if ([string]::IsNullOrEmpty($Script:se) -or [string]::IsNullOrEmpty($Script:re)) { return }
if ([MessageBox]::Show(
"Are you sure you want to replace all occurrences of '$Script:se' with '$Script:re'?",
"Replace All",
[MessageBoxButtons]::YesNo,
[MessageBoxIcon]::Question
) -ne [DialogResult]::Yes) { return }
$fl = Get-CSF
$mod = $Script:tb.Modified
try {
$Script:tb.Text = if ($Script:fre) {
[Regex]::Replace($Script:tb.Text, $Script:se, $Script:re, $fl)
} else {
$Script:tb.Text.Replace($Script:se, $Script:re, $fl)
}
} catch {
[MessageBox]::Show(
"An error occurred while performing the replacement.`n`n$($_.Exception.Message)",
"Replace All",
[MessageBoxButtons]::OK,
[MessageBoxIcon]::Error
)
}
if ($mod) { $Script:tb.Modified = $true }
}
}), 2, 2)
$l.Add((new CheckBox -Property @{
Text = "Case &Sensitive"
Dock = "Fill"
FlatStyle = [FlatStyle]::System
Checked = $Script:fcs -eq $true
Add_CheckedChanged = { $Script:fcs = $args[0].Checked }
}), 1, 3)
$l.Add(($Script:ff.CancelButton = new Button -Property @{
Text = "&Cancel"
FlatStyle = [FlatStyle]::System
Add_Click = { $Script:ff.Close() }
}), 2, 3)
$l.Add((new CheckBox -Property @{
Text = "Use Regular &Expressions"
Dock = "Fill"
FlatStyle = [FlatStyle]::System
Checked = $Script:fre -eq $true
Add_CheckedChanged = { $Script:fre = $args[0].Checked }
}), 1, 4)
$Script:ff.Show()
}
}))
[void]$m.Add(($sm = new ToolStripMenuItem("&View")))
$sm = $sm.DropDownItems
[void]$sm.Add((new ToolStripMenuItem("&Status Bar") -Property @{
Checked = $true
CheckOnClick = $true
Add_Click = { $Script:sb.Visible = $args[0].Checked }
}))
[void]$sm.Add((new ToolStripMenuItem("&Word Wrap") -Property @{
Checked = $Script:tb.WordWrap
ShortcutKeys = [Keys]::Alt -bor [Keys]::Z
CheckOnClick = $true
Add_Click = { $Script:tb.WordWrap = $args[0].Checked }
}))
[void]$sm.Add((new ToolStripMenuItem("&Font...") -Property @{
Add_Click = {
$dlg = new FontDialog -Property @{ Font = $Script:tb.Font }
if ($dlg.ShowDialog() -eq [DialogResult]::OK) { $Script:tb.Font = $dlg.Font }
}
}))
[void]$sm.Add((new ToolStripSeparator))
[void]$sm.Add(($Script:gtl = new ToolStripMenuItem("&Go To Line...") -Property @{
ShortcutKeys = [Keys]::Control -bor [Keys]::G
Enabled = $false
Add_Click = { Show-GTL }
}))
[void]$sm.Add((new ToolStripSeparator))
[void]$sm.Add(($Script:en = new ToolStripMenuItem("&Encoding")))
[void]$m.Add(($sm = new ToolStripMenuItem("&Help")))
$sm = $sm.DropDownItems
[void]$sm.Add((new ToolStripMenuItem("&About $an...") -Property @{
Add_Click = { [MessageBox]::Show("$an`n`n(C) 2025", "About $an", [MessageBoxButtons]::OK, [MessageBoxIcon]::Information) }
}))
[Encoding]::GetEncodings() | ForEach-Object {
$p = @{
Text = "$($_.DisplayName) ($($_.CodePage))"
Tag = $_
Checked = $Script:enc.CodePage -eq $_.CodePage
Add_Click = {
$ei = $args[0].Tag
$pre = $Script:enc
$Script:enc = $ei.GetEncoding()
$Script:encl.Text = $Script:enc.EncodingName
foreach ($item in $Script:en.DropDownItems) { $item.Checked = $item.Tag.CodePage -eq $ei.CodePage }
foreach ($item in $Script:encl.DropDownItems) { $item.Checked = $item.Tag.CodePage -eq $ei.CodePage }
if ([MessageBox]::Show(
"Do you want to re-encode current document to '$($ei.DisplayName)'?",
"Change Encoding",
[MessageBoxButtons]::YesNo,
[MessageBoxIcon]::Question
) -ne [DialogResult]::Yes) { return }
$Script:tb.Text = if (-not $Script:tb.Modified -and $null -ne $Script:fil) {
[File]::ReadAllText($Script:fil, $Script:enc)
} else {
$Script:enc.GetString($pre.GetBytes($Script:tb.Text))
}
}
}
[void]$Script:en.DropDownItems.Add((new ToolStripMenuItem -Property $p))
[void]$Script:encl.DropDownItems.Add((new ToolStripButton -Property $p))
}
function Open-File {
$Script:tb.Text = [File]::ReadAllText($Script:fil, $Script:enc)
$Script:tb.SelectionStart = 0
$Script:tb.SelectionLength = 0
$Script:f.Icon = [Icon]::ExtractAssociatedIcon($Script:fil)
}
function Save-IfModified {
if (-not $Script:tb.Modified) { return $true }
switch ([MessageBox]::Show(
"Do you want to save changes to your document?",
$an,
[MessageBoxButtons]::YesNoCancel,
[MessageBoxIcon]::Warning
)) {
([DialogResult]::Yes) { return Save-File }
([DialogResult]::No) { return $true }
Default { return $false }
}
}
function Save-File {
param ($sa)
if ($null -eq $Script:fil -or $sa) {
$dlg = new SaveFileDialog -Property @{ Filter = $Script:df }
if ($null -ne $Script:fil) {
$dlg.FileName = [Path]::GetFileName($Script:fil)
$dlg.InitialDirectory = [Path]::GetDirectoryName($Script:fil)
}
if ($dlg.ShowDialog() -ne [DialogResult]::OK) { return $false }
$Script:fil = $dlg.FileName
}
[File]::WriteAllText($Script:fil, $Script:tb.Text, $Script:enc)
$Script:tb.Modified = $false
Update-View
return $true
}
function Update-View {
$t = $an
if ($null -ne $Script:fil) { $t += " - $([Path]::GetFileName($Script:fil))" }
if ($Script:tb.Modified) { $t += "*" }
$Script:f.Text = $t
$s = $Script:tb.SelectionStart
$sl = $Script:tb.SelectionLength
$l = $Script:tb.GetLineFromCharIndex($s)
$c = $s - $Script:tb.GetFirstCharIndexFromLine($l) + 1
$l++
$t = "Ln $l, Col $c"
if ($sl -gt 0) {
$ec = $s + $sl
$el = $Script:tb.GetLineFromCharIndex($ec)
$ec -= $Script:tb.GetFirstCharIndexFromLine($el) + 1
$el++
$t += " - Ln $el, Col $ec ($sl Selected)"
}
$Script:stl.Text = $t
$Script:gtl.Enabled = $Script:tb.Lines.Count -gt 0
}
function Find-Next {
if ([string]::IsNullOrEmpty($Script:se)) { return }
$s = $Script:tb.SelectionStart
if (-not $Script:fb) { $s += $Script:tb.SelectionLength } elseif ($s -gt 0) { $s-- } else { $s = 0 }
$fl = Get-CSF
if ($Script:fre) {
try {
$t = $Script:tb.Text
if ($Script:fb) {
$Script:lms = 0
$ll = $s
$fl = $fl -bor [RegexOptions]::RightToLeft
} else {
$Script:lms = $s
$ll = $t.Length - $s
}
$t = $t.Substring($Script:lms, $ll)
$Script:lm = [Regex]::Match($t, $Script:se, $fl)
if ($Script:lm.Success) {
$i = $Script:lm.Index + $Script:lms
} else {
$Script:lm = $null
$i = -1
}
} catch {
[MessageBox]::Show(
"An error occurred while performing the search.`n`n$($_.Exception.Message)",
"Find",
[MessageBoxButtons]::OK,
[MessageBoxIcon]::Error
)
return
}
} else {
$i = if ($Script:fb) {
$Script:tb.Text.LastIndexOf($Script:se, $s, $fl)
} else {
$Script:tb.Text.IndexOf($Script:se, $s, $fl)
}
}
if ($i -ge 0) {
$Script:tb.Select($i, $Script:se.Length)
$Script:tb.ScrollToCaret()
$Script:tb.Focus()
} else {
[MessageBox]::Show("The specified text was not found.", "Find", [MessageBoxButtons]::OK, [MessageBoxIcon]::Information)
}
}
function Show-GTL {
$tl = $Script:tb.Lines.Count
if ($tl -eq 0) { return }
$ln = $Script:tb.GetLineFromCharIndex($Script:tb.SelectionStart) + 1
$f = new Form -Property @{
Text = "Go To Line"
Size = new Size(300, 120)
FormBorderStyle = [FormBorderStyle]::FixedDialog
MaximizeBox = $false
MinimizeBox = $false
ShowInTaskbar = $false
StartPosition = "CenterParent"
}
$f.Controls.Add(($l = new TableLayoutPanel -Property @{
Dock = "Fill"
RowCount = 2
ColumnCount = 2
}))
$ls = $l.ColumnStyles
$ls.Add((new ColumnStyle([SizeType]::Absolute, 80)))
$ls.Add((new ColumnStyle([SizeType]::Percent, 100)))
$ls = $l.RowStyles
$ls.Add((new RowStyle([SizeType]::Absolute, 30)))
$ls.Add((new RowStyle([SizeType]::Absolute, 30)))
$l = $l.Controls
$l.Add((new Label -Property @{
Text = "&Line Number:"
TextAlign = "MiddleRight"
}), 0, 0)
$l.Add(($Script:li = new NumericUpDown -Property @{
Dock = "Fill"
Minimum = 1
Maximum = $tl
Value = $ln
}), 1, 0)
$l.Add(($f.AcceptButton = new Button -Property @{
Text = "&Go!"
DialogResult = [DialogResult]::OK
Add_Click = {
$ln = [int]$Script:li.Value
if ($ln -le 0) { return }
$tl = $Script:tb.Lines.Count
if ($ln -gt $tl) { $ln = $tl }
$ci = $Script:tb.GetFirstCharIndexFromLine($ln - 1)
if ($ci -ge 0) {
$Script:tb.Select($ci, 0)
$Script:tb.ScrollToCaret()
$Script:tb.Focus()
}
}
}), 1, 1)
$f.ShowDialog()
}
function Get-CSF {
if ($Script:fre) {
if ($Script:fcs) { return [RegexOptions]::None } else { return [RegexOptions]::IgnoreCase }
} else {
if ($Script:fcs) { return [StringComparison]::Ordinal } else { return [StringComparison]::OrdinalIgnoreCase }
}
}
if ($null -ne $Script:fil) { Open-File }
Update-View
[Application]::Run($Script:f)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment