diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml new file mode 100644 index 0000000..26307b4 --- /dev/null +++ b/.github/workflows/release.yaml @@ -0,0 +1,24 @@ +name: Release for all platforms +on: + release: + types: [published] +jobs: + build_and_upload: + runs-on: ubuntu-latest + strategy: + matrix: + os: [ubuntu-latest, windows-latest, macos-14] + steps: + - name: Checkout code + uses: actions/checkout@v2 + - name: Build for Release + run: make build + - name: Upload Release + uses: actions/upload-release-asset@v1 + with: + upload_url: ${{ github.event.release.upload_url }} + asset_path: build/almo + asset_name: ${{ matrix.os }} + asset_content_type: application/octet-stream + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} \ No newline at end of file diff --git a/Makefile b/Makefile index 98539e5..c4a7452 100644 --- a/Makefile +++ b/Makefile @@ -4,7 +4,7 @@ setup: bash scripts/setup.sh build: setup - g++ -std=c++23 build/almo.cpp -o build/almo + g++ -std=c++20 build/almo.cpp -o build/almo pybind: setup bash scripts/pybind.sh build/pyalmo.cpp almo.so diff --git a/scripts/setup.sh b/scripts/setup.sh index f074e8f..95f38b5 100755 --- a/scripts/setup.sh +++ b/scripts/setup.sh @@ -7,7 +7,7 @@ set -f src_dir="src" build_dir="build" -data_petterns=("*.css" "*.html" "*.js") +data_petterns=("*.css" "*.html" "*.js" "*.txt") verbose=0 # 指定された内容を指定色で表示する. @@ -49,7 +49,7 @@ for file in $(find $build_dir -type f); do for pettern in ${data_petterns[@]}; do if [[ $file == $build_dir/*$pettern ]]; then vprint " Matched! with $pettern => $file" green - echo "R\"(" > "$file.tmp" + echo -n "R\"(" > "$file.tmp" cat "$file" >> "$file.tmp" echo ")\"" >> "$file.tmp" mv "$file.tmp" "$file" @@ -60,6 +60,10 @@ for file in $(find $build_dir -type f); do vprint "$file is not matching any data file" done +# バージョン、コミットハッシュの情報を出力 +echo "R\"($(git describe --tags --abbrev=0))\"" > "$build_dir/version.txt" +echo "R\"($(git show --format='%h' --no-patch))\"" > "$build_dir/commithash.txt" + # 元に戻す if [ $mode == "on" ]; then diff --git a/src/almo.cpp b/src/almo.cpp index 8166cbf..44cb557 100644 --- a/src/almo.cpp +++ b/src/almo.cpp @@ -15,7 +15,6 @@ class Config { std::string syntax_theme = "__default__"; bool plot_graph = false; std::string out_path = "__stdout__"; - void parse_arguments(int argc, char* argv[]) { if (argc < 2) { std::cerr << "コマンドライン引数が不足しています。" << std::endl; @@ -28,6 +27,11 @@ class Config { exit(0); } + if (argc == 2 && std::string(argv[1]) == "-v") { + std::cout << "almo " << almo::VERSION << " (" << almo::COMMITHASH << ")" << std::endl; + exit(0); + } + for (int i = 2; i < argc; i++) { if (argv[i][0] == '-') { if (std::string(argv[i]).length() > 2) { diff --git a/src/render.hpp b/src/render.hpp index b066cb1..009f2a1 100644 --- a/src/render.hpp +++ b/src/render.hpp @@ -13,21 +13,6 @@ #include "utils.hpp" namespace almo { -std::string LIGHT_THEME = { -#include "light.css" -}; -std::string DARK_THEME = { -#include "dark.css" -}; - -std::string RUNNER = { -#include "runner.js" -}; - -std::string TEMPLATE = { -#include "template.html" -}; - std::string load_html_template(std::string html_path, std::string css_setting, bool required_pyodide) { const std::string pyodide_loader = diff --git a/src/utils.hpp b/src/utils.hpp index 9cdf203..b8418fd 100644 --- a/src/utils.hpp +++ b/src/utils.hpp @@ -1,14 +1,44 @@ #pragma once -#include -#include #include -#include -#include -#include -#include + #include +#include #include +#include +#include +#include +#include +#include + +// コンパイル時に埋め込む定数 +namespace almo { +std::string LIGHT_THEME = { +#include "light.css" +}; + +std::string DARK_THEME = { +#include "dark.css" +}; + +std::string RUNNER = { +#include "runner.js" +}; + +std::string TEMPLATE = { +#include "template.html" +}; + +std::string VERSION = { +#include "version.txt" +}; + +std::string COMMITHASH = { +#include "commithash.txt" +}; + + +} // namespace almo // 文字列の vector を 結合する。第二引数はOptionalで区切り文字。デフォルトは空 std::string join(std::vector v, std::string sep = "") { @@ -22,7 +52,6 @@ std::string join(std::vector v, std::string sep = "") { return ss.str(); } - // 文字列を sep で分割する std::vector split(std::string str, std::string sep) { std::vector result; @@ -37,11 +66,11 @@ std::vector split(std::string str, std::string sep) { return result; } - // パースが失敗した時のエラー class ParseError : public std::exception { std::string message; -public: + + public: ParseError(std::string message) : message(message) {} const char* what() const noexcept override { std::string error = "パースエラー \n" + message; @@ -51,11 +80,11 @@ class ParseError : public std::exception { } }; - // 構文が間違っている時のエラー class SyntaxError : public std::exception { std::string message; -public: + + public: SyntaxError(std::string message) : message(message) {} const char* what() const noexcept override { std::string error = "構文エラー \n" + message; @@ -68,7 +97,8 @@ class SyntaxError : public std::exception { // ファイルが存在しない時のエラー class NotFoundFileError : public std::exception { std::string message; -public: + + public: NotFoundFileError(std::string message) : message(message) {} const char* what() const noexcept override { std::string error = "ファイルが存在しません \n" + message; @@ -81,7 +111,8 @@ class NotFoundFileError : public std::exception { // コマンドライン引数が間違っている時のエラー class InvalidCommandLineArgumentsError : public std::exception { std::string message; -public: + + public: InvalidCommandLineArgumentsError(std::string message) : message(message) {} const char* what() const noexcept override { std::string error = "不正なコマンドライン引数 \n" + message; @@ -91,7 +122,6 @@ class InvalidCommandLineArgumentsError : public std::exception { } }; - std::vector glob(const std::string& pattern) { std::vector result; glob_t globResult; @@ -106,7 +136,6 @@ std::vector glob(const std::string& pattern) { return result; } - // ファイルを読んで、各行をvectorに入れて返す // ファイルが存在しない場合はNotFoundFileErrorを投げる std::vector read_file(std::string path) { @@ -122,12 +151,10 @@ std::vector read_file(std::string path) { return result; } - // 文字列を受け取り、コメントに囲まれた部分を削除して返す std::string _remove_comment(std::string s) { std::vector lines = split(s, "\n"); - std::regex comment_start = std::regex("(.*)(.*)"); @@ -142,13 +169,11 @@ std::string _remove_comment(std::string s) { ret += std::regex_replace(line, comment_end, "$2"); ret += "\n"; in_comment = false; - } - else { + } else { // --> がない場合 continue; } - } - else { + } else { if (std::regex_match(line, comment_start)) { if (std::regex_match(line, comment_end)) { // が同じ行にある場合 @@ -156,34 +181,30 @@ std::string _remove_comment(std::string s) { ret += std::regex_replace(line, comment_end, "$2"); ret += "\n"; in_comment = false; - } - else { + } else { // がない場合 ret += std::regex_replace(line, comment_start, "$1"); ret += "\n"; in_comment = true; } - } - else { + } else { ret += line; ret += "\n"; } } } - return ret; } - // 文字列を受け取り、ダブルクオーテーションや改行などをエスケープする // https://stackoverflow.com/questions/7724448/simple-json-string-escape-for-c -std::string escape(const std::string &s) { +std::string escape(const std::string& s) { std::ostringstream o; for (auto c = s.cbegin(); c != s.cend(); c++) { if (*c == '"' || *c == '\\' || ('\x00' <= *c && *c <= '\x1f')) { - o << "\\u" - << std::hex << std::setw(4) << std::setfill('0') << static_cast(*c); + o << "\\u" << std::hex << std::setw(4) << std::setfill('0') + << static_cast(*c); } else { o << *c; } @@ -191,10 +212,9 @@ std::string escape(const std::string &s) { return o.str(); } - -// 文字列を受け取り、 HTMLに埋め込んでも大丈夫なようにエスケープする. -// ref: https://github.com/abap34/ALMO/issues/91 -std::string escape_for_html(const std::string &s) { +//  文字列を受け取り、 HTMLに埋め込んでも大丈夫なようにエスケープする. +// ref: https://github.com/abap34/ALMO/issues/91 +std::string escape_for_html(const std::string& s) { std::string ret = s; ret = std::regex_replace(ret, std::regex("&"), "&"); ret = std::regex_replace(ret, std::regex("<"), "<"); @@ -204,25 +224,20 @@ std::string escape_for_html(const std::string &s) { return ret; } - - // 文字列を受け取り、末尾のスペースを削除する std::string rtrim(std::string s) { s.erase(s.find_last_not_of(" \n\r\t") + 1); return s; } - // 文字列を受け取り、先頭にあるスペースを削除する std::string ltrim(std::string s) { s.erase(0, s.find_first_not_of(" \n\r\t")); return s; } - - // 文字列を受け取って、先頭が "- " だったら削除 -std::string remove_listdef(std::string s){ +std::string remove_listdef(std::string s) { if (s.size() >= 2 && s[0] == '-' && s[1] == ' ') { return s.substr(2); }