Skip to content

Commit 0cda83c

Browse files
committed
Add CSV/TSV/PSV rainbow highlighters (light/dark) support
1 parent ed8c299 commit 0cda83c

File tree

12 files changed

+436
-5
lines changed

12 files changed

+436
-5
lines changed
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
// Copyright © 2017-2026 QL-Win Contributors
2+
//
3+
// This file is part of QuickLook program.
4+
//
5+
// This program is free software: you can redistribute it and/or modify
6+
// it under the terms of the GNU General Public License as published by
7+
// the Free Software Foundation, either version 3 of the License, or
8+
// (at your option) any later version.
9+
//
10+
// This program is distributed in the hope that it will be useful,
11+
// but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+
// GNU General Public License for more details.
14+
//
15+
// You should have received a copy of the GNU General Public License
16+
// along with this program. If not, see <http://www.gnu.org/licenses/>.
17+
18+
using QuickLook.Common.Commands;
19+
using QuickLook.Common.Controls;
20+
using QuickLook.Common.Helpers;
21+
using QuickLook.Common.Plugin;
22+
using QuickLook.Common.Plugin.MoreMenu;
23+
using System.Collections.Generic;
24+
using System.IO;
25+
26+
namespace QuickLook.Plugin.CsvViewer;
27+
28+
public sealed partial class Plugin : IViewer, IMoreMenu
29+
{
30+
public IEnumerable<IMenuItem> MenuItems => GetMenuItems();
31+
32+
public IEnumerable<IMenuItem> GetMenuItems()
33+
{
34+
string translationFile = Path.Combine(Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location), "Translations.config");
35+
36+
yield return new MoreMenuItem()
37+
{
38+
Icon = FontSymbols.Code,
39+
Header = TranslationHelper.Get("MW_ReopenAsTextPreview", translationFile),
40+
Command = new RelayCommand(() => PluginHelper.InvokePluginPreview("QuickLook.Plugin.TextViewer", _currentPath)),
41+
};
42+
}
43+
}

QuickLook.Plugin/QuickLook.Plugin.CsvViewer/Plugin.cs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,15 +16,17 @@
1616
// along with this program. If not, see <http://www.gnu.org/licenses/>.
1717

1818
using QuickLook.Common.Plugin;
19+
using QuickLook.Common.Plugin.MoreMenu;
1920
using System;
2021
using System.IO;
2122
using System.Windows;
2223

2324
namespace QuickLook.Plugin.CsvViewer;
2425

25-
public sealed class Plugin : IViewer
26+
public sealed partial class Plugin : IViewer, IMoreMenu
2627
{
2728
private CsvViewerPanel _panel;
29+
private string _currentPath;
2830

2931
public int Priority => 0;
3032

@@ -49,6 +51,8 @@ public void Prepare(string path, ContextObject context)
4951

5052
public void View(string path, ContextObject context)
5153
{
54+
_currentPath = path;
55+
5256
_panel = new CsvViewerPanel();
5357

5458
context.ViewerContent = _panel;

QuickLook.Plugin/QuickLook.Plugin.CsvViewer/QuickLook.Plugin.CsvViewer.csproj

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,12 @@
8383
</ProjectReference>
8484
</ItemGroup>
8585

86+
<ItemGroup>
87+
<None Include="Translations.config">
88+
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
89+
</None>
90+
</ItemGroup>
91+
8692
<ItemGroup>
8793
<Compile Include="..\..\GitVersion.cs">
8894
<Link>Properties\GitVersion.cs</Link>
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
3+
<Translations>
4+
<ar>
5+
<MW_ReopenAsTextPreview>إعادة فتح كمعاينة نص</MW_ReopenAsTextPreview>
6+
</ar>
7+
<ca>
8+
<MW_ReopenAsTextPreview>Torna a obrir com a previsualització de text</MW_ReopenAsTextPreview>
9+
</ca>
10+
<de>
11+
<MW_ReopenAsTextPreview>Als Text-Vorschau erneut öffnen</MW_ReopenAsTextPreview>
12+
</de>
13+
<en>
14+
<MW_ReopenAsTextPreview>Reopen as text preview</MW_ReopenAsTextPreview>
15+
</en>
16+
<es>
17+
<MW_ReopenAsTextPreview>Reabrir como vista previa de texto</MW_ReopenAsTextPreview>
18+
</es>
19+
<fr>
20+
<MW_ReopenAsTextPreview>Rouvrir en aperçu texte</MW_ReopenAsTextPreview>
21+
</fr>
22+
<it>
23+
<MW_ReopenAsTextPreview>Riapri come anteprima testo</MW_ReopenAsTextPreview>
24+
</it>
25+
<ja-JP>
26+
<MW_ReopenAsTextPreview>テキストとして再度開く</MW_ReopenAsTextPreview>
27+
</ja-JP>
28+
<ko>
29+
<MW_ReopenAsTextPreview>텍스트 미리보기로 다시 열기</MW_ReopenAsTextPreview>
30+
</ko>
31+
<nb-NO>
32+
<MW_ReopenAsTextPreview>Åpne på nytt som tekst-forhåndsvisning</MW_ReopenAsTextPreview>
33+
</nb-NO>
34+
<nl-NL>
35+
<MW_ReopenAsTextPreview>Opnieuw openen als tekst-voorbeeld</MW_ReopenAsTextPreview>
36+
</nl-NL>
37+
<pl>
38+
<MW_ReopenAsTextPreview>Otwórz ponownie jako podgląd tekstu</MW_ReopenAsTextPreview>
39+
</pl>
40+
<pt-BR>
41+
<MW_ReopenAsTextPreview>Reabrir como visualização de texto</MW_ReopenAsTextPreview>
42+
</pt-BR>
43+
<pt-PT>
44+
<MW_ReopenAsTextPreview>Reabrir como pré-visualização de texto</MW_ReopenAsTextPreview>
45+
</pt-PT>
46+
<ro>
47+
<MW_ReopenAsTextPreview>Redeschideți ca previzualizare text</MW_ReopenAsTextPreview>
48+
</ro>
49+
<ru-RU>
50+
<MW_ReopenAsTextPreview>Переоткрыть как предварительный просмотр текста</MW_ReopenAsTextPreview>
51+
</ru-RU>
52+
<tr-TR>
53+
<MW_ReopenAsTextPreview>Metin önizlemesi olarak yeniden aç</MW_ReopenAsTextPreview>
54+
</tr-TR>
55+
<uk-UA>
56+
<MW_ReopenAsTextPreview>Перевідкрити як попередній перегляд тексту</MW_ReopenAsTextPreview>
57+
</uk-UA>
58+
<vi>
59+
<MW_ReopenAsTextPreview>Mở lại dưới dạng xem trước văn bản</MW_ReopenAsTextPreview>
60+
</vi>
61+
<zh-CN>
62+
<MW_ReopenAsTextPreview>重新作为文本预览打开</MW_ReopenAsTextPreview>
63+
</zh-CN>
64+
<zh-TW>
65+
<MW_ReopenAsTextPreview>重新作為文本預覽開啟</MW_ReopenAsTextPreview>
66+
</zh-TW>
67+
<mr>
68+
<MW_ReopenAsTextPreview>पुनः टेक्स्ट पूर्वावलोकन म्हणून उघडा</MW_ReopenAsTextPreview>
69+
</mr>
70+
<hi>
71+
<MW_ReopenAsTextPreview>टेक्स्ट पूर्वावलोकन के रूप में फिर से खोलें</MW_ReopenAsTextPreview>
72+
</hi>
73+
<he>
74+
<MW_ReopenAsTextPreview>פתח מחדש כתצוגת טקסט</MW_ReopenAsTextPreview>
75+
</he>
76+
<hu-HU>
77+
<MW_ReopenAsTextPreview>Újranyitás szöveg előnézetként</MW_ReopenAsTextPreview>
78+
</hu-HU>
79+
<id-ID>
80+
<MW_ReopenAsTextPreview>Buka ulang sebagai pratinjau teks</MW_ReopenAsTextPreview>
81+
</id-ID>
82+
<sk>
83+
<MW_ReopenAsTextPreview>Znova otvoriť ako náhľad textu</MW_ReopenAsTextPreview>
84+
</sk>
85+
<el>
86+
<MW_ReopenAsTextPreview>Επανανοίξτε ως προεπισκόπηση κειμένου</MW_ReopenAsTextPreview>
87+
</el>
88+
<sv>
89+
<MW_ReopenAsTextPreview>Öppna på nytt som textförhandsgranskning</MW_ReopenAsTextPreview>
90+
</sv>
91+
</Translations>

QuickLook.Plugin/QuickLook.Plugin.TextViewer/Plugin.MoreMenu.cs

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
using QuickLook.Common.Controls;
2020
using QuickLook.Common.Helpers;
2121
using QuickLook.Common.Plugin.MoreMenu;
22+
using System;
2223
using System.Collections.Generic;
2324
using System.IO;
2425
using System.Reflection;
@@ -30,14 +31,16 @@ public sealed partial class Plugin
3031
public IEnumerable<IMenuItem> GetMenuItems()
3132
{
3233
string translationFile = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "Translations.config");
33-
string extension = "";
34+
string extension = string.Empty;
35+
3436
try
3537
{
38+
// Get the file extension in lowercase for comparison
3639
extension = Path.GetExtension(_currentPath).ToLower();
37-
} catch (System.Exception)
38-
{
3940
}
40-
41+
catch (Exception)
42+
{
43+
}
4144

4245
var reopen = extension switch
4346
{
@@ -58,6 +61,14 @@ public IEnumerable<IMenuItem> GetMenuItems()
5861
Header = TranslationHelper.Get("MW_ReopenAsImagePreview", translationFile),
5962
Command = new RelayCommand(() => PluginHelper.InvokePluginPreview("QuickLook.Plugin.ImageViewer", _currentPath)),
6063
},
64+
65+
// CSV, TSV, PSV <=> CSV viewer
66+
".csv" or ".tsv" or ".psv" => new MoreMenuItem()
67+
{
68+
Icon = FontSymbols.Code,
69+
Header = TranslationHelper.Get("MW_ReopenAsCsvPreview", translationFile),
70+
Command = new RelayCommand(() => PluginHelper.InvokePluginPreview("QuickLook.Plugin.CsvViewer", _currentPath)),
71+
},
6172
_ => null,
6273
};
6374

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
using ICSharpCode.AvalonEdit.Document;
2+
using ICSharpCode.AvalonEdit.Rendering;
3+
using System.Windows.Media;
4+
5+
namespace QuickLook.Plugin.TextViewer.Themes.HighlightingDefinitions.Dark;
6+
7+
/// <summary>
8+
/// Rainbow CSV Highlighting Definition
9+
/// </summary>
10+
public class CSVHighlightingDefinition : DarkHighlightingDefinition
11+
{
12+
public override string Name => "CSV";
13+
14+
public override string Extension => ".csv";
15+
16+
public override DocumentColorizingTransformer[] LineTransformers { get; } = [new RainbowTransformer(',')];
17+
18+
public class RainbowTransformer(char sep) : DocumentColorizingTransformer
19+
{
20+
private readonly char _sep = sep;
21+
22+
private readonly Brush[] _brushes =
23+
[
24+
Colors.OrangeRed.ToBrush(),
25+
Colors.CornflowerBlue.ToBrush(),
26+
Colors.LimeGreen.ToBrush(),
27+
Colors.MediumVioletRed.ToBrush(),
28+
Colors.Peru.ToBrush(),
29+
Colors.CadetBlue.ToBrush(),
30+
Colors.Khaki.ToBrush(),
31+
Colors.MediumSlateBlue.ToBrush(),
32+
];
33+
34+
protected override void ColorizeLine(DocumentLine line)
35+
{
36+
var text = CurrentContext.Document.GetText(line);
37+
if (string.IsNullOrEmpty(text))
38+
return;
39+
40+
int offset = line.Offset;
41+
int i = 0;
42+
int col = 0;
43+
int len = text.Length;
44+
45+
while (i < len)
46+
{
47+
int contentStart = i;
48+
int contentEnd = i;
49+
50+
if (text[i] == '"')
51+
{
52+
contentStart = i + 1;
53+
i++;
54+
while (i < len)
55+
{
56+
if (text[i] == '"')
57+
{
58+
if (i + 1 < len && text[i + 1] == '"')
59+
{
60+
i += 2;
61+
continue;
62+
}
63+
else
64+
{
65+
contentEnd = i;
66+
i++;
67+
break;
68+
}
69+
}
70+
i++;
71+
}
72+
while (i < len && text[i] != _sep) i++;
73+
}
74+
else
75+
{
76+
contentStart = i;
77+
while (i < len && text[i] != _sep) i++;
78+
contentEnd = i;
79+
}
80+
81+
if (contentEnd > contentStart)
82+
{
83+
int a = offset + contentStart;
84+
int b = offset + contentEnd;
85+
var brush = _brushes[col % _brushes.Length];
86+
ChangeLinePart(a, b, el => el.TextRunProperties.SetForegroundBrush(brush));
87+
}
88+
89+
if (i < len && text[i] == _sep) i++;
90+
col++;
91+
}
92+
}
93+
}
94+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
using ICSharpCode.AvalonEdit.Rendering;
2+
3+
namespace QuickLook.Plugin.TextViewer.Themes.HighlightingDefinitions.Dark;
4+
5+
/// <summary>
6+
/// Rainbow PSV Highlighting Definition
7+
/// </summary>
8+
public class PSVHighlightingDefinition : DarkHighlightingDefinition
9+
{
10+
public override string Name => "PSV";
11+
12+
public override string Extension => ".psv";
13+
14+
public override DocumentColorizingTransformer[] LineTransformers { get; } = [new CSVHighlightingDefinition.RainbowTransformer('|')];
15+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
using ICSharpCode.AvalonEdit.Rendering;
2+
3+
namespace QuickLook.Plugin.TextViewer.Themes.HighlightingDefinitions.Dark;
4+
5+
/// <summary>
6+
/// Rainbow TSV Highlighting Definition
7+
/// </summary>
8+
public class TSVHighlightingDefinition : DarkHighlightingDefinition
9+
{
10+
public override string Name => "TSV";
11+
12+
public override string Extension => ".tsv";
13+
14+
public override DocumentColorizingTransformer[] LineTransformers { get; } = [new CSVHighlightingDefinition.RainbowTransformer('\t')];
15+
}

0 commit comments

Comments
 (0)