Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/main' into webview-preview
Browse files Browse the repository at this point in the history
* origin/main: (55 commits)
  Put package job into own workflow and run workflows only when needed (#88)
  Add download count
  Tell the world
  Update readme, bump version
  Ok - let's try again! (#87)
  Fix typo in new-project (#85)
  Clean up example projects (#84)
  Fix bug where new project creates output called "model" (#83)
  Update README.md
  Fix possible null-reference when calculating code-completion (#81)
  Add logo and app icon (#80)
  Implement dialog for building command line invocations  (#78)
  Tweak documentation to reflect Martin's Cake goodness (#77)
  Improve intellisense for awkward user input (#75)
  Tweak help memu, add chat-link (#76)
  Nuget update.... with multi-line pipes
  Add Gitter badge (#74)
  Update README.md
  Add code coverage collection and publish to coveralls.io (#73)
  Clean build warnings
  ...
  • Loading branch information
NeilMacMullen committed Feb 16, 2021
2 parents e235799 + 1240ac0 commit c66a799
Show file tree
Hide file tree
Showing 79 changed files with 3,288 additions and 681 deletions.
25 changes: 25 additions & 0 deletions .github/workflows/cd.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
name: CD

on:
push:
paths-ignore:
- "docs/**"
- "*.md"

jobs:
package:
env:
DisableGitVersionTask: true
runs-on: windows-latest
steps:
- uses: actions/checkout@v2
- name: Setup .NET
uses: actions/setup-dotnet@v1
with:
dotnet-version: 5.0.x
- name: Package
run: dotnet run --project build/Build.csproj -- --target Package
- uses: actions/upload-artifact@v2
with:
name: Textrude.zip
path: publish/Textrude.zip
34 changes: 26 additions & 8 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,14 @@
name: CI

on: [push, pull_request]
on:
push:
paths-ignore:
- "docs/**"
- "*.md"
pull_request:
paths-ignore:
- "docs/**"
- "*.md"

jobs:
test:
Expand All @@ -20,11 +28,21 @@ jobs:
uses: actions/setup-dotnet@v1
with:
dotnet-version: 5.0.x
- name: Clean
run: dotnet clean -p:Configuration=${{ matrix.build_config }} && dotnet nuget locals all --clear
- name: Restore dependencies
run: dotnet restore -p:Configuration=${{ matrix.build_config }}
- name: Build
run: dotnet build -p:Configuration=${{ matrix.build_config }} --no-restore
- name: Test
run: dotnet test -p:Configuration=${{ matrix.build_config }} --no-build
run: dotnet run --project build/Build.csproj -- --target Test --configuration ${{ matrix.build_config }} --clean
- name: Coveralls
uses: coverallsapp/github-action@master
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
flag-name: run-on-${{ matrix.os }}
path-to-lcov: TestResults/lcov.info
parallel: true
coveralls-finish:
needs: test
runs-on: ubuntu-latest
steps:
- name: Coveralls Finished
uses: coverallsapp/github-action@master
with:
github-token: ${{ secrets.github_token }}
parallel-finished: true
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
/act
/tools
/TestReports

## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
Expand Down
22 changes: 21 additions & 1 deletion Engine/Application/ModelPath.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,14 @@ namespace Engine.Application
/// </remarks>
public class ModelPath
{
public enum PathType
{
Method,
Property,
Unknown,
Keyword
}

public const string Separator = ".";

/// <summary>
Expand All @@ -37,6 +45,8 @@ public class ModelPath
/// </summary>
public int Length => _tokens.Length;

public PathType ModelType { get; private set; } = PathType.Unknown;

public static ModelPath FromTokens(IEnumerable<string> tokens)
{
var tokenArray = tokens.ToImmutableArray();
Expand All @@ -50,12 +60,22 @@ public static ModelPath FromTokens(IEnumerable<string> tokens)
/// </summary>
public ModelPath WithChild(string child) => FromTokens(_tokens.Append(child));

public ModelPath WithType(PathType type)
{
var m = FromTokens(_tokens);
m.ModelType = type;
return m;
}


/// <summary>
/// Returns a "dotted" string representation
/// </summary>
public string Render() => string.Join(Separator, _tokens);

public static ModelPath FromString(string path) =>
FromTokens((path.Split(Separator)));

public string Terminal() => IsEmpty ? string.Empty : _tokens.Last();
}
}
}
32 changes: 28 additions & 4 deletions Engine/Application/TemplateManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,15 @@ public static ImmutableArray<ModelPath> PathsForObjectTree(IDictionary<string, o

foreach (var keyValuePair in container)
{
var p = prefix.WithChild(keyValuePair.Key);
//we need to be careful here - there is nothing to stop the user
//deliberately or accidentally injecting null values into the model
var type = keyValuePair.Value?.GetType()?.FullName ?? string.Empty;
var mType = ModelPath.PathType.Property;
if (type.Contains("Scriban") && type.Contains("Function"))
mType = ModelPath.PathType.Method;


var p = prefix.WithChild(keyValuePair.Key).WithType(mType);
if (keyValuePair.Value is IDictionary<string, object> child)
ret.AddRange(PathsForObjectTree(child, p));
else ret.Add(p);
Expand All @@ -148,7 +156,23 @@ public static ImmutableArray<ModelPath> PathsForObjectTree(IDictionary<string, o
public ImmutableArray<ModelPath> GetBuiltIns() => PathsForObjectTree(_context.BuiltinObject, ModelPath.Empty);
public ImmutableArray<ModelPath> GetObjectTree() => PathsForObjectTree(_top, ModelPath.Empty);

public ImmutableArray<ModelPath> ModelPaths() => GetBuiltIns().Concat(GetObjectTree())
.ToImmutableArray();
public ImmutableArray<ModelPath> GetKeywords()
{
var keywords =
@"func end if else for break continue
in while capture readonly import
with wrap include ret case when this
empty tablerow";
return keywords.Split(" \r\n".ToCharArray(),
StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries)
.Select(s => ModelPath.FromString(s).WithType(ModelPath.PathType.Keyword))
.ToImmutableArray();
}

public ImmutableArray<ModelPath> ModelPaths() =>
GetBuiltIns()
.Concat(GetObjectTree())
.Concat(GetKeywords())
.ToImmutableArray();
}
}
}
4 changes: 2 additions & 2 deletions Engine/Engine.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Include="CsvHelper" Version="22.1.2" />
<PackageReference Include="CsvHelper" Version="23.0.0" />
<PackageReference Include="Humanizer" Version="2.8.26" />
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
<PackageReference Include="Scriban" Version="3.4.2" />
<PackageReference Include="Scriban" Version="3.5.0" />
<PackageReference Include="System.Collections.Immutable" Version="5.0.0" />
<PackageReference Include="YamlDotNet" Version="9.1.4" />
</ItemGroup>
Expand Down
44 changes: 18 additions & 26 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
# Textrude
# ![Textude](img/textrude_logo.png)
![GitHub release (latest by SemVer including pre-releases)](https://img.shields.io/github/downloads-pre/NeilMacmullen/Textrude/total)
[![Coverage Status](https://coveralls.io/repos/github/NeilMacMullen/Textrude/badge.svg?branch=main&kill_cache=1)](https://coveralls.io/github/NeilMacMullen/Textrude?branch=main) [![Join the chat at https://gitter.im/Textrude/community](https://badges.gitter.im/Textrude/community.svg)](https://gitter.im/Textrude/community?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)

## Give a Star! :star:

Expand Down Expand Up @@ -26,7 +28,7 @@ Let's face it, there are any number of code-generation technologies you might co

## Download/build

The current release is **v1.3.0**.
The current release is **v1.4.0**.

**Textrude requires [.Net 5.0](https://dotnet.microsoft.com/download/dotnet/5.0). If it's not already on your machine you will be prompted to install it.**

Expand All @@ -40,29 +42,20 @@ The current release is **v1.3.0**.

## What's new

### vNext (source only)
- Update to Monaco 22.3 which supports an extra couple of languages
- Rewire font-size control, line numbers, wordwarp to model/output panes
- remove minimap from model/output panes
- added spinner to monaco panes and made white flash a bit briefer
- whitespace can be made visible in input/output panes
- reuse single Monaco edit pane for multiple models/outputs for cleaner switching & lower resource use
- definitions and includes are now move to main input section and used Monaco editor
- the template is now edited using Monaco and (rudimentary) syntax hightlight is applied
- models and outputs can now be renamed in TextrudeInteractive
- Textrude CLI now supports named models/outputs via "mymodel=d:/model.csv" syntax

### v1.3.0 (source/binary)
- Models and outputs can be added/removed on a per-project basis
- Syntax highlighting for output panes
- Input/ouput panes can be "linked" to files and load/save are supported
- fontsize, wordwrap and line-number settings are now persisted
- warning dialog is now shown if the current project has unsaved changes
- default rendering throttle reduced to 50ms for better responsiveness
- Taskbar icon now shows jumplist, TextrudeInteractive can be started with name of project as parameter
- TextrudeInteractive now opens last used project when reopened
- TextrudeInteractive now uses the Monaco editor (from VS Code) hugely improving the syntax highlighting abilities. Massive thanks to [Martin Hochstrasser](https://github.com/highstreeto) for this!
- upgrade to latest Scriban which supports [captured variables in anonymous functions](https://github.com/scriban/scriban/issues/322)
### v1.4.0 (source/binary)
- The Monaco text editor is now used for all edit panes including the template editor, definitions and include paths.
- A single Monaco edit pane is now used for multiple models/outputs for cleaner switching & improved responsiveness
- The view menu allows visible-whitespace to be toggled on and off
- Rudimentary syntax highlighting and intellisense are provided for the template editor
- Models and outputs can now be assigned names
- Help menu now includes a link to gitter-chat
- Model, template and output panes now support linking to files.
- Export/Build... menu now brings up a dialog to help build CLI options.
- Updated to latest Scriban for [multi-line pipes](https://github.com/scriban/scriban/pull/327)
- Special thanks to [Martin Hochstrasser](https://github.com/highstreeto) for
- CAKE build support
- The fancy new logo!


[Full change history](doc/changeHistory.md)

Expand All @@ -86,7 +79,6 @@ Textrude makes heavy use of the following components:
- [Json.Net](https://www.newtonsoft.com/json) for Json deserialisation
- [Humanizr](https://github.com/Humanizr/Humanizer) for useful text-processing
- [MaterialDesignToolkit](https://github.com/MaterialDesignInXAML/MaterialDesignInXamlToolkit), [MaterialDesignExtensions](https://spiegelp.github.io/MaterialDesignExtensions) and [Ookii Dialogs](https://github.com/augustoproiete/ookii-dialogs-wpf)to make the UI a bit less clunky
- [AvalonEdit](http://avalonedit.net/) for text-editing goodness

Huge thanks to the contributors:
- [Martin Hochstrasser](https://github.com/highstreeto) - Docker support, general build enhancements and integration of the Monaco editor
Expand Down
90 changes: 41 additions & 49 deletions SharedApplication/CommandLineBuilder.cs
Original file line number Diff line number Diff line change
@@ -1,89 +1,81 @@
using System.Linq;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.Json;
using YamlDotNet.Serialization;

namespace SharedApplication
{
/// <summary>
/// Builds command lines for the CLI version of textrude
/// </summary>
public class CommandLineBuilder
{
private readonly StringBuilder builder = new();
private readonly RenderOptions options;
private readonly StringBuilder _builder = new();
private readonly RenderOptions _options;
private string _exe = string.Empty;

public CommandLineBuilder(RenderOptions theoptions) => options = theoptions;
public CommandLineBuilder(RenderOptions op) => _options = op;

public CommandLineBuilder WithExe(string exe)
{
_exe = exe;
return this;
}

private void AppendFlag(string flag) => builder.Append($" --{flag.ToLowerInvariant()}");
private void AppendItem(string item) => builder.Append($" \"{item}\"");
private void AppendFileName(string file) => AppendItem(file);
private string QuoteItem(string item)
=> item.Contains(" ") ? $"\"{item}\"" : item;

public string BuildRenderInvocation()
{
StartInvocation("render");
if (options.Lazy)
AppendFlag(nameof(RenderOptions.Lazy));
private void AppendFlag(string flag) => _builder.Append($" --{flag.ToLowerInvariant()}");
private void AppendItem(string item) => _builder.Append($" {QuoteItem(item)}");

if (options.Models.Any())
private void AppendIfPresent(string option, IEnumerable<string> items)
{
var clean = items.Clean();
if (clean.Any())
{
AppendFlag(nameof(RenderOptions.Models));
foreach (var model in options.Models)
AppendFlag(option);
foreach (var i in clean)
{
AppendFileName(model);
AppendItem(i);
}
}
}

AppendFlag(nameof(options.Template));
AppendFileName("template.sbn");


if (options.Definitions.Any())
{
AppendFlag(nameof(RenderOptions.Definitions));
foreach (var d in options.Definitions)
AppendItem(d);
}

if (options.Include.Any())
{
AppendFlag(nameof(RenderOptions.Include));
foreach (var inc in options.Include)
AppendFileName(inc);
}
public string BuildRenderInvocation()
{
StartInvocation("render");
if (_options.Lazy)
AppendFlag(nameof(RenderOptions.Lazy));

AppendIfPresent(nameof(RenderOptions.Models), _options.Models);

if (options.Output.Any())
{
AppendFlag(nameof(RenderOptions.Output));
foreach (var outfile in options.Output)
AppendFileName(outfile);
}
AppendFlag(nameof(_options.Template));
AppendItem(_options.Template);

return builder.ToString();
AppendIfPresent(nameof(RenderOptions.Definitions), _options.Definitions);
AppendIfPresent(nameof(RenderOptions.Include), _options.Include);
AppendIfPresent(nameof(RenderOptions.Output), _options.Output);
return _builder.ToString();
}

private void StartInvocation(string cmd)
{
builder.Clear();
_builder.Clear();
if (_exe.Length != 0)
AppendFileName(_exe);
builder.Append($" {cmd}");
AppendItem(_exe);
_builder.Append($" {cmd}");
}

public (string argsContent, string invocation) BuildJson(string argsFile)
{
StartInvocation("renderFromFile ");
AppendFlag(nameof(RenderFromFileOptions.Arguments));
AppendFileName(argsFile);
var invocation = builder.ToString();
AppendItem(argsFile);
var invocation = _builder.ToString();

return (
JsonSerializer.Serialize(options, new JsonSerializerOptions {WriteIndented = true}),
JsonSerializer.Serialize(_options, new JsonSerializerOptions {WriteIndented = true}),
invocation
);
}
Expand All @@ -92,10 +84,10 @@ private void StartInvocation(string cmd)
{
StartInvocation("renderFromFile ");
AppendFlag(nameof(RenderFromFileOptions.Arguments));
AppendFileName(argsFile);
var invocation = builder.ToString();
AppendItem(argsFile);
var invocation = _builder.ToString();

return (new Serializer().Serialize(options),
return (new Serializer().Serialize(_options),
invocation);
}
}
Expand Down
Loading

0 comments on commit c66a799

Please sign in to comment.