Compare commits

..

No commits in common. "master" and "1.1.7468.23805" have entirely different histories.

31 changed files with 416 additions and 1081 deletions

87
.github/workflows/main.yml vendored Normal file
View File

@ -0,0 +1,87 @@
name: CD
on:
push:
branches:
- master
jobs:
build:
runs-on: windows-latest
steps:
- uses: actions/checkout@v2
- name: Build
id: base_init
run: |
$(new-object System.Net.WebClient).DownloadFile("https://www.github.com/JFronny/UpTool2/releases/latest/download/Tools.zip", "$($(pwd).Path)\Tools.zip")
& "C:\Program Files\7-Zip\7z.exe" x .\Tools.zip
rm Tools.zip
rm Install.bat
rm Remove.bat
dotnet build --verbosity:m -p:Configuration=Release
cp W32.Test\bin\Release\netcoreapp3.1\package.zip .
$file = Get-Item $(Resolve-Path W32.Test\bin\Release\netcoreapp3.1\*.exe).Path
$asm = $([Reflection.Assembly]::LoadFile($file.DirectoryName + "\" + $file.BaseName + ".dll"))
$asmver = $asm.GetName().Version.ToString()
echo "::set-output name=vers::$asmver"
- name: Create Release
id: create_release
uses: actions/create-release@v1.0.1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
tag_name: ${{ steps.base_init.outputs.vers }}
release_name: Release ${{ steps.base_init.outputs.vers }}
draft: false
prerelease: false
- name: Upload Release Asset
id: upload_release_asset
uses: actions/upload-release-asset@v1.0.2
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ steps.create_release.outputs.upload_url }}
asset_path: ./package.zip
asset_name: package.zip
asset_content_type: application/zip
- name: Generate XML
run: |
$file = Get-Item $(Resolve-Path W32.Test\bin\Release\netcoreapp3.1\*.exe).Path
$asm = [Reflection.Assembly]::LoadFile($file.DirectoryName + "\" + $file.BaseName + ".dll")
[System.XML.XMLDocument]$xml=New-Object System.XML.XMLDocument
[System.XML.XMLElement]$app=$xml.CreateElement("app")
$xml.appendChild($app)
$app.appendChild($xml.CreateElement("Name")).InnerText = $asm.GetName().Name
$app.appendChild($xml.CreateElement("Description")).InnerText = "Collection of Utilities for manipulating Windows"
$app.appendChild($xml.CreateElement("Version")).InnerText = "${{ steps.base_init.outputs.vers }}"
$app.appendChild($xml.CreateElement("ID")).InnerText = "3191d2f3-bf48-48ea-97a2-59fb32722d0a"
$app.appendChild($xml.CreateElement("File")).InnerText = "${{ steps.upload_release_asset.outputs.browser_download_url }}"
$app.appendChild($xml.CreateElement("Hash")).InnerText = $(Get-FileHash .\package.zip).Hash
$app.appendChild($xml.CreateElement("MainFile")).InnerText = $file.Name
echo NULL > app.xml
$xml.save($(gi .\app.xml).Fullname)
- name: Upload XML
uses: actions/upload-release-asset@v1.0.2
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ steps.create_release.outputs.upload_url }}
asset_path: ./app.xml
asset_name: app.xml
asset_content_type: text/xml
- name: Publish nugets
run: |
$tmp = "${{ steps.base_init.outputs.vers }}"
$tmp1 = $tmp.split('.')[2]
$tmp2 = $tmp.split('.')[3]
$suffix = "$tmp1.$tmp2"
cd Misc
dotnet pack --version-suffix "$suffix" -c Release -o .
dotnet nuget push $(Get-Item $(Resolve-Path *.nupkg).Path).Name -k ${{secrets.NUGET_API_KEY}} -s https://api.nuget.org/v3/index.json
cd ..\W32
dotnet pack --version-suffix "$suffix" -c Release -o .
dotnet nuget push $(Get-Item $(Resolve-Path *.nupkg).Path).Name -k ${{secrets.NUGET_API_KEY}} -s https://api.nuget.org/v3/index.json
cd ..\Commandline
dotnet pack --version-suffix "$suffix" -c Release -o .
dotnet nuget push $(Get-Item $(Resolve-Path *.nupkg).Path).Name -k ${{secrets.NUGET_API_KEY}} -s https://api.nuget.org/v3/index.json
cd ..

View File

@ -1,85 +0,0 @@
.shared_windows_runners:
tags:
- windows
image: mcr.microsoft.com/dotnet/sdk
uptool:
extends:
- .shared_windows_runners
stage: deploy
script: |
mkdir i
cd i
$(new-object System.Net.WebClient).DownloadFile("https://gitlab.com/JFronny/UpTool2/-/jobs/artifacts/master/raw/Installer-generic.zip?job=uptool", "$($(pwd).Path)\Install.zip")
& "C:\Program Files\7-Zip\7z.exe" x .\Install.zip
.\Installer.exe --basic i -p
cd ..
rm -R i
$Env:Path="$Env:Path;$Env:APPDATA\UpTool2\Install"
uptool --basic add-repo DevTools https://gitlab.com/JFronny/UpTool2/-/snippets/2010392/raw
uptool --basic update
uptool --basic install "UpTool2 package tools"
$Env:Path="$Env:Path;$Env:APPDATA\UpTool2\Apps\0e35d154-d0d3-45e0-b080-62f521263a44\app"
mkdir .\build
cd W32.Test
dotnet publish -o ..\build -c Release
cd ..
$file = Get-Item $(Resolve-Path .\build\*.exe).Path
pkgtool build --binDir build --mainBin $file --packageFile .\package.zip --noLogo
$asm = $([Reflection.Assembly]::LoadFile($file.DirectoryName + "\" + $file.BaseName + ".dll"))
$asmver = $asm.GetName().Version.ToString()
[System.XML.XMLDocument]$xml=New-Object System.XML.XMLDocument
[System.XML.XMLElement]$app=$xml.CreateElement("app")
$xml.appendChild($app)
$app.appendChild($xml.CreateElement("Name")).InnerText = $asm.GetName().Name
$app.appendChild($xml.CreateElement("Description")).InnerText = "Collection of Utilities for manipulating Windows"
$app.appendChild($xml.CreateElement("Version")).InnerText = $asmver
$app.appendChild($xml.CreateElement("ID")).InnerText = "3191d2f3-bf48-48ea-97a2-59fb32722d0a"
$app.appendChild($xml.CreateElement("File")).InnerText = $CI_PROJECT_URL + "/-/jobs/" + $CI_JOB_ID + "/artifacts/raw/package.zip"
$app.appendChild($xml.CreateElement("Hash")).InnerText = $(Get-FileHash .\package.zip).Hash
$app.appendChild($xml.CreateElement("MainFile")).InnerText = $file.Name
echo NULL > app.xml
$xml.save($(gi .\app.xml).Fullname)
$tmp1 = $asmver.split('.')[2]
$tmp2 = $asmver.split('.')[3]
$suffix = "$tmp1.$tmp2"
cd Core
dotnet pack --version-suffix "$suffix" -c Release -o .
$tmp = $(Get-Item $(Resolve-Path *.nupkg).Path).Name
echo $tmp
dotnet nuget push $tmp -s https://api.nuget.org/v3/index.json -k $NUGET
cd ..\Misc
dotnet pack --version-suffix "$suffix" -c Release -o .
$tmp = $(Get-Item $(Resolve-Path *.nupkg).Path).Name
echo $tmp
dotnet nuget push $tmp -s https://api.nuget.org/v3/index.json -k $NUGET
cd ..\AspNet
dotnet pack --version-suffix "$suffix" -c Release -o .
$tmp = $(Get-Item $(Resolve-Path *.nupkg).Path).Name
echo $tmp
dotnet nuget push $tmp -s https://api.nuget.org/v3/index.json -k $NUGET
cd ..\W32
dotnet pack --version-suffix "$suffix" -c Release -o .
$tmp = $(Get-Item $(Resolve-Path *.nupkg).Path).Name
echo $tmp
dotnet nuget push $tmp -s https://api.nuget.org/v3/index.json -k $NUGET
cd ..\Commandline
dotnet pack --version-suffix "$suffix" -c Release -o .
$tmp = $(Get-Item $(Resolve-Path *.nupkg).Path).Name
echo $tmp
dotnet nuget push $tmp -s https://api.nuget.org/v3/index.json -k $NUGET
cd ..
mkdir nugets
cp .\Core\*.nupkg .\nugets\
cp .\Misc\*.nupkg .\nugets\
cp .\W32\*.nupkg .\nugets\
cp .\Commandline\*.nupkg .\nugets\
artifacts:
paths:
- package.zip
- app.xml
- nugets
only:
- master

View File

@ -1,33 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Library</OutputType>
<RootNamespace>CC_Functions.AspNet</RootNamespace>
<AssemblyName>CC_Functions.AspNet</AssemblyName>
<Deterministic>false</Deterministic>
<PackageId>CC-Functions.AspNet</PackageId>
<Title>CC-Functions.AspNet</Title>
<Authors>JFronny</Authors>
<Description>Random pieces of code for Asp.Net, including my SerialDict integrated Database</Description>
<Copyright>Copyright 2020</Copyright>
<PackageProjectUrl>https://gitlab.com/JFronny/CC-Functions</PackageProjectUrl>
<RepositoryUrl>https://gitlab.com/JFronny/CC-Functions.git</RepositoryUrl>
<RepositoryType>git</RepositoryType>
<AssemblyVersion>1.1.*</AssemblyVersion>
<FileVersion>1.0.0.0</FileVersion>
<VersionSuffix>0.0</VersionSuffix>
<PackageVersion>1.1.$(VersionSuffix)</PackageVersion>
<TargetFramework>netstandard2.1</TargetFramework>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DocumentationFile>bin\Debug\Core.xml</DocumentationFile>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DocumentationFile>bin\Release\Core.xml</DocumentationFile>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="protobuf-net" Version="3.0.62" />
<PackageReference Include="System.Text.Json" Version="5.0.0" />
</ItemGroup>
</Project>

View File

@ -1,138 +0,0 @@
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Text.Json;
using System.Text.Json.Serialization;
namespace CC_Functions.AspNet
{
/// <summary>
/// Provides serializing dictionary with Guid keys
/// </summary>
public class DictionaryGuidConverter : JsonConverterFactory
{
/// <inheritdoc />
public override bool CanConvert(Type typeToConvert)
{
if (!typeToConvert.IsGenericType)
{
return false;
}
if (typeToConvert.GetGenericTypeDefinition() != typeof(Dictionary<,>))
{
return false;
}
return typeToConvert.GetGenericArguments()[0] == typeof(Guid);
}
/// <inheritdoc />
public override JsonConverter CreateConverter(Type typeToConvert, JsonSerializerOptions options)
{
Type valueType = typeToConvert.GetGenericArguments()[1];
JsonConverter converter = (JsonConverter)Activator.CreateInstance(
typeof(DictionaryGuidConverterInner<>).MakeGenericType(valueType),
BindingFlags.Instance | BindingFlags.Public,
null,
new object[] { options },
null);
return converter;
}
private class DictionaryGuidConverterInner<TValue> : JsonConverter<Dictionary<Guid, TValue>>
{
private readonly JsonConverter<TValue> _valueConverter;
private Type _valueType;
public DictionaryGuidConverterInner(JsonSerializerOptions options)
{
// For performance, use the existing converter if available.
_valueConverter = (JsonConverter<TValue>)options
.GetConverter(typeof(TValue));
// Cache the key and value types.
_valueType = typeof(TValue);
}
public override Dictionary<Guid, TValue> Read(
ref Utf8JsonReader reader,
Type typeToConvert,
JsonSerializerOptions options)
{
if (reader.TokenType != JsonTokenType.StartObject)
{
throw new JsonException();
}
Dictionary<Guid, TValue> dictionary = new Dictionary<Guid, TValue>();
while (reader.Read())
{
if (reader.TokenType == JsonTokenType.EndObject)
{
return dictionary;
}
// Get the key.
if (reader.TokenType != JsonTokenType.PropertyName)
{
throw new JsonException();
}
string propertyName = reader.GetString();
// For performance, parse with ignoreCase:false first.
if (!Guid.TryParse(propertyName, out Guid key))
{
throw new JsonException(
$"Unable to convert \"{propertyName}\" to Guid.");
}
// Get the value.
TValue v;
if (_valueConverter != null)
{
reader.Read();
v = _valueConverter.Read(ref reader, _valueType, options);
}
else
{
v = JsonSerializer.Deserialize<TValue>(ref reader, options);
}
// Add to dictionary.
dictionary.Add(key, v);
}
throw new JsonException();
}
public override void Write(
Utf8JsonWriter writer,
Dictionary<Guid, TValue> dictionary,
JsonSerializerOptions options)
{
writer.WriteStartObject();
foreach (KeyValuePair<Guid, TValue> kvp in dictionary)
{
writer.WritePropertyName(kvp.Key.ToString());
if (_valueConverter != null)
{
_valueConverter.Write(writer, kvp.Value, options);
}
else
{
JsonSerializer.Serialize(writer, kvp.Value, options);
}
}
writer.WriteEndObject();
}
}
}
}

View File

@ -1,21 +0,0 @@
using System.Text.Json;
namespace CC_Functions.AspNet
{
/// <summary>
/// Extension methods for various types
/// </summary>
public static class GenericExtensions
{
/// <summary>
/// Include CCF json extensions for this serializer
/// </summary>
/// <param name="options">The options to include CCF in</param>
/// <returns>The options including CCF</returns>
public static JsonSerializerOptions AddCcf(this JsonSerializerOptions options)
{
options.Converters.Add(new DictionaryGuidConverter());
return options;
}
}
}

View File

@ -1,164 +0,0 @@
using System;
using System.Collections;
using System.Collections.Generic;
namespace CC_Functions.AspNet
{
/// <summary>
/// Provides synchronizing for dictionaries with saving/loading backends
/// </summary>
/// <typeparam name="T">The key type</typeparam>
/// <typeparam name="U">The param type</typeparam>
public abstract class SaveLoadDict<T, U> : IDictionary<T, U>
{
/// <inheritdoc />
public IEnumerator<KeyValuePair<T, U>> GetEnumerator()
{
lock (this) return Load().GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
lock (this) return GetEnumerator();
}
/// <inheritdoc />
public void Add(KeyValuePair<T, U> item)
{
lock (this) Add(item.Key, item.Value);
}
/// <inheritdoc />
public void Clear()
{
lock (this) Save(new Dictionary<T, U>());
}
/// <inheritdoc />
public bool Contains(KeyValuePair<T, U> item)
{
lock (this) return Load().Contains(item);
}
/// <inheritdoc />
public void CopyTo(KeyValuePair<T, U>[] array, int arrayIndex)
{
lock (this) Load().CopyTo(array, arrayIndex);
}
/// <inheritdoc />
public bool Remove(KeyValuePair<T, U> item)
{
lock (this)
{
IDictionary<T, U> dictionary = Load();
try
{
return dictionary.Remove(item);
}
finally
{
Save(dictionary);
}
}
}
/// <inheritdoc />
public int Count
{
get { lock (this) return Load().Count; }
}
/// <inheritdoc />
public bool IsReadOnly => false;
/// <inheritdoc />
public void Add(T key, U value)
{
lock (this)
{
IDictionary<T, U> dictionary = Load();
dictionary.Add(key, value);
Save(dictionary);
}
}
/// <inheritdoc />
public bool ContainsKey(T key)
{
lock (this) return Load().ContainsKey(key);
}
/// <inheritdoc />
public bool Remove(T key)
{
lock (this)
{
IDictionary<T, U> dictionary = Load();
try
{
return dictionary.Remove(key);
}
finally
{
Save(dictionary);
}
}
}
/// <inheritdoc />
public bool TryGetValue(T key, out U value)
{
lock (this) return Load().TryGetValue(key, out value);
}
/// <inheritdoc />
public U this[T key]
{
get
{
lock (this) return Load()[key];
}
set
{
lock (this)
{
IDictionary<T, U> dictionary = Load();
dictionary[key] = value;
Save(dictionary);
}
}
}
/// <inheritdoc />
public ICollection<T> Keys
{
get { lock (this) return Load().Keys; }
}
/// <inheritdoc />
public ICollection<U> Values
{
get { lock (this) return Load().Values; }
}
/// <summary>
/// Replace the current content based on the current state
/// </summary>
/// <param name="f">Function to mutate the content</param>
public void Mutate(Func<IDictionary<T, U>, IDictionary<T, U>> f)
{
lock (this) Save(f(Load()));
}
/// <summary>
/// Save the dictionary content
/// </summary>
/// <param name="v">Dictionary content to save</param>
protected abstract void Save(IDictionary<T, U> v);
/// <summary>
/// Load the content to a dictionary
/// </summary>
/// <returns>The loaded content</returns>
protected abstract IDictionary<T, U> Load();
}
}

View File

@ -1,73 +0,0 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using ProtoBuf;
namespace CC_Functions.AspNet
{
/// <summary>
/// An implementation of SaveLoadDict that uses Protobuf-net for serialization and Guid keys
/// </summary>
/// <typeparam name="T">The data type</typeparam>
public abstract class SerialDict<T> : SaveLoadDict<Guid, T>
{
//Interface
/// <summary>
/// Gets the directory containing databases
/// </summary>
public abstract string DatabasesDir { get; }
/// <summary>
/// Gets the file name for this database. Must not contain the path
/// </summary>
public abstract string DatabaseFileName { get; }
/// <summary>
/// Called when the database is loaded. Use for preparing initial entries
/// </summary>
public event LoadedD Loaded;
/// <summary>
/// Called when the database is loaded. Use for preparing initial entries
/// </summary>
/// <param name="v">The current dictionary content</param>
public delegate void LoadedD(IDictionary<Guid, T> v);
/// <summary>
/// Loads the dictionary and replaces Guids with strings. Use for sending
/// </summary>
/// <returns>The simplified dictionary</returns>
public IDictionary<string, T> GetSendable() => Load().ToDictionary(s => s.Key.ToString(), s => s.Value);
//Internal
private string GetRel() => Path.Combine(DatabasesDir, DatabaseFileName);
/// <inheritdoc />
protected override IDictionary<Guid, T> Load()
{
if (!Directory.Exists(DatabasesDir))
Directory.CreateDirectory(DatabasesDir);
IDictionary<Guid, T> v;
if (File.Exists(GetRel()))
{
using (FileStream file = File.OpenRead(GetRel()))
v = Serializer.Deserialize<Dictionary<Guid, T>>(file);
Loaded?.Invoke(v);
return v;
}
else
{
v = new Dictionary<Guid, T>();
Loaded?.Invoke(v);
Save(v);
return v;
}
}
/// <inheritdoc />
protected override void Save(IDictionary<Guid, T> dict)
{
if (!Directory.Exists(DatabasesDir))
Directory.CreateDirectory(DatabasesDir);
using FileStream file = File.Create(GetRel());
Serializer.Serialize(file, dict);
}
}
}

View File

@ -13,10 +13,6 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Commandline", "Commandline\
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CLITest", "CLITest\CLITest.csproj", "{3FAB0713-3021-4C6A-BF4A-ABBD542634A6}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Core", "Core\Core.csproj", "{780EC190-E223-46DE-B6FB-1CF56ABDF34E}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AspNet", "AspNet\AspNet.csproj", "{1A9F3CD1-559B-4429-B8A6-490AF7188A2E}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@ -43,14 +39,6 @@ Global
{3FAB0713-3021-4C6A-BF4A-ABBD542634A6}.Debug|Any CPU.Build.0 = Debug|Any CPU
{3FAB0713-3021-4C6A-BF4A-ABBD542634A6}.Release|Any CPU.ActiveCfg = Release|Any CPU
{3FAB0713-3021-4C6A-BF4A-ABBD542634A6}.Release|Any CPU.Build.0 = Release|Any CPU
{780EC190-E223-46DE-B6FB-1CF56ABDF34E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{780EC190-E223-46DE-B6FB-1CF56ABDF34E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{780EC190-E223-46DE-B6FB-1CF56ABDF34E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{780EC190-E223-46DE-B6FB-1CF56ABDF34E}.Release|Any CPU.Build.0 = Release|Any CPU
{1A9F3CD1-559B-4429-B8A6-490AF7188A2E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{1A9F3CD1-559B-4429-B8A6-490AF7188A2E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{1A9F3CD1-559B-4429-B8A6-490AF7188A2E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{1A9F3CD1-559B-4429-B8A6-490AF7188A2E}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE

View File

@ -1,32 +1,14 @@
using System;
using System.Drawing;
using System.Threading;
using CC_Functions.Commandline;
using CC_Functions.Commandline.TUI;
using CC_Functions.Core;
namespace CLITest
{
internal class Program
{
private static void Main()
private static void Main(string[] args)
{
Thread.CurrentThread.ForceInvariantCulture();
//Parse test
if (new ArgsParse(new[] { "--meme", "Fuk u", "--meme:yeet", "--meme:yote", "--meme" })["meme"] != "yote")
throw new Exception("ArgsParse error 1");
if (!new ArgsParse(new[] { "--meme", "Fuk u", "--meme:yeet", "--meme:yote", "--meme" }).GetBool("meme"))
throw new Exception("ArgsParse error 2");
if (new ArgsParse(new[] {"--meme:"}).GetBool("meme"))
throw new Exception("ArgsParse error 3");
if (!new ArgsParse(new[] {"--meme:true"}).GetBool("mEme"))
throw new Exception("ArgsParse error 4");
if (new ArgsParse(new[] {"--meme:1.1.2019"}).Get<DateTime>("meme") != new DateTime(2019, 1, 1))
throw new Exception("ArgsParse error 5");
if (new ArgsParse(new[] {"--meme:2019"}).Get("meme", s => s == null ? DateTime.Now : DateTime.Parse("1.1." + s)) != new DateTime(2019, 1, 1))
throw new Exception("ArgsParse error 6");
//Display test
Console.BackgroundColor = ConsoleColor.Black;
Console.ForegroundColor = ConsoleColor.White;
Console.Clear();
@ -38,7 +20,7 @@ namespace CLITest
BackColor = ConsoleColor.DarkGreen
};
screen.Controls.Add(btn1);
btn1.Click += (screen1, eventArgs) => { DiffDraw.Draw(true, true); };
btn1.Click += (screen1, eventArgs) => { DiffDraw.FullDraw(true); };
Label lab1 = new Label("Meem")
{
Point = new Point(2, 1),
@ -97,11 +79,6 @@ namespace CLITest
}
Console.ResetColor();
Console.Clear();
Console.WriteLine("Test2");
Thread.Sleep(100);
DiffDraw.Clear(10, 10);
DiffDraw.Draw(true, false);
Console.Clear();
Console.WriteLine("Bye");
}
}

View File

@ -1,98 +0,0 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Reflection;
using System.Threading;
namespace CC_Functions.Commandline
{
/// <summary>
/// A class to provide basic parsing for program arguments
/// </summary>
public class ArgsParse : IEnumerable<string>
{
private readonly string[] _args;
/// <summary>
/// Create a new instance based on the specified args
/// </summary>
/// <param name="args">The inputted args. Should be a parameter of the main method</param>
public ArgsParse(string[] args) => _args = args ?? throw new NullReferenceException();
/// <summary>
/// Shadowed from the base args
/// </summary>
/// <param name="i">The index in the base args</param>
public string this[int i]
{
get => _args[i];
set => _args[i] = value;
}
/// <summary>
/// Shadowed from the base args
/// </summary>
/// <returns>An enumerator for the base args</returns>
IEnumerator<string> IEnumerable<string>.GetEnumerator() => ((IEnumerable<string>)_args).GetEnumerator();
/// <summary>
/// Shadowed from the base args
/// </summary>
/// <returns></returns>
public IEnumerator GetEnumerator() => _args.GetEnumerator();
/// <summary>
/// Gets the string specified for this key or null
/// </summary>
/// <param name="i">The name of the parameter</param>
public string? this[string i]
{
get
{
string? selected = null;
foreach (string s in _args)
if (s.TrimStart('-', '/').ToLower().StartsWith($"{i.ToLower()}:"))
selected = string.Join("", s.TrimStart('-', '/').Skip(i.Length + 1));
return selected;
}
}
/// <summary>
/// Gets the string specified for this key or null
/// </summary>
/// <param name="i">The name of the parameter</param>
/// <returns>The value or null</returns>
public string? GetString(string i) => this[i];
/// <summary>
/// Gets a boolean value with the specified name. Either specified as --i or --i:true
/// </summary>
/// <param name="i">The name of the parameter</param>
/// <returns>The value</returns>
public bool GetBool(string i) => _args.Any(s => s.ToLower().TrimStart('-', '/') == i.ToLower()) || bool.TryParse(this[i], out bool res) && res;
/// <summary>
/// Gets an arg using a transformer specified by you. The value passed will be the same as this[i]
/// </summary>
/// <param name="i">The name of the parameter</param>
/// <param name="func">A null-safe function to convert a string to the expected type</param>
/// <typeparam name="T">The type to convert to</typeparam>
/// <returns>The converted value</returns>
public T Get<T>(string i, Func<string?, T> func) => func(this[i]);
/// <summary>
/// Uses reflection to call the Parse method on types providing it. Use Get() with a func param for other types
/// This will return null if the type is not found
/// </summary>
/// <param name="i">The name of the parameter</param>
/// <typeparam name="T">The type to convert to</typeparam>
/// <returns>The converted value</returns>
public T Get<T>(string i)
{
MethodInfo[] parse = typeof(T).GetMethods().Where(s => s.Name.ToLower() == "parse"
&& s.GetParameters().Length == 1
&& s.GetParameters()[0].ParameterType == typeof(string)
&& s.ReturnType == typeof(T)
&& !s.IsAbstract && !s.IsPrivate && s.IsStatic).ToArray();
if (parse.Length == 0)
throw new InvalidOperationException("Could not find a valid parse method");
string? v = this[i];
if (v == null)
return default;
return (T) parse[0].Invoke(null, new object[] {v});
}
}
}

View File

@ -9,11 +9,11 @@
<Deterministic>false</Deterministic>
<PackageId>CC-Functions.Commandline</PackageId>
<Title>CC-Functions.Commandline</Title>
<Authors>JFronny</Authors>
<Authors>CC24</Authors>
<Description>Random pieces of code used across my projects. CLI/TUI extensions</Description>
<Copyright>Copyright 2020</Copyright>
<PackageProjectUrl>https://gitlab.com/JFronny/CC-Functions</PackageProjectUrl>
<RepositoryUrl>https://gitlab.com/JFronny/CC-Functions.git</RepositoryUrl>
<PackageProjectUrl>https://github.com/JFronny/CC-Functions</PackageProjectUrl>
<RepositoryUrl>https://github.com/JFronny/CC-Functions.git</RepositoryUrl>
<RepositoryType>git</RepositoryType>
<AssemblyVersion>1.1.*</AssemblyVersion>
<FileVersion>1.0.0.0</FileVersion>
@ -31,6 +31,7 @@
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\Core\Core.csproj" />
<ProjectReference Include="..\Misc\Misc.csproj" />
</ItemGroup>
</Project>

View File

@ -1,7 +1,7 @@
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using CC_Functions.Core;
using CC_Functions.Misc;
namespace CC_Functions.Commandline.TUI
{

View File

@ -1,6 +1,6 @@
using System;
using System.Drawing;
using CC_Functions.Core;
using CC_Functions.Misc;
namespace CC_Functions.Commandline.TUI
{
@ -10,7 +10,11 @@ namespace CC_Functions.Commandline.TUI
public class CenteredScreen : Screen
{
private bool _resizing;
private Size _actualSize;
/// <summary>
/// The actual size of this control. The "Size" property is assigned automatically
/// </summary>
public Size ActualSize;
/// <summary>
/// The panel used for storing and rendering the actual controls
@ -29,9 +33,9 @@ namespace CC_Functions.Commandline.TUI
/// <param name="color">Whether to use color when drawing</param>
public CenteredScreen(int width, int height, ConsoleColor contentBack, bool color = true) : base(width, height, color)
{
_titleLabel = new Label(Title);
ContentPanel = new Panel {BackColor = contentBack};
ActualSize = new Size(width, height);
_titleLabel = new Label(Title);
Controls.Add(ContentPanel);
Controls.Add(_titleLabel);
WindowResize += (screen, args) => CalculatePosition();
@ -55,22 +59,6 @@ namespace CC_Functions.Commandline.TUI
}
}
/// <summary>
/// The actual size of this control. The "Size" property is assigned automatically
/// </summary>
public Size ActualSize
{
get => _actualSize;
set
{
if (_actualSize != value)
{
_actualSize = value;
CalculatePosition(true);
}
}
}
/// <summary>
/// Calculates the Size variable, Title and ContentPanel position/size
/// </summary>
@ -88,7 +76,7 @@ namespace CC_Functions.Commandline.TUI
if (!initial)
{
Console.Clear();
DiffDraw.Draw(Color, true);
DiffDraw.FullDraw(Color);
}
_resizing = false;
}

View File

@ -1,6 +1,6 @@
using System;
using System.Drawing;
using CC_Functions.Core;
using CC_Functions.Misc;
namespace CC_Functions.Commandline.TUI
{

View File

@ -1,9 +1,8 @@
using System;
using System.Drawing;
using CC_Functions.Commandline.TUI;
using CC_Functions.Core;
using CC_Functions.Misc;
namespace CC_Functions.Commandline
namespace CC_Functions.Commandline.TUI
{
/// <summary>
/// Provides differential drawing of a char[,] Do not use in combination with System.Console
@ -27,14 +26,12 @@ namespace CC_Functions.Commandline
/// Draws to the console
/// </summary>
/// <param name="color">Whether to use color</param>
/// <param name="full">Whether to redraw the entire screen (should be done from time to time to prevent corruption)</param>
public static void Draw(bool color, bool full = false)
public static void Draw(bool color)
{
Console.CursorTop = 0;
Console.CursorLeft = 0;
ConsoleColor fCol = Console.ForegroundColor;
ConsoleColor bCol = Console.BackgroundColor;
if (full) Console.Clear();
int width = Width;
int height = Height;
for (int y = 0; y < height; y++)
@ -42,8 +39,44 @@ namespace CC_Functions.Commandline
for (int x = 0; x < width; x++)
{
Pixel tmp1 = Screen[y, x];
if (!full && tmp1 == _last[y, x]) continue;
if (!ReferenceEquals(tmp1, null) && color)
if (tmp1 == _last[y, x]) continue;
if (color)
{
if (Console.ForegroundColor != tmp1.ForeColor)
Console.ForegroundColor = tmp1.ForeColor;
if (Console.BackgroundColor != tmp1.BackColor)
Console.BackgroundColor = tmp1.BackColor;
}
Console.CursorLeft = x;
Console.Write(tmp1);
}
Console.WriteLine();
Console.CursorLeft = 0;
}
Console.ForegroundColor = fCol;
Console.BackgroundColor = bCol;
_last = Screen;
}
/// <summary>
/// Redraws the entire screen (should be done from time to time to prevent corruption)
/// </summary>
/// <param name="color">Whether to use color</param>
public static void FullDraw(bool color)
{
Console.CursorTop = 0;
Console.CursorLeft = 0;
ConsoleColor fcol = Console.ForegroundColor;
ConsoleColor bcol = Console.BackgroundColor;
Console.Clear();
int width = Width;
int height = Height;
for (int y = 0; y < height; y++)
{
for (int x = 0; x < width; x++)
{
Pixel? tmp1 = Screen[y, x];
if (tmp1 != null && color)
{
if (Console.ForegroundColor != tmp1.ForeColor)
Console.ForegroundColor = tmp1.ForeColor;
@ -56,8 +89,8 @@ namespace CC_Functions.Commandline
Console.WriteLine();
Console.CursorLeft = 0;
}
Console.ForegroundColor = fCol;
Console.BackgroundColor = bCol;
Console.ForegroundColor = fcol;
Console.BackgroundColor = bcol;
_last = Screen;
}

View File

@ -1,5 +1,5 @@
using System.Drawing;
using CC_Functions.Core;
using CC_Functions.Misc;
namespace CC_Functions.Commandline.TUI
{
@ -8,40 +8,20 @@ namespace CC_Functions.Commandline.TUI
/// </summary>
public class Label : Control
{
private string _content;
/// <summary>
/// The text inside this label
/// </summary>
public string Content;
/// <summary>
/// Creates a new label
/// </summary>
/// <param name="content">The text inside this label</param>
public Label(string content)
{
_content = "";
Content = content;
}
public Label(string content) => Content = content;
/// <inheritdoc />
public override bool Selectable { get; } = false;
/// <summary>
/// The text inside this label
/// </summary>
public string Content
{
get => _content;
set
{
if (_content != value)
{
_content = value;
char[,] inp = Content.ToNdArray2D();
int w = inp.GetLength(1);
int h = inp.GetLength(0);
Size = new Size(w, h);
}
}
}
/// <inheritdoc />
public override Pixel[,] Render()
{
@ -52,6 +32,7 @@ namespace CC_Functions.Commandline.TUI
for (int x = 0; x < w; x++)
for (int y = 0; y < h; y++)
output[x, y] = new Pixel(BackColor, ForeColor, inp[x, y]);
Size = new Size(w, h);
return output;
}
}

View File

@ -1,6 +1,6 @@
using System.Collections.Generic;
using System.Linq;
using CC_Functions.Core;
using CC_Functions.Misc;
namespace CC_Functions.Commandline.TUI
{

View File

@ -48,26 +48,13 @@ namespace CC_Functions.Commandline.TUI
}
}
/// <summary>
/// The current index of the tab-selected control in an array of selectable controls
/// </summary>
public int TabPoint
{
get => _tabPoint;
set
{
if (_tabPoint != value)
{
_tabPoint = value;
}
}
}
private int _wndHeight = Console.WindowHeight;
private int _wndWidth = Console.WindowWidth;
private int _tabPoint;
/// <summary>
/// The current index of the tab-selected control in an array of selectable controls
/// </summary>
public int TabPoint;
/// <summary>
/// Creates a screen object. Multiple can be instantiated but drawing one overrides others. Use panels for that
@ -100,7 +87,6 @@ namespace CC_Functions.Commandline.TUI
/// <returns>The new state of the screen</returns>
public new Pixel[,] Render()
{
FixSelection();
Pixel[,] tmp = base.Render();
DiffDraw.Clear(tmp);
DiffDraw.Draw(Color);
@ -129,18 +115,23 @@ namespace CC_Functions.Commandline.TUI
break;
case ConsoleKey.Enter:
if (selectable.Any() && selectable.Length >= TabPoint && selectable[TabPoint].Enabled)
{
selectable[TabPoint].InvokeClick(this);
render = true;
}
break;
case ConsoleKey.Escape:
Close?.Invoke(this, new EventArgs());
break;
default:
if (selectable.Any() && selectable.Length >= TabPoint && selectable[TabPoint].Enabled)
{
InvokeInput(this, input);
selectable[TabPoint].InvokeInput(this, input);
InvokeInput(this, input);
render = true;
}
break;
}
render = true;
}
if (_wndWidth != Console.WindowWidth || _wndHeight != Console.WindowHeight)
{
@ -151,8 +142,6 @@ namespace CC_Functions.Commandline.TUI
}
if (canRedraw && render)
Render();
else
FixSelection();
}
/// <summary>
@ -185,21 +174,10 @@ namespace CC_Functions.Commandline.TUI
TabPoint--;
if (TabPoint < 0) TabPoint = selectable.Length - 1;
}
FixSelection(true);
}
}
private void FixSelection(bool draw = false)
{
Control[] controls = EnumerateRecursive();
Control[] selectable = controls.Where(s => s.Selectable).ToArray();
if (selectable.Any())
{
foreach (Control control in selectable) control.Selected = false;
selectable[TabPoint].Selected = true;
TabChanged?.Invoke(this, new EventArgs());
if (draw)
Render();
Render();
}
}

View File

@ -1,5 +1,5 @@
using System;
using CC_Functions.Core;
using CC_Functions.Misc;
namespace CC_Functions.Commandline.TUI
{

View File

@ -2,7 +2,7 @@ using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using CC_Functions.Core;
using CC_Functions.Misc;
namespace CC_Functions.Commandline.TUI
{
@ -135,6 +135,7 @@ namespace CC_Functions.Commandline.TUI
case ConsoleKey.Enter:
if (lines.Length < Size.Height)
{
tmp = lines.ToList();
lines[Cursor.Y] = lines[Cursor.Y].Insert(Math.Max(Cursor.X, 0), "\n");
Cursor.Y++;
Cursor.X = 0;

View File

@ -1,28 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Library</OutputType>
<RootNamespace>CC_Functions.Core</RootNamespace>
<AssemblyName>CC_Functions.Core</AssemblyName>
<Deterministic>false</Deterministic>
<PackageId>CC-Functions.Core</PackageId>
<Title>CC-Functions.Core</Title>
<Authors>JFronny</Authors>
<Description>Random pieces of code without external dependencies. Used in other CC_Functions packages</Description>
<Copyright>Copyright 2020</Copyright>
<PackageProjectUrl>https://gitlab.com/JFronny/CC-Functions</PackageProjectUrl>
<RepositoryUrl>https://gitlab.com/JFronny/CC-Functions.git</RepositoryUrl>
<RepositoryType>git</RepositoryType>
<AssemblyVersion>1.1.*</AssemblyVersion>
<FileVersion>1.0.0.0</FileVersion>
<VersionSuffix>0.0</VersionSuffix>
<PackageVersion>1.1.$(VersionSuffix)</PackageVersion>
<TargetFramework>netstandard2.1</TargetFramework>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DocumentationFile>bin\Debug\Core.xml</DocumentationFile>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DocumentationFile>bin\Release\Core.xml</DocumentationFile>
</PropertyGroup>
</Project>

View File

@ -1,255 +0,0 @@
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Globalization;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Net;
using System.Threading;
namespace CC_Functions.Core
{
/// <summary>
/// Extension methods for various types
/// </summary>
public static class GenericExtensions
{
/// <summary>
/// Gets an element from the dictionary or adds the default
/// </summary>
/// <param name="dict">The dictionary to get from</param>
/// <param name="key">The key to check</param>
/// <param name="def">The default value to place</param>
/// <typeparam name="TKey">The key type</typeparam>
/// <typeparam name="TValue">The value type</typeparam>
/// <returns>The element at the key</returns>
public static TValue Get<TKey, TValue>(this IDictionary<TKey, TValue> dict, TKey key, TValue def = default)
{
if (!dict.ContainsKey(key))
dict[key] = def;
return dict[key];
}
/// <summary>
/// Sets an element and returns it
/// </summary>
/// <param name="dict">The dictionary to set in</param>
/// <param name="key">The key to set at</param>
/// <param name="val">The value to place</param>
/// <typeparam name="TKey">The key type</typeparam>
/// <typeparam name="TValue">The value type</typeparam>
/// <returns>The value that was placed</returns>
public static TValue Set<TKey, TValue>(this IDictionary<TKey, TValue> dict, TKey key, TValue val = default)
{
dict[key] = val;
return dict[key];
}
/// <summary>
/// Tries to cast an object
/// </summary>
/// <param name="o">The object to try to parse</param>
/// <param name="parsed">The parsed object (if successful) or the default (usually null)</param>
/// <typeparam name="T">The type to cast to</typeparam>
/// <returns>Whether the cast was successful</returns>
public static bool TryCast<T>(this object o, out T parsed)
{
try
{
parsed = (T) o;
return true;
}
catch
{
parsed = default;
return false;
}
}
/// <summary>
/// Runs a function that transforms an object in-line
/// </summary>
/// <param name="self">The object to run on</param>
/// <param name="func">The function to run</param>
/// <typeparam name="TIn">The input type</typeparam>
/// <typeparam name="TOut">The output type</typeparam>
/// <returns></returns>
public static TOut SelectO<TIn, TOut>(this TIn self, Func<TIn, TOut> func) => func.Invoke(self);
/// <summary>
/// Runs a function under a condition in-line (equal to if)
/// </summary>
/// <param name="condition">The condition to check</param>
/// <param name="func">The function to run</param>
public static void RunIf(bool condition, Action func)
{
if (condition)
func();
}
/// <summary>
/// Parses a string to a value of an enum
/// </summary>
/// <param name="value">The string to parse</param>
/// <typeparam name="TEnum">The enum type (MUST be an enum)</typeparam>
/// <returns>The element</returns>
public static TEnum ParseToEnum<TEnum>(string value) => (TEnum) Enum.Parse(typeof(TEnum),
Enum.GetNames(typeof(TEnum)).First(s => s.ToLower() == value.ToLower()));
/// <summary>
/// Parses a string to a nullable bool (defaults to null if parse fails)
/// </summary>
/// <param name="value">The st string to parse</param>
/// <returns>The output nullable bool</returns>
public static bool? ParseBool(string value) =>
bool.TryParse(value, out bool tmp) ? (bool?) tmp : null;
/// <summary>
/// AND operation for nullable bools (uses <see cref="True">True</see>)
/// </summary>
/// <param name="left">First bool to check</param>
/// <param name="right">Second bool to check</param>
/// <returns>The operation result</returns>
public static bool And(this bool? left, bool? right) => left.True() && right.True();
/// <summary>
/// OR operation for nullable bools (uses <see cref="True">True</see>)
/// </summary>
/// <param name="left">First bool to check</param>
/// <param name="right">Second bool to check</param>
/// <returns>The operation result</returns>
public static bool Or(this bool? left, bool? right) => left.True() || right.True();
/// <summary>
/// XOR operation for nullable bools (uses <see cref="True">True</see>)
/// </summary>
/// <param name="left">First bool to check</param>
/// <param name="right">Second bool to check</param>
/// <returns>The operation result</returns>
public static bool Xor(this bool? left, bool? right) => left.Or(right) && !left.And(right);
/// <summary>
/// Whether the nullable bool is true (null->false)
/// </summary>
/// <param name="self">Value to check</param>
/// <returns>Whether it is true</returns>
public static bool True(this bool? self) => self == true;
/// <summary>
/// Whether the nullable bool is false (null->false)
/// </summary>
/// <param name="self">Value to check</param>
/// <returns>Whether it is false</returns>
public static bool False(this bool? self) => self == false;
/// <summary>
/// Whether the nullable bool is null
/// </summary>
/// <param name="self">Value to check</param>
/// <returns>Whether it is null</returns>
public static bool Null(this bool? self) => self == null;
/// <summary>
/// Removes an element from a dictionary by its index (not key)
/// </summary>
/// <param name="dict">The dictionary to remove from</param>
/// <param name="index">The index of the value</param>
/// <typeparam name="TKey">The key type</typeparam>
/// <typeparam name="TValue">The value type</typeparam>
public static void RemoveAt<TKey, TValue>(this Dictionary<TKey, TValue> dict, int index) =>
dict.Remove(dict.Keys.ToArray()[index]);
/// <summary>
/// "Unshorten" (follow) an URL
/// </summary>
/// <param name="self">The URL to unshorten</param>
/// <returns>The unshortened URL</returns>
public static Uri Unshorten(this Uri self)
{
HttpWebRequest req = (HttpWebRequest) WebRequest.Create(self);
req.AllowAutoRedirect = true;
req.MaximumAutomaticRedirections = 100;
WebResponse resp = req.GetResponse();
return resp.ResponseUri;
}
/// <summary>
/// Rounds a RectangleF to a Rectangle instead of flooring
/// </summary>
/// <param name="self">The RectangleF to round</param>
/// <returns>The rounded Rectangle</returns>
public static Rectangle Round(this RectangleF self) => Rectangle.Round(self);
/// <summary>
/// Ceilings a RectangleF to a Rectangle instead of flooring
/// </summary>
/// <param name="self">The RectangleF to ceil (?)</param>
/// <returns>The ceiled (?) Rectangle</returns>
public static Rectangle Ceiling(this RectangleF self) => Rectangle.Ceiling(self);
/// <summary>
/// Pings an URL to check for availability
/// </summary>
/// <param name="self">The URL to check</param>
/// <returns>Whether the service is online</returns>
public static bool Ping(this Uri self)
{
try
{
HttpWebRequest request = (HttpWebRequest) WebRequest.Create(self);
request.Timeout = 3000;
request.AllowAutoRedirect = true;
using WebResponse response = request.GetResponse();
return true;
}
catch
{
return false;
}
}
/// <summary>
/// Gets the size of a dictionary
/// </summary>
/// <param name="directory">The dictionary to check</param>
/// <returns>The size of the dictionary</returns>
public static long GetSize(this DirectoryInfo directory) => IO.GetDirectorySize(directory.FullName);
/// <summary>
/// Adds a directory to an archive recursively
/// </summary>
/// <param name="archive">The archive to add to</param>
/// <param name="folderPath">The directory to add</param>
/// <param name="entryName">The name of the directory in-archive</param>
/// <param name="ignoredExtensions">Extensions for files to ignore</param>
/// <param name="ignoredPaths">Paths to exclude from adding</param>
/// <returns>The new entry</returns>
public static ZipArchiveEntry AddDirectory(this ZipArchive archive, string folderPath, string entryName,
string[] ignoredExtensions, string[] ignoredPaths)
{
entryName = entryName.TrimEnd('/');
ZipArchiveEntry result = archive.CreateEntry($"{entryName}/");
string[] files = Directory.GetFiles(folderPath);
foreach (string t in files)
if (!ignoredExtensions.Contains(Path.GetExtension(t)) &&
!ignoredPaths.Any(s => IO.CheckPathEqual(s, t)))
archive.CreateEntryFromFile(t, $"{entryName}/{Path.GetFileName(t)}");
string[] dirs = Directory.GetDirectories(folderPath);
foreach (string t in dirs)
if (!ignoredPaths.Any(s => IO.CheckPathEqual(s, t)))
archive.AddDirectory(t, $"{entryName}/{Path.GetFileName(t)}", ignoredExtensions,
ignoredPaths);
return result;
}
/// <summary>
/// Sets the threads cultureInfo properties to InvariantCulture. For testing
/// </summary>
/// <param name="thread">The thread to modify</param>
public static void ForceInvariantCulture(this Thread thread)
{
thread.CurrentCulture = CultureInfo.InvariantCulture;
thread.CurrentUICulture = CultureInfo.InvariantCulture;
}
}
}

21
LICENSE
View File

@ -1,21 +0,0 @@
MIT License
Copyright (c) 2020 J. Fronny
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@ -2,7 +2,7 @@
using System.Drawing;
using System.Linq;
namespace CC_Functions.Core
namespace CC_Functions.Misc
{
/// <summary>
/// Contains extension functions to work with 1D and 2D arrays

View File

@ -1,9 +1,10 @@
using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Net;
using CC_Functions.Core;
namespace CC_Functions.Misc
{
@ -12,6 +13,234 @@ namespace CC_Functions.Misc
/// </summary>
public static class GenericExtensions
{
/// <summary>
/// Gets an element from the dictionary or adds the default
/// </summary>
/// <param name="dict">The dictionary to get from</param>
/// <param name="key">The key to check</param>
/// <param name="def">The default value to place</param>
/// <typeparam name="TKey">The key type</typeparam>
/// <typeparam name="TValue">The value type</typeparam>
/// <returns>The element at the key</returns>
public static TValue Get<TKey, TValue>(this IDictionary<TKey, TValue> dict, TKey key, TValue def = default)
{
if (!dict.ContainsKey(key))
dict[key] = def;
return dict[key];
}
/// <summary>
/// Sets an element and returns it
/// </summary>
/// <param name="dict">The dictionary to set in</param>
/// <param name="key">The key to set at</param>
/// <param name="val">The value to place</param>
/// <typeparam name="TKey">The key type</typeparam>
/// <typeparam name="TValue">The value type</typeparam>
/// <returns>The value that was placed</returns>
public static TValue Set<TKey, TValue>(this IDictionary<TKey, TValue> dict, TKey key, TValue val = default)
{
dict[key] = val;
return dict[key];
}
/// <summary>
/// Tries to cast an object
/// </summary>
/// <param name="o">The object to try to parse</param>
/// <param name="parsed">The parsed object (if successful) or the default (usually null)</param>
/// <typeparam name="T">The type to cast to</typeparam>
/// <returns>Whether the cast was successful</returns>
public static bool TryCast<T>(this object o, out T parsed)
{
try
{
parsed = (T) o;
return true;
}
catch
{
parsed = default;
return false;
}
}
/// <summary>
/// Runs a function that transforms an object in-line
/// </summary>
/// <param name="self">The object to run on</param>
/// <param name="func">The function to run</param>
/// <typeparam name="TIn">The input type</typeparam>
/// <typeparam name="TOut">The output type</typeparam>
/// <returns></returns>
public static TOut SelectO<TIn, TOut>(this TIn self, Func<TIn, TOut> func) => func.Invoke(self);
/// <summary>
/// Runs a function under a condition in-line (equal to if)
/// </summary>
/// <param name="condition">The condition to check</param>
/// <param name="func">The function to run</param>
public static void RunIf(bool condition, Action func)
{
if (condition)
func();
}
/// <summary>
/// Parses a string to a value of an enum
/// </summary>
/// <param name="value">The string to parse</param>
/// <typeparam name="TEnum">The enum type (MUST be an enum)</typeparam>
/// <returns>The element</returns>
public static TEnum ParseToEnum<TEnum>(string value) => (TEnum) Enum.Parse(typeof(TEnum),
Enum.GetNames(typeof(TEnum)).First(s => s.ToLower() == value.ToLower()));
/// <summary>
/// Parses a string to a nullable bool (defaults to null if parse fails)
/// </summary>
/// <param name="value">The st string to parse</param>
/// <returns>The output nullable bool</returns>
public static bool? ParseBool(string value) =>
bool.TryParse(value, out bool tmp) ? (bool?) tmp : null;
/// <summary>
/// AND operation for nullable bools (uses <see cref="True">True</see>)
/// </summary>
/// <param name="left">First bool to check</param>
/// <param name="right">Second bool to check</param>
/// <returns>The operation result</returns>
public static bool And(this bool? left, bool? right) => left.True() && right.True();
/// <summary>
/// OR operation for nullable bools (uses <see cref="True">True</see>)
/// </summary>
/// <param name="left">First bool to check</param>
/// <param name="right">Second bool to check</param>
/// <returns>The operation result</returns>
public static bool Or(this bool? left, bool? right) => left.True() || right.True();
/// <summary>
/// XOR operation for nullable bools (uses <see cref="True">True</see>)
/// </summary>
/// <param name="left">First bool to check</param>
/// <param name="right">Second bool to check</param>
/// <returns>The operation result</returns>
public static bool Xor(this bool? left, bool? right) => left.Or(right) && !left.And(right);
/// <summary>
/// Whether the nullable bool is true (null->false)
/// </summary>
/// <param name="self">Value to check</param>
/// <returns>Whether it is true</returns>
public static bool True(this bool? self) => self == true;
/// <summary>
/// Whether the nullable bool is false (null->false)
/// </summary>
/// <param name="self">Value to check</param>
/// <returns>Whether it is false</returns>
public static bool False(this bool? self) => self == false;
/// <summary>
/// Whether the nullable bool is null
/// </summary>
/// <param name="self">Value to check</param>
/// <returns>Whether it is null</returns>
public static bool Null(this bool? self) => self == null;
/// <summary>
/// Removes an element from a dictionary by its index (not key)
/// </summary>
/// <param name="dict">The dictionary to remove from</param>
/// <param name="index">The index of the value</param>
/// <typeparam name="TKey">The key type</typeparam>
/// <typeparam name="TValue">The value type</typeparam>
public static void RemoveAt<TKey, TValue>(this Dictionary<TKey, TValue> dict, int index) =>
dict.Remove(dict.Keys.ToArray()[index]);
/// <summary>
/// Gets the size of a dictionary
/// </summary>
/// <param name="directory">The dictionary to check</param>
/// <returns>The size of the dictionary</returns>
public static long GetSize(this DirectoryInfo directory) => IO.GetDirectorySize(directory.FullName);
/// <summary>
/// Adds a directory to an archive recursively
/// </summary>
/// <param name="archive">The archive to add to</param>
/// <param name="folderPath">The directory to add</param>
/// <param name="entryName">The name of the directory in-archive</param>
/// <param name="ignoredExtensions">Extensions for files to ignore</param>
/// <param name="ignoredPaths">Paths to exclude from adding</param>
/// <returns>The new entry</returns>
public static ZipArchiveEntry AddDirectory(this ZipArchive archive, string folderPath, string entryName,
string[] ignoredExtensions, string[] ignoredPaths)
{
entryName = entryName.TrimEnd('/');
ZipArchiveEntry result = archive.CreateEntry($"{entryName}/");
string[] files = Directory.GetFiles(folderPath);
foreach (string t in files)
if (!ignoredExtensions.Contains(Path.GetExtension(t)) &&
!ignoredPaths.Any(s => IO.CheckPathEqual(s, t)))
archive.CreateEntryFromFile(t, $"{entryName}/{Path.GetFileName(t)}");
string[] dirs = Directory.GetDirectories(folderPath);
foreach (string t in dirs)
if (!ignoredPaths.Any(s => IO.CheckPathEqual(s, t)))
archive.AddDirectory(t, $"{entryName}/{Path.GetFileName(t)}", ignoredExtensions,
ignoredPaths);
return result;
}
/// <summary>
/// "Unshorten" (follow) an URL
/// </summary>
/// <param name="self">The URL to unshorten</param>
/// <returns>The unshortened URL</returns>
public static Uri Unshorten(this Uri self)
{
HttpWebRequest req = (HttpWebRequest) WebRequest.Create(self);
req.AllowAutoRedirect = true;
req.MaximumAutomaticRedirections = 100;
WebResponse resp = req.GetResponse();
return resp.ResponseUri;
}
/// <summary>
/// Pings an URL to check for availability
/// </summary>
/// <param name="self">The URL to check</param>
/// <returns>Whether the service is online</returns>
public static bool Ping(this Uri self)
{
try
{
HttpWebRequest request = (HttpWebRequest) WebRequest.Create(self);
request.Timeout = 3000;
request.AllowAutoRedirect = true;
using WebResponse response = request.GetResponse();
return true;
}
catch
{
return false;
}
}
/// <summary>
/// Rounds a RectangleF to a Rectangle instead of flooring
/// </summary>
/// <param name="self">The RectangleF to round</param>
/// <returns>The rounded Rectangle</returns>
public static Rectangle Round(this RectangleF self) => Rectangle.Round(self);
/// <summary>
/// Ceilings a RectangleF to a Rectangle instead of flooring
/// </summary>
/// <param name="self">The RectangleF to ceil (?)</param>
/// <returns>The ceiled (?) Rectangle</returns>
public static Rectangle Ceiling(this RectangleF self) => Rectangle.Ceiling(self);
/// <summary>
/// Extension method for <see cref="Crypto">Crypto's</see> Encrypt
/// </summary>

View File

@ -1,7 +1,7 @@
using System;
using System.IO;
namespace CC_Functions.Core
namespace CC_Functions.Misc
{
/// <summary>
/// IO functions

View File

@ -7,17 +7,17 @@
<Deterministic>false</Deterministic>
<PackageId>CC-Functions.Misc</PackageId>
<Title>CC-Functions.Misc</Title>
<Authors>JFronny</Authors>
<Authors>CC24</Authors>
<Description>Random pieces of code used across my projects. I do NOT recommend using this in your own project!</Description>
<Copyright>Copyright 2020</Copyright>
<PackageProjectUrl>https://gitlab.com/JFronny/CC-Functions</PackageProjectUrl>
<RepositoryUrl>https://gitlab.com/JFronny/CC-Functions.git</RepositoryUrl>
<PackageProjectUrl>https://github.com/JFronny/CC-Functions</PackageProjectUrl>
<RepositoryUrl>https://github.com/JFronny/CC-Functions.git</RepositoryUrl>
<RepositoryType>git</RepositoryType>
<AssemblyVersion>1.1.*</AssemblyVersion>
<FileVersion>1.0.0.0</FileVersion>
<VersionSuffix>0.0</VersionSuffix>
<PackageVersion>1.1.$(VersionSuffix)</PackageVersion>
<TargetFramework>netstandard2.1</TargetFramework>
<TargetFramework>netstandard2.0</TargetFramework>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DocumentationFile>bin\Debug\Misc.xml</DocumentationFile>
@ -29,14 +29,11 @@
<EmbeddedResource Include="HIDClasses.txt" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="System.Management" Version="5.0.0" />
<PackageReference Include="System.Security.Cryptography.ProtectedData" Version="5.0.0" />
<PackageReference Include="System.Management" Version="4.7.0" />
<PackageReference Include="System.Security.Cryptography.ProtectedData" Version="4.7.0" />
</ItemGroup>
<ItemGroup>
<Reference Include="System.IO.Compression" Condition="'$(TargetFramework)' == 'net461'" />
<Reference Include="System.IO.Compression.FileSystem" Condition="'$(TargetFramework)' == 'net461'" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Core\Core.csproj" />
</ItemGroup>
</Project>
</Project>

View File

@ -1,4 +1,4 @@
namespace CC_Functions.Core
namespace CC_Functions.Misc
{
/// <summary>
/// Characters for use in CC-Functions.CommandLine

View File

@ -1,6 +1,2 @@
# CC-Functions
[![UpTool2](https://img.shields.io/badge/Get%20it-on%20UpTool2-blue)](https://jfronny.gitlab.io/home/uptool)
[![Nuget](https://img.shields.io/nuget/v/CC-Functions.Core?label=CC-Functions.Core)](https://www.nuget.org/packages/CC-Functions.Core/)
[![Nuget](https://img.shields.io/nuget/v/CC-Functions.Misc?label=CC-Functions.Misc)](https://www.nuget.org/packages/CC-Functions.Misc/)
[![Nuget](https://img.shields.io/nuget/v/CC-Functions.W32?label=CC-Functions.W32)](https://www.nuget.org/packages/CC-Functions.W32/)
[![Nuget](https://img.shields.io/nuget/v/CC-Functions.W32?label=CC-Functions.Commandline)](https://www.nuget.org/packages/CC-Functions.Commandline/)
# CC-Functions
[![UpTool2](https://img.shields.io/github/v/tag/JFronny/CC-Functions?color=informational&label=UpTool2)](https://jfronny.github.io/home/uptool) [![Nuget](https://img.shields.io/nuget/v/CC-Functions.Misc?label=CC-Functions.Misc)](https://www.nuget.org/packages/CC-Functions.Misc/) [![Nuget](https://img.shields.io/nuget/v/CC-Functions.W32?label=CC-Functions.W32)](https://www.nuget.org/packages/CC-Functions.W32/)

View File

@ -5,13 +5,13 @@
<AssemblyName>CC-Functions.W32</AssemblyName>
<LangVersion>8</LangVersion>
<UseWindowsForms>true</UseWindowsForms>
<TargetFramework>netcoreapp3.1</TargetFramework>
<TargetFrameworks>net461;netcoreapp3.1</TargetFrameworks>
<Deterministic>false</Deterministic>
<Authors>JFronny</Authors>
<Authors>CC24</Authors>
<Description>W32 Additions for CC-Functions</Description>
<Copyright>Copyright 2020</Copyright>
<PackageProjectUrl>https://gitlab.com/JFronny/CC-Functions</PackageProjectUrl>
<RepositoryUrl>https://gitlab.com/JFronny/CC-Functions.git</RepositoryUrl>
<PackageProjectUrl>https://github.com/JFronny/CC-Functions</PackageProjectUrl>
<RepositoryUrl>https://github.com/JFronny/CC-Functions.git</RepositoryUrl>
<RepositoryType>git</RepositoryType>
<AssemblyVersion>1.1.*</AssemblyVersion>
<FileVersion>1.0.0.0</FileVersion>

View File

@ -1,5 +0,0 @@
{
"extends": [
"config:base"
]
}