Implement GitLab Pages
1. convert README.markdown -> README.org
2. reuse README.org in org-mode based GitLab pages implementation
This way, we use org-mode to maintain README which GitLab-CI turns into
a homepage on GitLab Pages. It doesn't require a separate git branch and
makes it effortless to keep README and landing page in sync. We don't
check in any generated/exported files, it's all done by GitLab-CI during
publishing.
diff --git a/.gitignore b/.gitignore
index 51d899c..618079d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -12,3 +12,7 @@
/rebar.lock
/rebar3.crashdump
/util/rebar3
+/pages/out
+/public
+/pages/.org-mode
+/pages/org-latest.tar.gz
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 3bb75a8..7a183d1 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -1,4 +1,4 @@
-# Copyright (c) 2016-2017 Tuncer Ayaz
+# Copyright (c) 2016-2018 Tuncer Ayaz
#
# Permission to use, copy, modify, and/or distribute this software for any
# purpose with or without fee is hereby granted, provided that the above
@@ -14,15 +14,34 @@
variables:
GIT_DEPTH: "3"
+ DEFAULT_IMAGE: erlang:20-alpine
+
+pages:
+ stage: deploy
+ image: $DEFAULT_IMAGE
+ before_script:
+ - apk add --update make emacs texinfo ca-certificates curl
+ - update-ca-certificates
+ - cd pages
+ - ./install
+ - cd ..
+ script:
+ - make pages
+ - mv pages/out public
+ artifacts:
+ paths:
+ - public
+ only:
+ - master
cache:
key: $CI_PROJECT_PATH
paths:
- - .default/rebar3_*_plt
+ - _build/default/rebar3_*_plt
.build_job_template: &build_job_definition
stage: build
- image: erlang:20-alpine
+ image: $DEFAULT_IMAGE
before_script:
- apk add --update make
script:
@@ -71,12 +90,12 @@
<<: *test_job_definition
before_script:
- apk add --update make
- image: erlang:20-alpine
+ image: $DEFAULT_IMAGE
test:dialyze:
stage: test
- image: erlang:20-alpine
+ image: $DEFAULT_IMAGE
before_script:
- apk add --update make
script:
- - make ci-dialyze
\ No newline at end of file
+ - make ci-dialyze
diff --git a/Makefile b/Makefile
index ff6931d..e33e87b 100644
--- a/Makefile
+++ b/Makefile
@@ -14,7 +14,7 @@
## limitations under the License.
##==============================================================================
-.PHONY: clean doc test dialyze check eunit ci ci-dialyze
+.PHONY: clean edoc test dialyze check eunit ci ci-dialyze pages
REBAR=`sh -c "PATH='$(PATH)':util which rebar3||util/getrebar||echo false"`
@@ -27,7 +27,13 @@
ci-dialyze: clean dialyze
-doc:
+pages: edoc
+ @test -d pages/out/edoc && rm pages/out/edoc/* || mkdir -p pages/out/edoc
+ @cp doc/*.html doc/*.css doc/*.png pages/out/edoc
+ @(cd pages && ./export)
+ @rm -f pages/out/*.html~
+
+edoc:
@$(REBAR) edoc
clean:
diff --git a/README.markdown b/README.markdown
deleted file mode 100644
index b9646dd..0000000
--- a/README.markdown
+++ /dev/null
@@ -1,152 +0,0 @@
-# Welcome to Triq -- Trifork QuickCheck for Erlang
-
-[![Travis-CI Build Status](https://travis-ci.org/triqng/triq.svg?branch=master)](https://travis-ci.org/triqng/triq)
-[![GitLab-CI Build Status](https://gitlab.com/triqng/triq/badges/master/pipeline.svg)](https://gitlab.com/triqng/triq/pipelines)
-
-This is a fork of Triq that is being run under the ZeroMQ Collaberation rules, http://rfc.zeromq.org/spec:22 with the one exception being that it is under the apache licence
-
-
-
-Triq (pronounced "Trick Check") is a free alternative to [QuviQ
-eqc](http://www.quviq.com/). Triq's API is modelled closely after
-`eqc`, so I recommend their tutorials and slides for an introduction
-to QuickCheck. Notice that QuviQ `eqc` has many features not found in
-`triq`, but it is open source licensed under the Apache license. For
-instance, `eqc` has features for reporting, management, probably a
-much better shrinking mechanism, cool C integration, and
-professional support.
-
-## Using Triq
-
-### Installation via package manager
-
-To use `triq`, you can add it as a project dependency and let your
-package manager of choice handle it:
-
-rebar.config: `{triq, "1.*"}`
-
-erlang.mk: `DEPS = triq`
-
-mix.exs: `{:triq, "~> 1.*"}`
-
-### Installation from source into `$ERL_LIBS`
-
-If you want to make `triq` available globally, you can install it from source
-into your Erlang installation by adding it in one of your `$ERL_LIBS` paths.
-So, it's either somewhere like `/usr/local/lib/lib/erlang/lib` or `$HOME/.erl`.
-
-You can either download a tagged release from
-`https://github.com/triqng/triq/releases` and extract that or clone the git
-repo `https://github.com/triqng/triq` in the target directory. Once that's
-done, cd into the directory and run `./rebar compile` or just `make`.
-
-Now, if you start `erl`, you should be able to call functions from the
-`triq` module.
-
-```
-$ erl
-1> code:which(triq).
-"/usr/local/lib/erlang/lib/triq/ebin/triq.beam"
-2>
-```
-
-### Writing properties with Triq
-
-To write properties with `triq`, include the header file:
-
-```
--include_lib("triq/include/triq.hrl").
-```
-
-And you're ready to write property tests. An example property could be:
-
-```
-prop_append() ->
- ?FORALL({Xs,Ys},{list(int()),list(int())},
- lists:reverse(Xs++Ys)
- ==
- lists:reverse(Ys) ++ lists:reverse(Xs)).
-```
-
-To test this property, run `triq:check/1`, thus:
-
-```
-1> triq:check(prop_append()).
-......................................................................
-..............................
-Ran 100 tests
-true
-2>
-```
-
-If the test fails, it will try to shrink the result; here is an example:
-
-```
-prop_delete() ->
- ?FORALL(L,list(int()),
- ?IMPLIES(L /= [],
- ?FORALL(I,elements(L),
- ?WHENFAIL(io:format("L=~p, I=~p~n", [L,I]),
- not lists:member(I,lists:delete(I,L)))))).
-```
-
-Which runs like this:
-```
-1> triq:check(triq_tests:prop_delete()).
-x....Failed!
-L=[4,5,5], I=5
-
-Failed after 5 tests with false
-Simplified:
- L = [0,0]
- I = 0
-false
-2>
-```
-
-You can get the values used for the failing test with `counterexample`,
-and reuse the same test values with `check/2`:
-```
-3> A = triq:counterexample(triq_tests:xprop_delete()).
-x.xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxFailed!
-L=[3,2,1,1,1], I=1
-
-Failed after 101 tests with false
-Simplified:
- L = [0,0]
- I = 0
-[[0,0],0]
-4> A.
-[[0,0],0]
-5> triq:check(triq_tests:xprop_delete(), A).
-Failed!
-L=[0,0], I=0
-
-Failed after 1 tests with false
-Simplified:
- L = [0,0]
- I = 0
-false
-6>
-```
-
-Modules compiled with the `triq.hrl` header, auto-export all functions named
-`prop_*`, and have a function added called `check/0` which runs `triq:check/1`
-on all the properties in the module.
-
-```
-1> mymodule:check().
-```
-
-You can also instruct `triq` to generate EUnit integration functions which allow
-the module to be treated like an ordinary EUnit tests module. This avoids the need
-for `triq` or generic `qc` support in your build/test tool of choice.
-To achieve that, just make sure to include the attribute `-triq(eunit).` in the module.
-So, the initial `triq.hrl` include would turn into this:
-
-```
--include_lib("triq/include/triq.hrl").
--triq(eunit).
-```
-
-Good luck!
diff --git a/README.org b/README.org
new file mode 100644
index 0000000..9663558
--- /dev/null
+++ b/README.org
@@ -0,0 +1,171 @@
+#+OPTIONS: ^:nil
+#+TITLE: Triq
+
+* [[http://gitlab.com/triqng/triq][Triq]] is The Free QuickCheck for Erlang
+
+** Introduction
+ :PROPERTIES:
+ :CUSTOM_ID: introduction
+ :END:
+
+By and large, the Triq API is modeled closely after QuviQ =eqc=, except you
+want to replace any occurrence of =eqc= with =triq=. The main supporting module
+is called =triq_dom=, corresponding to eqc's =eqc_gen=.
+
+#+BEGIN_EXPORT html
+<a href="https://gitlab.com/triqng/triq/pipelines"><img src="https://gitlab.com/triqng/triq/badges/master/pipeline.svg"></a>
+#+END_EXPORT
+
+This is a fork of Triq that is being run under the ZeroMQ Collaberation
+rules, https://rfc.zeromq.org/spec:22 with the one exception being that
+it is under the Apache licence.
+
+** Obtaining Triq
+ :PROPERTIES:
+ :CUSTOM_ID: using-triq
+ :END:
+
+*** Installation via package manager
+ :PROPERTIES:
+ :CUSTOM_ID: installation-via-package-manager
+ :END:
+
+To use =triq=, you can add it as a project dependency and let your
+package manager of choice handle it:
+
+rebar.config: ={triq, "1.*"}=
+
+erlang.mk: =DEPS = triq=
+
+mix.exs: ={:triq, "~> 1.*"}=
+
+*** Installation from source into =$ERL_LIBS=
+ :PROPERTIES:
+ :CUSTOM_ID: installation-from-source-into-erl_libs
+ :END:
+
+If you want to make =triq= available globally, you can install it from
+source into your Erlang installation by adding it in one of your
+=$ERL_LIBS= paths. So, it's either somewhere like
+=/usr/lib/erlang/lib= or =$HOME/.erl=.
+
+You can either download a tagged release from
+=https://gitlab.com/triqng/triq/tags= and extract that or clone the
+git repo =https://gitlab.com/triqng/triq= in the target directory. Once
+that's done, cd into the directory and run =make=.
+
+Now, if you start =erl=, you should be able to call functions from the
+=triq= module.
+
+#+BEGIN_EXAMPLE
+ $ erl
+ 1> code:which(triq).
+ "/usr/local/lib/erlang/lib/triq/ebin/triq.beam"
+ 2>
+#+END_EXAMPLE
+
+** Writing QuickCheck properties with Triq
+ :PROPERTIES:
+ :CUSTOM_ID: writing-properties-with-triq
+ :END:
+
+To write properties with =triq=, include the header file:
+
+#+BEGIN_EXAMPLE erlang
+ -include_lib("triq/include/triq.hrl").
+#+END_EXAMPLE
+
+And you're ready to write property tests. An example property could be:
+
+#+BEGIN_EXAMPLE erlang
+ prop_append() ->
+ ?FORALL({Xs,Ys},{list(int()),list(int())},
+ lists:reverse(Xs++Ys)
+ ==
+ lists:reverse(Ys) ++ lists:reverse(Xs)).
+#+END_EXAMPLE
+
+To test this property, run =triq:check/1=, thus:
+
+#+BEGIN_EXAMPLE
+ 1> triq:check(prop_append()).
+ ......................................................................
+ ..............................
+ Ran 100 tests
+ true
+ 2>
+#+END_EXAMPLE
+
+If the test fails, it will try to shrink the result; here is an example:
+
+#+BEGIN_EXAMPLE erlang
+ prop_delete() ->
+ ?FORALL(L,list(int()),
+ ?IMPLIES(L /= [],
+ ?FORALL(I,elements(L),
+ ?WHENFAIL(io:format("L=~p, I=~p~n", [L,I]),
+ not lists:member(I,lists:delete(I,L)))))).
+#+END_EXAMPLE
+
+Which runs like this:
+
+#+BEGIN_EXAMPLE
+ 1> triq:check(triq_tests:prop_delete()).
+ x....Failed!
+ L=[4,5,5], I=5
+
+ Failed after 5 tests with false
+ Simplified:
+ L = [0,0]
+ I = 0
+ false
+ 2>
+#+END_EXAMPLE
+
+You can get the values used for the failing test with =counterexample=,
+and reuse the same test values with =check/2=:
+
+#+BEGIN_EXAMPLE
+ 3> A = triq:counterexample(triq_tests:xprop_delete()).
+ x.xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxFailed!
+ L=[3,2,1,1,1], I=1
+
+ Failed after 101 tests with false
+ Simplified:
+ L = [0,0]
+ I = 0
+ [[0,0],0]
+ 4> A.
+ [[0,0],0]
+ 5> triq:check(triq_tests:xprop_delete(), A).
+ Failed!
+ L=[0,0], I=0
+
+ Failed after 1 tests with false
+ Simplified:
+ L = [0,0]
+ I = 0
+ false
+ 6>
+#+END_EXAMPLE
+
+Modules compiled with the =triq.hrl= header, auto-export all functions
+named =prop_*=, and have a function added called =check/0= which runs
+=triq:check/1= on all the properties in the module.
+
+#+BEGIN_EXAMPLE
+ 1> mymodule:check().
+#+END_EXAMPLE
+
+You can also instruct =triq= to generate EUnit tests for each property
+which allow the module to be treated like an ordinary EUnit test
+suite. This is highly recommended and avoids the need for =triq= or
+generic =qc= support in your build/test tool of choice. To achieve
+that, just make sure to include the attribute =-triq(eunit).= at the
+top of the module. Thus, the initial =triq.hrl= include would turn
+into this:
+
+#+BEGIN_EXAMPLE erlang
+ -include_lib("triq/include/triq.hrl").
+ -triq(eunit).
+#+END_EXAMPLE
diff --git a/pages/export b/pages/export
new file mode 100755
index 0000000..9e70ffa
--- /dev/null
+++ b/pages/export
@@ -0,0 +1,8 @@
+#!/bin/sh
+set -u
+emacs --batch \
+ --no-init-file \
+ -L .org-mode/lisp \
+ -L .org-mode/contrib/lisp \
+ --load export.el \
+ --funcall org-publish-all
diff --git a/pages/export.el b/pages/export.el
new file mode 100644
index 0000000..1d19df5
--- /dev/null
+++ b/pages/export.el
@@ -0,0 +1,71 @@
+;; Copyright (c) 2017-2018 Tuncer Ayaz
+;;
+;; Permission to use, copy, modify, and/or distribute this software for any
+;; purpose with or without fee is hereby granted, provided that the above
+;; copyright notice and this permission notice appear in all copies.
+;;
+;; THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+;; WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+;; MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+;; ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+;; WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+;; ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+;; OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+(require 'org)
+(require 'ox)
+(require 'ox-publish)
+;; Override user settings, just in case it's used somewhere.
+;; Email address is intentionally invalid.
+(setq user-full-name "triqng")
+(setq user-mail-address "triqnq@triqnq.triqnq")
+
+;; We let org-mode include its default CSS, but have to
+;; make minor ergonomic adjustments.
+(setf custom-html-head-extra
+ (concat
+ "<style type=\"text/css\">\n"
+ "html {font-family: serif;}\n"
+ "body {margin: auto; max-width: 45em; background: #9FA590;}\n"
+ "pre {border: 1px solid #555555; box-shadow: none;}\n"
+ "</style>"))
+
+;; Define org site (org files to export and web resources to copy)
+(setq org-publish-project-alist
+ `(("orgs"
+ :base-directory "src"
+ :base-extension "org"
+ ;; Enable sitemap if needed
+ ;;:auto-sitemap t
+ ;;:sitemap-filename "index.org"
+ ;;:sitemap-title "Triq"
+ :recursive t
+ :publishing-directory "out"
+ :publishing-function org-html-publish-to-html
+ :with-author nil
+ :with-email nil
+ :with-toc nil
+ :auto-preamble nil
+ :section-numbers nil
+ :use-sub-superscripts nil
+ :html-validation-link nil
+ :html-inline-images t
+ ;;:html-head-include-default-style nil
+ :html-head-include-scripts nil
+ ;;:html-htmlize-output-type 'css
+ ;;:html-head ,custom-html-head
+ :html-head-extra ,custom-html-head-extra
+ :html-link-home "index.html"
+ :html-link-up ""
+ :html-home/up-format ""
+ :html-postamble nil)
+ ;; We don't have external resources right now, but if we do,
+ ;; it can be used by enabling the res component. Unused for now.
+ ;;("res"
+ ;; :base-directory "res"
+ ;; :base-extension "css\\|png"
+ ;; :publishing-directory "out"
+ ;; :recursive t
+ ;; :publishing-function org-publish-attachment)
+ ;;("pages" :components ("orgs" "res"))))
+ ("pages" :components ("orgs"))))
diff --git a/pages/install b/pages/install
new file mode 100755
index 0000000..7eb1406
--- /dev/null
+++ b/pages/install
@@ -0,0 +1,12 @@
+#!/bin/sh
+set -eu
+
+if [ ! -d ".org-mode" ]; then
+ curl -o org-latest.tar.gz https://orgmode.org/org-latest.tar.gz
+ tar xf org-latest.tar.gz
+ mv org-mode .org-mode
+fi
+
+if [ ! -e ".org-mode/lisp/org.elc" ]; then
+ (cd .org-mode && make)
+fi
diff --git a/pages/src/index.org b/pages/src/index.org
new file mode 100644
index 0000000..f5e40b9
--- /dev/null
+++ b/pages/src/index.org
@@ -0,0 +1,9 @@
+#+INCLUDE: "../../README.org" :minlevel 1
+
+** API Documentation
+ :PROPERTIES:
+ :CUSTOM_ID: edoc
+ :END:
+
+Generated edoc is available [[file:edoc/index.html][here]]. The interesting modules are [[file:edoc/triq.html][triq]] and
+[[file:edoc/triq_dom.html][triq_dom]].