Skip to content

Commit 875dba8

Browse files
authored
Improving device generation to support multilanguage pattern (#275)
1 parent 15b3afe commit 875dba8

File tree

9 files changed

+110
-69
lines changed

9 files changed

+110
-69
lines changed

Diff for: README.md

+13-12
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
-----
66
Document Language: [English](README.md) | [简体中文](README.zh-cn.md)
77

8-
## Welcome to the **nanoFramework** team code samples repository!
8+
# Welcome to the **nanoFramework** team code samples repository!
99

1010
This repo contains code samples used by the team when testing, working on proof of concepts for new and improved features and other explorational endeavours.
1111
Feel free to browse, take what you like and contribute back if you want.
@@ -39,11 +39,12 @@ Our samples uses 🌶️ to show how easy or complicated those samples are. The
3939
* [🌶️ - System.Device.PWM sample](samples/PWM)
4040
* [🌶️ - System.Device.Spi sample](samples/SPI)
4141
* [🌶️ to 🌶️🌶️ - System.IO.Ports serial Communication sample](samples/SerialCommunication)
42-
* [🌶️🌶️ - I2C GPS sample](samples/I2C/System.Device.I2c/GPS)
4342
* [🌶️🌶️ - I2C sample sample pack](samples/I2C)
4443
* [🌶️🌶️ - I2C Scanner sample](samples/I2C/NanoI2cScanner)
44+
* [🌶️🌶️ - I2S Microphone sample](samples/I2S/Input)
4545
* [🌶️🌶️ - I2S sample pack](samples/I2S)
46-
* [🌶️🌶️🌶️ - Using Azure SDK with BMP280 on M5Stack with .NET nanoFramework](samples/AzureSDK/AzureSDKSensorCertificate)
46+
* [🌶️🌶️ - I2S Speaker sample](samples/I2S/Output)
47+
* [🌶️🌶️🌶️ - Using Azure SDK with BMP280 on M5Stack with .NET nanoFramework](samples/AzureSDK/AzureSDKSensorCertificate/Readme.md)
4748

4849
### AMQP
4950

@@ -65,7 +66,7 @@ Our samples uses 🌶️ to show how easy or complicated those samples are. The
6566
* [🌶️🌶️🌶️ - Complete Azure MQTT sample using BMP280 sensor **without Azure lib** and with deep sleep](samples/AzureMQTTTwinsBMP280Sleep)
6667
* [🌶️🌶️🌶️ - HTTP.HttpAzureGET Sample](samples/HTTP/HttpAzureGET)
6768
* [🌶️🌶️🌶️ - HTTP.HttpAzurePOST Sample](samples/HTTP/HttpAzurePOST)
68-
* [🌶️🌶️🌶️ - Using Azure SDK with BMP280 on M5Stack with .NET nanoFramework](samples/AzureSDK/AzureSDKSensorCertificate)
69+
* [🌶️🌶️🌶️ - Using Azure SDK with BMP280 on M5Stack with .NET nanoFramework](samples/AzureSDK/AzureSDKSensorCertificate/Readme.md)
6970
* [Azure IoT Device Provisioning Service (DPS) example](samples/AzureSDK/DpsSampleApp)
7071

7172
### Bluetooth
@@ -115,7 +116,7 @@ Our samples uses 🌶️ to show how easy or complicated those samples are. The
115116

116117
* [🌶️🌶️🌶️ - Complete Azure MQTT sample using BMP280 sensor **with** Azure lib and deep sleep](samples/AzureSDK/AzureSDKSleepBMP280)
117118
* [🌶️🌶️🌶️ - Complete Azure MQTT sample using BMP280 sensor **without Azure lib** and with deep sleep](samples/AzureMQTTTwinsBMP280Sleep)
118-
* [🌶️🌶️🌶️ - Using Azure SDK with BMP280 on M5Stack with .NET nanoFramework](samples/AzureSDK/AzureSDKSensorCertificate)
119+
* [🌶️🌶️🌶️ - Using Azure SDK with BMP280 on M5Stack with .NET nanoFramework](samples/AzureSDK/AzureSDKSensorCertificate/Readme.md)
119120

120121
### Interop
121122

@@ -134,21 +135,21 @@ Our samples uses 🌶️ to show how easy or complicated those samples are. The
134135
### Networking including HTTP, SSL
135136

136137
* [🌶️ - UdpClient sample pack](samples/UdpClient)
138+
* [🌶️ - WebSocket Client Sample](samples/WebSockets/WebSockets.Client.Sample)
139+
* [🌶️ - WiFI samples](samples/Wifi)
137140
* [🌶️ to 🌶️🌶️ - .NET **nanoFramework** Webserver sample pack](samples/Webserver)
141+
* [🌶️ to 🌶️🌶️ - WebSocket sample pack](samples/WebSockets)
138142
* [🌶️🌶️ - HTTP Listener sample](samples/HTTP/HttpListener)
139143
* [🌶️🌶️ - HTTP sample pack](samples/HTTP)
140144
* [🌶️🌶️ - HTTP WebRequest sample](samples/HTTP/HttpWebRequest)
141145
* [🌶️🌶️ - Networking sample pack](samples/Networking)
146+
* [🌶️🌶️ - WebSocket Server Sample with RGB Led](samples/WebSockets/WebSockets.Server.RgbSample)
147+
* [🌶️🌶️ - WebSocket ServerClient Sample](samples/WebSockets/Websockets.ServerClient.Sample)
142148
* [🌶️🌶️ - Wifi Soft AP sample](samples/WiFiAP)
143149
* [🌶️🌶️ to 🌶️🌶️🌶️ - MQTT sample pack](samples/MQTT)
144150
* [🌶️🌶️ to 🌶️🌶️🌶️ - TLS sample pack](samples/SSL)
145151
* [🌶️🌶️🌶️ - HTTP.HttpAzureGET Sample](samples/HTTP/HttpAzureGET)
146152
* [🌶️🌶️🌶️ - HTTP.HttpAzurePOST Sample](samples/HTTP/HttpAzurePOST)
147-
* [Error](samples/Wifi)
148-
* [Error](samples/WebSockets)
149-
* [Error](samples/WebSockets/WebSockets.Client.Sample)
150-
* [Error](samples/WebSockets/WebSockets.Server.RgbSample)
151-
* [Error](samples/WebSockets/Websockets.ServerClient.Sample)
152153

153154
### Real Time Clock
154155

@@ -198,12 +199,12 @@ Our samples uses 🌶️ to show how easy or complicated those samples are. The
198199

199200
### USB Client related
200201

201-
* [System.Device.UsbClient sample pack](samples/UsbClient)
202+
* [🌶️🌶️ - System.Device.UsbClient sample pack](samples/UsbClient)
202203

203204
### Wifi
204205

206+
* [🌶️ - WiFI samples](samples/Wifi)
205207
* [🌶️🌶️ - Wifi Soft AP sample](samples/WiFiAP)
206-
* [Error](samples/Wifi)
207208

208209
</devices>
209210

Diff for: README.zh-cn.md

+13-12
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
-----
66
文档语言: [English](README.md) | [简体中文](README.zh-cn.md)
77

8-
## 欢迎使用 **nanoFramework** 例程库!
8+
# 欢迎使用 **nanoFramework** 例程库!
99

1010
本库包括了团队在测试时使用的例程代码,用于验证新增功能以及其它实验室探索。
1111
随意浏览,随心所欲,尽享回报。
@@ -37,11 +37,12 @@
3737
* [🌶️ - System.Device.PWM sample](samples/PWM)
3838
* [🌶️ - System.Device.Spi sample](samples/SPI)
3939
* [🌶️ to 🌶️🌶️ - System.IO.Ports serial Communication sample](samples/SerialCommunication)
40-
* [🌶️🌶️ - I2C GPS sample](samples/I2C/System.Device.I2c/GPS)
4140
* [🌶️🌶️ - I2C sample sample pack](samples/I2C)
4241
* [🌶️🌶️ - I2C Scanner sample](samples/I2C/NanoI2cScanner)
42+
* [🌶️🌶️ - I2S Microphone sample](samples/I2S/Input)
4343
* [🌶️🌶️ - I2S sample pack](samples/I2S)
44-
* [🌶️🌶️🌶️ - Using Azure SDK with BMP280 on M5Stack with .NET nanoFramework](samples/AzureSDK/AzureSDKSensorCertificate)
44+
* [🌶️🌶️ - I2S Speaker sample](samples/I2S/Output)
45+
* [🌶️🌶️🌶️ - Using Azure SDK with BMP280 on M5Stack with .NET nanoFramework](samples/AzureSDK/AzureSDKSensorCertificate/Readme.md)
4546

4647
### AMQP
4748

@@ -63,7 +64,7 @@
6364
* [🌶️🌶️🌶️ - Complete Azure MQTT sample using BMP280 sensor **without Azure lib** and with deep sleep](samples/AzureMQTTTwinsBMP280Sleep)
6465
* [🌶️🌶️🌶️ - HTTP.HttpAzureGET Sample](samples/HTTP/HttpAzureGET)
6566
* [🌶️🌶️🌶️ - HTTP.HttpAzurePOST Sample](samples/HTTP/HttpAzurePOST)
66-
* [🌶️🌶️🌶️ - Using Azure SDK with BMP280 on M5Stack with .NET nanoFramework](samples/AzureSDK/AzureSDKSensorCertificate)
67+
* [🌶️🌶️🌶️ - Using Azure SDK with BMP280 on M5Stack with .NET nanoFramework](samples/AzureSDK/AzureSDKSensorCertificate/Readme.md)
6768
* [Azure IoT Device Provisioning Service (DPS) example](samples/AzureSDK/DpsSampleApp)
6869

6970
### Bluetooth
@@ -113,7 +114,7 @@
113114

114115
* [🌶️🌶️🌶️ - Complete Azure MQTT sample using BMP280 sensor **with** Azure lib and deep sleep](samples/AzureSDK/AzureSDKSleepBMP280)
115116
* [🌶️🌶️🌶️ - Complete Azure MQTT sample using BMP280 sensor **without Azure lib** and with deep sleep](samples/AzureMQTTTwinsBMP280Sleep)
116-
* [🌶️🌶️🌶️ - Using Azure SDK with BMP280 on M5Stack with .NET nanoFramework](samples/AzureSDK/AzureSDKSensorCertificate)
117+
* [🌶️🌶️🌶️ - Using Azure SDK with BMP280 on M5Stack with .NET nanoFramework](samples/AzureSDK/AzureSDKSensorCertificate/Readme.md)
117118

118119
### Interop
119120

@@ -132,21 +133,21 @@
132133
### Networking including HTTP, SSL
133134

134135
* [🌶️ - UdpClient sample pack](samples/UdpClient)
136+
* [🌶️ - WebSocket 客户端示例](samples/WebSockets/WebSockets.Client.Sample/README.zh-cn.md)
137+
* [🌶️ - WiFI 示例](samples/Wifi/README.zh-cn.md)
135138
* [🌶️ to 🌶️🌶️ - .NET **nanoFramework** Webserver sample pack](samples/Webserver)
139+
* [🌶️ to 🌶️🌶️ - WebSocket示例包](samples/WebSockets/README.zh-cn.md)
136140
* [🌶️🌶️ - HTTP Listener sample](samples/HTTP/HttpListener)
137141
* [🌶️🌶️ - HTTP sample pack](samples/HTTP)
138142
* [🌶️🌶️ - HTTP WebRequest sample](samples/HTTP/HttpWebRequest)
139143
* [🌶️🌶️ - Networking sample pack](samples/Networking)
144+
* [🌶️🌶️ - WebSocket ServerClient Sample](samples/WebSockets/Websockets.ServerClient.Sample/README.zh-cn.md)
145+
* [🌶️🌶️ - WebSocket Server示例与RGB Led](samples/WebSockets/WebSockets.Server.RgbSample/README.zh-cn.md)
140146
* [🌶️🌶️ - Wifi Soft AP sample](samples/WiFiAP)
141147
* [🌶️🌶️ to 🌶️🌶️🌶️ - MQTT sample pack](samples/MQTT)
142148
* [🌶️🌶️ to 🌶️🌶️🌶️ - TLS sample pack](samples/SSL)
143149
* [🌶️🌶️🌶️ - HTTP.HttpAzureGET Sample](samples/HTTP/HttpAzureGET)
144150
* [🌶️🌶️🌶️ - HTTP.HttpAzurePOST Sample](samples/HTTP/HttpAzurePOST)
145-
* [Error](samples/Wifi)
146-
* [Error](samples/WebSockets)
147-
* [Error](samples/WebSockets/WebSockets.Client.Sample)
148-
* [Error](samples/WebSockets/WebSockets.Server.RgbSample)
149-
* [Error](samples/WebSockets/Websockets.ServerClient.Sample)
150151

151152
### Real Time Clock
152153

@@ -196,12 +197,12 @@
196197

197198
### USB Client related
198199

199-
* [System.Device.UsbClient sample pack](samples/UsbClient)
200+
* [🌶️🌶️ - System.Device.UsbClient sample pack](samples/UsbClient)
200201

201202
### Wifi
202203

204+
* [🌶️ - WiFI 示例](samples/Wifi/README.zh-cn.md)
203205
* [🌶️🌶️ - Wifi Soft AP sample](samples/WiFiAP)
204-
* [Error](samples/Wifi)
205206

206207
</devices>
207208

Diff for: device-listing/Configuration.cs

+5
Original file line numberDiff line numberDiff line change
@@ -20,5 +20,10 @@ internal class Configuration
2020
/// Gets or sets the list of ignored folders.
2121
/// </summary>
2222
public string[] Ignored { get; set; }
23+
24+
/// <summary>
25+
/// Gets or sets the list of languages to generate.
26+
/// </summary>
27+
public string[] Languages {get; set;}
2328
}
2429
}

Diff for: device-listing/Configuration.json

+4
Original file line numberDiff line numberDiff line change
@@ -103,5 +103,9 @@
103103
"packages",
104104
"bin",
105105
"obj"
106+
],
107+
"Languages": [
108+
"",
109+
"zh-cn"
106110
]
107111
}

Diff for: device-listing/Program.cs

+44-41
Original file line numberDiff line numberDiff line change
@@ -26,48 +26,50 @@
2626
}
2727

2828
string samplesPath = Path.Combine(repoRoot, "samples");
29+
List<SampleInfo> samples;
2930

30-
List<SampleInfo> samples = new();
31+
// We will iterate one per language
32+
foreach (var language in configuration.Languages)
33+
{
34+
samples = new();
3135

32-
GetAllDirectoriesAndPopulate(Directory.EnumerateDirectories(samplesPath));
36+
GetAllDirectoriesAndPopulate(Directory.EnumerateDirectories(samplesPath), language);
3337

34-
samples.Sort();
38+
samples.Sort();
3539

36-
var allCategories = new HashSet<string>();
40+
var allCategories = new HashSet<string>();
3741

38-
foreach (SampleInfo sample in samples)
39-
{
40-
bool beingDisplayed = false;
41-
foreach (string category in sample.Categories)
42+
foreach (SampleInfo sample in samples)
4243
{
43-
if (allCategories.Add(category))
44+
bool beingDisplayed = false;
45+
foreach (string category in sample.Categories)
4446
{
45-
if (!configuration.Categories.Where(m => m.Name == category).Any())
47+
if (allCategories.Add(category))
4648
{
47-
Console.ForegroundColor = ConsoleColor.Yellow;
48-
Console.WriteLine($"Warning: Category `{category}` is missing description (`{sample.Title}`). [{sample.ReadmePath}]");
49-
Console.ForegroundColor = ConsoleColor.White;
49+
if (!configuration.Categories.Where(m => m.Name == category).Any())
50+
{
51+
Console.ForegroundColor = ConsoleColor.Yellow;
52+
Console.WriteLine($"Warning: Category `{category}` is missing description (`{sample.Title}`). [{sample.ReadmePath}]");
53+
Console.ForegroundColor = ConsoleColor.White;
54+
}
5055
}
51-
}
5256

53-
beingDisplayed |= !beingDisplayed && configuration.Categories.Where(m => m.Name == category).Any();
54-
}
57+
beingDisplayed |= !beingDisplayed && configuration.Categories.Where(m => m.Name == category).Any();
58+
}
5559

56-
if (!beingDisplayed && sample.CategoriesFileExists)
57-
{
58-
// We do not want to show the warning when file doesn't exist as you will get separate warning that category.txt is missing in that case.
59-
Console.ForegroundColor = ConsoleColor.Yellow;
60-
Console.WriteLine($"Warning: Sample `{sample.Title}` is not being displayed under any category. [{sample.CategoriesFilePath}]");
61-
Console.ForegroundColor = ConsoleColor.White;
60+
if (!beingDisplayed && sample.CategoriesFileExists)
61+
{
62+
// We do not want to show the warning when file doesn't exist as you will get separate warning that category.txt is missing in that case.
63+
Console.ForegroundColor = ConsoleColor.Yellow;
64+
Console.WriteLine($"Warning: Sample `{sample.Title}` is not being displayed under any category. [{sample.CategoriesFilePath}]");
65+
Console.ForegroundColor = ConsoleColor.White;
66+
}
6267
}
68+
string alphabeticalDevicesIndex = Path.Combine(repoRoot, $"README{(string.IsNullOrEmpty(language) ? string.Empty : $".{language}")}.md");
69+
string categorizedDeviceListing = GetCategorizedDeviceListing(samplesPath, samples);
70+
ReplacePlaceholder(alphabeticalDevicesIndex, "devices", categorizedDeviceListing);
6371
}
6472

65-
string alphabeticalDevicesIndex = Path.Combine(repoRoot, "README.md");
66-
string categorizedDeviceListing = GetCategorizedDeviceListing(samplesPath, samples);
67-
ReplacePlaceholder(alphabeticalDevicesIndex, "devices", categorizedDeviceListing);
68-
alphabeticalDevicesIndex = Path.Combine(repoRoot, "README.zh-cn.md");
69-
ReplacePlaceholder(alphabeticalDevicesIndex, "devices", categorizedDeviceListing);
70-
7173
string GetDeviceListing(string devicesPath, IEnumerable<SampleInfo> samples)
7274
{
7375
var deviceListing = new StringBuilder();
@@ -87,7 +89,7 @@ string GetCategorizedDeviceListing(string devicesPath, IEnumerable<SampleInfo> d
8789
var categoryDescription = configuration.Categories.Where(m => m.Name == categoryToDisplay).FirstOrDefault()?.Description;
8890
if (!string.IsNullOrEmpty(categoryDescription))
8991
{
90-
string listingInCurrentCategory = GetDeviceListing(devicesPath, devices.Where((d) => d.Categories.Contains(categoryToDisplay)));
92+
string listingInCurrentCategory = GetDeviceListing(devicesPath, devices.Where(d => d.Categories.Contains(categoryToDisplay)));
9193
if (!string.IsNullOrEmpty(listingInCurrentCategory))
9294
{
9395
sampleListing.AppendLine($"### {categoryDescription}");
@@ -173,7 +175,7 @@ void ReplacePlaceholder(string filePath, string placeholderName, string newConte
173175
fileContent.Substring(endIdx));
174176
}
175177

176-
void GetAllDirectoriesAndPopulate(IEnumerable<string> path)
178+
void GetAllDirectoriesAndPopulate(IEnumerable<string> path, string language)
177179
{
178180
foreach (string directory in path)
179181
{
@@ -182,11 +184,19 @@ void GetAllDirectoriesAndPopulate(IEnumerable<string> path)
182184
continue;
183185
}
184186

185-
string readme = Path.Combine(directory, "README.md");
186187
string categories = Path.Combine(directory, "category.txt");
187188

188-
if (File.Exists(readme))
189+
// Find the README.xx.md files
190+
var files = Directory.EnumerateFiles(directory, $"README{(string.IsNullOrEmpty(language) ? string.Empty : $".{language}")}.md");
191+
// If we don't have any, then fall back to the neutral langauge
192+
if (!files.Any())
189193
{
194+
files = Directory.EnumerateFiles(directory, "README.md");
195+
}
196+
197+
foreach (var readme in files)
198+
{
199+
// string readme = Path.Combine(directory, "README.md");
190200
var device = new SampleInfo(readme, categories);
191201

192202
if (device.Title == null)
@@ -196,15 +206,8 @@ void GetAllDirectoriesAndPopulate(IEnumerable<string> path)
196206
}
197207

198208
samples.Add(device);
199-
}
200-
else
201-
{
202-
if (File.Exists(categories))
203-
{
204-
Console.WriteLine($"Warning: Device directory does not have a README.md file. [{directory}]");
205-
}
206-
}
207209

208-
GetAllDirectoriesAndPopulate(Directory.EnumerateDirectories(directory));
210+
GetAllDirectoriesAndPopulate(Directory.EnumerateDirectories(directory), language);
211+
}
209212
}
210213
}

Diff for: device-listing/SampleInfo.cs

+28-3
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ class SampleInfo : IComparable<SampleInfo>
1717
public HashSet<string> Categories { get; private set; } = new HashSet<string>();
1818
public string CategoriesFilePath { get; private set; }
1919
public bool CategoriesFileExists { get; private set; }
20+
public string Language { get; private set; }
2021

2122
public SampleInfo(string readmePath, string categoriesFilePath)
2223
{
@@ -25,6 +26,7 @@ public SampleInfo(string readmePath, string categoriesFilePath)
2526
Title = GetTitle(readmePath) ?? "Error";
2627
CategoriesFilePath = categoriesFilePath;
2728
CategoriesFileExists = File.Exists(categoriesFilePath);
29+
Language = FindLanguage(readmePath);
2830

2931
ImportCategories();
3032
}
@@ -34,6 +36,23 @@ public int CompareTo(SampleInfo? other)
3436
return Title.CompareTo(other?.Title);
3537
}
3638

39+
public string FindLanguage(string filepath)
40+
{
41+
// Pattern is like path\name.zn-cn.ext or path\name.ext
42+
var separator = Path.DirectorySeparatorChar;
43+
var file = filepath.Substring(filepath.LastIndexOf(separator) + 1);
44+
var filewithoutext = file.Substring(0, file.LastIndexOf('.'));
45+
var posdot = filewithoutext.LastIndexOf('.');
46+
// We do have another dot, so by convention, it does contain our langage
47+
if (posdot > 0)
48+
{
49+
return filewithoutext.Substring(posdot + 1);
50+
}
51+
52+
// Neutral language by convention
53+
return string.Empty;
54+
}
55+
3756
private void ImportCategories()
3857
{
3958
if (!CategoriesFileExists)
@@ -59,10 +78,16 @@ private void ImportCategories()
5978
private static string? GetTitle(string readmePath)
6079
{
6180
string[] lines = File.ReadAllLines(readmePath);
62-
if (lines[0].StartsWith("# "))
81+
int inc = 0;
82+
do
6383
{
64-
return lines[0].Substring(2);
65-
}
84+
if (lines[inc].StartsWith("# "))
85+
{
86+
return lines[inc].Substring(2);
87+
}
88+
89+
inc++;
90+
} while (inc < lines.Length);
6691

6792
return null;
6893
}

Diff for: samples/I2S/Input/category.txt

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
device

Diff for: samples/I2S/Output/category.txt

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
device

Diff for: samples/UsbClient/README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# System.Device.UsbClient sample pack
1+
# 🌶️🌶️ - System.Device.UsbClient sample pack
22

33
Shows how to use the [System.Device.UsbClient](http://docs.nanoframework.net/api/System.Device.UsbClient.html) API to use the various USB client classes.
44

0 commit comments

Comments
 (0)