From e4fd785bb294ebe42dfd29af114afa2ee4713b7b Mon Sep 17 00:00:00 2001 From: Natanael Copa Date: Wed, 13 Jun 2012 14:50:58 +0000 Subject: [PATCH] testing/lua-microlight: cleanup those should never been there in first place --- testing/lua-microlight/Microlight.git/HEAD | 1 - testing/lua-microlight/Microlight.git/config | 6 - .../lua-microlight/Microlight.git/description | 1 - .../hooks/applypatch-msg.sample | 15 - .../Microlight.git/hooks/commit-msg.sample | 24 - .../Microlight.git/hooks/post-update.sample | 8 - .../hooks/pre-applypatch.sample | 14 - .../Microlight.git/hooks/pre-commit.sample | 50 -- .../Microlight.git/hooks/pre-rebase.sample | 169 ------ .../hooks/prepare-commit-msg.sample | 36 -- .../Microlight.git/hooks/update.sample | 128 ----- .../Microlight.git/info/exclude | 6 - ...4eeb410b7f82331a4c067294ec2b9bd38f24ed.idx | Bin 2360 -> 0 bytes ...eeb410b7f82331a4c067294ec2b9bd38f24ed.pack | Bin 24275 -> 0 bytes .../lua-microlight/Microlight.git/packed-refs | 2 - testing/lua-microlight/lua-microlight.tar | 0 testing/lua-microlight/ml.lua | 543 ------------------ 17 files changed, 1003 deletions(-) delete mode 100644 testing/lua-microlight/Microlight.git/HEAD delete mode 100644 testing/lua-microlight/Microlight.git/config delete mode 100644 testing/lua-microlight/Microlight.git/description delete mode 100755 testing/lua-microlight/Microlight.git/hooks/applypatch-msg.sample delete mode 100755 testing/lua-microlight/Microlight.git/hooks/commit-msg.sample delete mode 100755 testing/lua-microlight/Microlight.git/hooks/post-update.sample delete mode 100755 testing/lua-microlight/Microlight.git/hooks/pre-applypatch.sample delete mode 100755 testing/lua-microlight/Microlight.git/hooks/pre-commit.sample delete mode 100755 testing/lua-microlight/Microlight.git/hooks/pre-rebase.sample delete mode 100755 testing/lua-microlight/Microlight.git/hooks/prepare-commit-msg.sample delete mode 100755 testing/lua-microlight/Microlight.git/hooks/update.sample delete mode 100644 testing/lua-microlight/Microlight.git/info/exclude delete mode 100644 testing/lua-microlight/Microlight.git/objects/pack/pack-b24eeb410b7f82331a4c067294ec2b9bd38f24ed.idx delete mode 100644 testing/lua-microlight/Microlight.git/objects/pack/pack-b24eeb410b7f82331a4c067294ec2b9bd38f24ed.pack delete mode 100644 testing/lua-microlight/Microlight.git/packed-refs delete mode 100644 testing/lua-microlight/lua-microlight.tar delete mode 100644 testing/lua-microlight/ml.lua diff --git a/testing/lua-microlight/Microlight.git/HEAD b/testing/lua-microlight/Microlight.git/HEAD deleted file mode 100644 index cb089cd89a7..00000000000 --- a/testing/lua-microlight/Microlight.git/HEAD +++ /dev/null @@ -1 +0,0 @@ -ref: refs/heads/master diff --git a/testing/lua-microlight/Microlight.git/config b/testing/lua-microlight/Microlight.git/config deleted file mode 100644 index 83dff9c588b..00000000000 --- a/testing/lua-microlight/Microlight.git/config +++ /dev/null @@ -1,6 +0,0 @@ -[core] - repositoryformatversion = 0 - filemode = true - bare = true -[remote "origin"] - url = git://github.com/stevedonovan/Microlight.git diff --git a/testing/lua-microlight/Microlight.git/description b/testing/lua-microlight/Microlight.git/description deleted file mode 100644 index 498b267a8c7..00000000000 --- a/testing/lua-microlight/Microlight.git/description +++ /dev/null @@ -1 +0,0 @@ -Unnamed repository; edit this file 'description' to name the repository. diff --git a/testing/lua-microlight/Microlight.git/hooks/applypatch-msg.sample b/testing/lua-microlight/Microlight.git/hooks/applypatch-msg.sample deleted file mode 100755 index 8b2a2fe84fe..00000000000 --- a/testing/lua-microlight/Microlight.git/hooks/applypatch-msg.sample +++ /dev/null @@ -1,15 +0,0 @@ -#!/bin/sh -# -# An example hook script to check the commit log message taken by -# applypatch from an e-mail message. -# -# The hook should exit with non-zero status after issuing an -# appropriate message if it wants to stop the commit. The hook is -# allowed to edit the commit message file. -# -# To enable this hook, rename this file to "applypatch-msg". - -. git-sh-setup -test -x "$GIT_DIR/hooks/commit-msg" && - exec "$GIT_DIR/hooks/commit-msg" ${1+"$@"} -: diff --git a/testing/lua-microlight/Microlight.git/hooks/commit-msg.sample b/testing/lua-microlight/Microlight.git/hooks/commit-msg.sample deleted file mode 100755 index b58d1184a9d..00000000000 --- a/testing/lua-microlight/Microlight.git/hooks/commit-msg.sample +++ /dev/null @@ -1,24 +0,0 @@ -#!/bin/sh -# -# An example hook script to check the commit log message. -# Called by "git commit" with one argument, the name of the file -# that has the commit message. The hook should exit with non-zero -# status after issuing an appropriate message if it wants to stop the -# commit. The hook is allowed to edit the commit message file. -# -# To enable this hook, rename this file to "commit-msg". - -# Uncomment the below to add a Signed-off-by line to the message. -# Doing this in a hook is a bad idea in general, but the prepare-commit-msg -# hook is more suited to it. -# -# SOB=$(git var GIT_AUTHOR_IDENT | sed -n 's/^\(.*>\).*$/Signed-off-by: \1/p') -# grep -qs "^$SOB" "$1" || echo "$SOB" >> "$1" - -# This example catches duplicate Signed-off-by lines. - -test "" = "$(grep '^Signed-off-by: ' "$1" | - sort | uniq -c | sed -e '/^[ ]*1[ ]/d')" || { - echo >&2 Duplicate Signed-off-by lines. - exit 1 -} diff --git a/testing/lua-microlight/Microlight.git/hooks/post-update.sample b/testing/lua-microlight/Microlight.git/hooks/post-update.sample deleted file mode 100755 index ec17ec1939b..00000000000 --- a/testing/lua-microlight/Microlight.git/hooks/post-update.sample +++ /dev/null @@ -1,8 +0,0 @@ -#!/bin/sh -# -# An example hook script to prepare a packed repository for use over -# dumb transports. -# -# To enable this hook, rename this file to "post-update". - -exec git update-server-info diff --git a/testing/lua-microlight/Microlight.git/hooks/pre-applypatch.sample b/testing/lua-microlight/Microlight.git/hooks/pre-applypatch.sample deleted file mode 100755 index b1f187c2e9a..00000000000 --- a/testing/lua-microlight/Microlight.git/hooks/pre-applypatch.sample +++ /dev/null @@ -1,14 +0,0 @@ -#!/bin/sh -# -# An example hook script to verify what is about to be committed -# by applypatch from an e-mail message. -# -# The hook should exit with non-zero status after issuing an -# appropriate message if it wants to stop the commit. -# -# To enable this hook, rename this file to "pre-applypatch". - -. git-sh-setup -test -x "$GIT_DIR/hooks/pre-commit" && - exec "$GIT_DIR/hooks/pre-commit" ${1+"$@"} -: diff --git a/testing/lua-microlight/Microlight.git/hooks/pre-commit.sample b/testing/lua-microlight/Microlight.git/hooks/pre-commit.sample deleted file mode 100755 index 18c48297652..00000000000 --- a/testing/lua-microlight/Microlight.git/hooks/pre-commit.sample +++ /dev/null @@ -1,50 +0,0 @@ -#!/bin/sh -# -# An example hook script to verify what is about to be committed. -# Called by "git commit" with no arguments. The hook should -# exit with non-zero status after issuing an appropriate message if -# it wants to stop the commit. -# -# To enable this hook, rename this file to "pre-commit". - -if git rev-parse --verify HEAD >/dev/null 2>&1 -then - against=HEAD -else - # Initial commit: diff against an empty tree object - against=4b825dc642cb6eb9a060e54bf8d69288fbee4904 -fi - -# If you want to allow non-ascii filenames set this variable to true. -allownonascii=$(git config hooks.allownonascii) - -# Redirect output to stderr. -exec 1>&2 - -# Cross platform projects tend to avoid non-ascii filenames; prevent -# them from being added to the repository. We exploit the fact that the -# printable range starts at the space character and ends with tilde. -if [ "$allownonascii" != "true" ] && - # Note that the use of brackets around a tr range is ok here, (it's - # even required, for portability to Solaris 10's /usr/bin/tr), since - # the square bracket bytes happen to fall in the designated range. - test $(git diff --cached --name-only --diff-filter=A -z $against | - LC_ALL=C tr -d '[ -~]\0' | wc -c) != 0 -then - echo "Error: Attempt to add a non-ascii file name." - echo - echo "This can cause problems if you want to work" - echo "with people on other platforms." - echo - echo "To be portable it is advisable to rename the file ..." - echo - echo "If you know what you are doing you can disable this" - echo "check using:" - echo - echo " git config hooks.allownonascii true" - echo - exit 1 -fi - -# If there are whitespace errors, print the offending file names and fail. -exec git diff-index --check --cached $against -- diff --git a/testing/lua-microlight/Microlight.git/hooks/pre-rebase.sample b/testing/lua-microlight/Microlight.git/hooks/pre-rebase.sample deleted file mode 100755 index 9773ed4cb29..00000000000 --- a/testing/lua-microlight/Microlight.git/hooks/pre-rebase.sample +++ /dev/null @@ -1,169 +0,0 @@ -#!/bin/sh -# -# Copyright (c) 2006, 2008 Junio C Hamano -# -# The "pre-rebase" hook is run just before "git rebase" starts doing -# its job, and can prevent the command from running by exiting with -# non-zero status. -# -# The hook is called with the following parameters: -# -# $1 -- the upstream the series was forked from. -# $2 -- the branch being rebased (or empty when rebasing the current branch). -# -# This sample shows how to prevent topic branches that are already -# merged to 'next' branch from getting rebased, because allowing it -# would result in rebasing already published history. - -publish=next -basebranch="$1" -if test "$#" = 2 -then - topic="refs/heads/$2" -else - topic=`git symbolic-ref HEAD` || - exit 0 ;# we do not interrupt rebasing detached HEAD -fi - -case "$topic" in -refs/heads/??/*) - ;; -*) - exit 0 ;# we do not interrupt others. - ;; -esac - -# Now we are dealing with a topic branch being rebased -# on top of master. Is it OK to rebase it? - -# Does the topic really exist? -git show-ref -q "$topic" || { - echo >&2 "No such branch $topic" - exit 1 -} - -# Is topic fully merged to master? -not_in_master=`git rev-list --pretty=oneline ^master "$topic"` -if test -z "$not_in_master" -then - echo >&2 "$topic is fully merged to master; better remove it." - exit 1 ;# we could allow it, but there is no point. -fi - -# Is topic ever merged to next? If so you should not be rebasing it. -only_next_1=`git rev-list ^master "^$topic" ${publish} | sort` -only_next_2=`git rev-list ^master ${publish} | sort` -if test "$only_next_1" = "$only_next_2" -then - not_in_topic=`git rev-list "^$topic" master` - if test -z "$not_in_topic" - then - echo >&2 "$topic is already up-to-date with master" - exit 1 ;# we could allow it, but there is no point. - else - exit 0 - fi -else - not_in_next=`git rev-list --pretty=oneline ^${publish} "$topic"` - /usr/bin/perl -e ' - my $topic = $ARGV[0]; - my $msg = "* $topic has commits already merged to public branch:\n"; - my (%not_in_next) = map { - /^([0-9a-f]+) /; - ($1 => 1); - } split(/\n/, $ARGV[1]); - for my $elem (map { - /^([0-9a-f]+) (.*)$/; - [$1 => $2]; - } split(/\n/, $ARGV[2])) { - if (!exists $not_in_next{$elem->[0]}) { - if ($msg) { - print STDERR $msg; - undef $msg; - } - print STDERR " $elem->[1]\n"; - } - } - ' "$topic" "$not_in_next" "$not_in_master" - exit 1 -fi - -exit 0 - -################################################################ - -This sample hook safeguards topic branches that have been -published from being rewound. - -The workflow assumed here is: - - * Once a topic branch forks from "master", "master" is never - merged into it again (either directly or indirectly). - - * Once a topic branch is fully cooked and merged into "master", - it is deleted. If you need to build on top of it to correct - earlier mistakes, a new topic branch is created by forking at - the tip of the "master". This is not strictly necessary, but - it makes it easier to keep your history simple. - - * Whenever you need to test or publish your changes to topic - branches, merge them into "next" branch. - -The script, being an example, hardcodes the publish branch name -to be "next", but it is trivial to make it configurable via -$GIT_DIR/config mechanism. - -With this workflow, you would want to know: - -(1) ... if a topic branch has ever been merged to "next". Young - topic branches can have stupid mistakes you would rather - clean up before publishing, and things that have not been - merged into other branches can be easily rebased without - affecting other people. But once it is published, you would - not want to rewind it. - -(2) ... if a topic branch has been fully merged to "master". - Then you can delete it. More importantly, you should not - build on top of it -- other people may already want to - change things related to the topic as patches against your - "master", so if you need further changes, it is better to - fork the topic (perhaps with the same name) afresh from the - tip of "master". - -Let's look at this example: - - o---o---o---o---o---o---o---o---o---o "next" - / / / / - / a---a---b A / / - / / / / - / / c---c---c---c B / - / / / \ / - / / / b---b C \ / - / / / / \ / - ---o---o---o---o---o---o---o---o---o---o---o "master" - - -A, B and C are topic branches. - - * A has one fix since it was merged up to "next". - - * B has finished. It has been fully merged up to "master" and "next", - and is ready to be deleted. - - * C has not merged to "next" at all. - -We would want to allow C to be rebased, refuse A, and encourage -B to be deleted. - -To compute (1): - - git rev-list ^master ^topic next - git rev-list ^master next - - if these match, topic has not merged in next at all. - -To compute (2): - - git rev-list master..topic - - if this is empty, it is fully merged to "master". diff --git a/testing/lua-microlight/Microlight.git/hooks/prepare-commit-msg.sample b/testing/lua-microlight/Microlight.git/hooks/prepare-commit-msg.sample deleted file mode 100755 index f093a02ec49..00000000000 --- a/testing/lua-microlight/Microlight.git/hooks/prepare-commit-msg.sample +++ /dev/null @@ -1,36 +0,0 @@ -#!/bin/sh -# -# An example hook script to prepare the commit log message. -# Called by "git commit" with the name of the file that has the -# commit message, followed by the description of the commit -# message's source. The hook's purpose is to edit the commit -# message file. If the hook fails with a non-zero status, -# the commit is aborted. -# -# To enable this hook, rename this file to "prepare-commit-msg". - -# This hook includes three examples. The first comments out the -# "Conflicts:" part of a merge commit. -# -# The second includes the output of "git diff --name-status -r" -# into the message, just before the "git status" output. It is -# commented because it doesn't cope with --amend or with squashed -# commits. -# -# The third example adds a Signed-off-by line to the message, that can -# still be edited. This is rarely a good idea. - -case "$2,$3" in - merge,) - /usr/bin/perl -i.bak -ne 's/^/# /, s/^# #/#/ if /^Conflicts/ .. /#/; print' "$1" ;; - -# ,|template,) -# /usr/bin/perl -i.bak -pe ' -# print "\n" . `git diff --cached --name-status -r` -# if /^#/ && $first++ == 0' "$1" ;; - - *) ;; -esac - -# SOB=$(git var GIT_AUTHOR_IDENT | sed -n 's/^\(.*>\).*$/Signed-off-by: \1/p') -# grep -qs "^$SOB" "$1" || echo "$SOB" >> "$1" diff --git a/testing/lua-microlight/Microlight.git/hooks/update.sample b/testing/lua-microlight/Microlight.git/hooks/update.sample deleted file mode 100755 index 71ab04edc09..00000000000 --- a/testing/lua-microlight/Microlight.git/hooks/update.sample +++ /dev/null @@ -1,128 +0,0 @@ -#!/bin/sh -# -# An example hook script to blocks unannotated tags from entering. -# Called by "git receive-pack" with arguments: refname sha1-old sha1-new -# -# To enable this hook, rename this file to "update". -# -# Config -# ------ -# hooks.allowunannotated -# This boolean sets whether unannotated tags will be allowed into the -# repository. By default they won't be. -# hooks.allowdeletetag -# This boolean sets whether deleting tags will be allowed in the -# repository. By default they won't be. -# hooks.allowmodifytag -# This boolean sets whether a tag may be modified after creation. By default -# it won't be. -# hooks.allowdeletebranch -# This boolean sets whether deleting branches will be allowed in the -# repository. By default they won't be. -# hooks.denycreatebranch -# This boolean sets whether remotely creating branches will be denied -# in the repository. By default this is allowed. -# - -# --- Command line -refname="$1" -oldrev="$2" -newrev="$3" - -# --- Safety check -if [ -z "$GIT_DIR" ]; then - echo "Don't run this script from the command line." >&2 - echo " (if you want, you could supply GIT_DIR then run" >&2 - echo " $0 )" >&2 - exit 1 -fi - -if [ -z "$refname" -o -z "$oldrev" -o -z "$newrev" ]; then - echo "Usage: $0 " >&2 - exit 1 -fi - -# --- Config -allowunannotated=$(git config --bool hooks.allowunannotated) -allowdeletebranch=$(git config --bool hooks.allowdeletebranch) -denycreatebranch=$(git config --bool hooks.denycreatebranch) -allowdeletetag=$(git config --bool hooks.allowdeletetag) -allowmodifytag=$(git config --bool hooks.allowmodifytag) - -# check for no description -projectdesc=$(sed -e '1q' "$GIT_DIR/description") -case "$projectdesc" in -"Unnamed repository"* | "") - echo "*** Project description file hasn't been set" >&2 - exit 1 - ;; -esac - -# --- Check types -# if $newrev is 0000...0000, it's a commit to delete a ref. -zero="0000000000000000000000000000000000000000" -if [ "$newrev" = "$zero" ]; then - newrev_type=delete -else - newrev_type=$(git cat-file -t $newrev) -fi - -case "$refname","$newrev_type" in - refs/tags/*,commit) - # un-annotated tag - short_refname=${refname##refs/tags/} - if [ "$allowunannotated" != "true" ]; then - echo "*** The un-annotated tag, $short_refname, is not allowed in this repository" >&2 - echo "*** Use 'git tag [ -a | -s ]' for tags you want to propagate." >&2 - exit 1 - fi - ;; - refs/tags/*,delete) - # delete tag - if [ "$allowdeletetag" != "true" ]; then - echo "*** Deleting a tag is not allowed in this repository" >&2 - exit 1 - fi - ;; - refs/tags/*,tag) - # annotated tag - if [ "$allowmodifytag" != "true" ] && git rev-parse $refname > /dev/null 2>&1 - then - echo "*** Tag '$refname' already exists." >&2 - echo "*** Modifying a tag is not allowed in this repository." >&2 - exit 1 - fi - ;; - refs/heads/*,commit) - # branch - if [ "$oldrev" = "$zero" -a "$denycreatebranch" = "true" ]; then - echo "*** Creating a branch is not allowed in this repository" >&2 - exit 1 - fi - ;; - refs/heads/*,delete) - # delete branch - if [ "$allowdeletebranch" != "true" ]; then - echo "*** Deleting a branch is not allowed in this repository" >&2 - exit 1 - fi - ;; - refs/remotes/*,commit) - # tracking branch - ;; - refs/remotes/*,delete) - # delete tracking branch - if [ "$allowdeletebranch" != "true" ]; then - echo "*** Deleting a tracking branch is not allowed in this repository" >&2 - exit 1 - fi - ;; - *) - # Anything else (is there anything else?) - echo "*** Update hook: unknown type of update to ref $refname of type $newrev_type" >&2 - exit 1 - ;; -esac - -# --- Finished -exit 0 diff --git a/testing/lua-microlight/Microlight.git/info/exclude b/testing/lua-microlight/Microlight.git/info/exclude deleted file mode 100644 index a5196d1be8f..00000000000 --- a/testing/lua-microlight/Microlight.git/info/exclude +++ /dev/null @@ -1,6 +0,0 @@ -# git ls-files --others --exclude-from=.git/info/exclude -# Lines that start with '#' are comments. -# For a project mostly in C, the following would be a good set of -# exclude patterns (uncomment them if you want to use them): -# *.[oa] -# *~ diff --git a/testing/lua-microlight/Microlight.git/objects/pack/pack-b24eeb410b7f82331a4c067294ec2b9bd38f24ed.idx b/testing/lua-microlight/Microlight.git/objects/pack/pack-b24eeb410b7f82331a4c067294ec2b9bd38f24ed.idx deleted file mode 100644 index de1588edb9b3cb091275b4ba77359c8954182d85..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2360 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

6;Tr={n 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 0 and ch ~= sep and ch ~= other_sep do - i = i - 1 - ch = P:sub(i,i) - end - if i == 0 then - return '',P - else - return P:sub(1,i-1), P:sub(i+1) - end -end - ---- given a path, return the root part and the extension part. --- if there's no extension part, the second value will be empty --- @param P A file path --- @return the name part --- @return the extension -function ml.splitext(P) - local i = #P - local ch = P:sub(i,i) - while i > 0 and ch ~= '.' do - if ch == sep or ch == other_sep then - return P,'' - end - i = i - 1 - ch = P:sub(i,i) - end - if i == 0 then - return P,'' - else - return P:sub(1,i-1),P:sub(i) - end -end - ---- Extended table functions. --- 'list' here is shorthand for 'list-like table'; these functions --- only operate over the numeric `1..#t` range of a table and are --- particularly efficient for this purpose. --- @section table - -local function quote (v) - if type(v) == 'string' then - return ('%q'):format(v) - else - return tostring(v) - end -end - -local tbuff -function tbuff (t,buff,k) - buff[k] = "{" - k = k + 1 - for key,value in pairs(t) do - key = quote(key) - if type(value) ~= 'table' then - value = quote(value) - buff[k] = ('[%s]=%s'):format(key,value) - k = k + 1 - if buff.limit and k > buff.limit then - buff[k] = "..." - error("buffer overrun") - end - else - if not buff.tables then buff.tables = {} end - if not buff.tables[value] then - k = tbuff(value,buff,k) - buff.tables[value] = true - else - buff[k] = "" - k = k + 1 - end - end - buff[k] = "," - k = k + 1 - end - if buff[k-1] == "," then k = k - 1 end - buff[k] = "}" - k = k + 1 - return k -end - ---- return a string representation of a Lua table. --- Cycles are detected, and a limit on number of items can be imposed. --- @param t the table --- @param limit the limit on items, default 1000 --- @return a string -function ml.tstring (t,limit) - local buff = {limit = limit or 1000} - pcall(tbuff,t,buff,1) - return table.concat(buff) -end - ---- dump a Lua table to a file object. --- @param t the table --- @param f the file object (anything supporting f.write) -function ml.tdump(t,...) - local f = select('#',...) > 0 and select(1,...) or io.stdout - f:write(ml.tstring(t),'\n') -end - ---- map a function over a list. --- The output must always be the same length as the input, so --- any `nil` values are mapped to `false`. --- @param f a function of one or more arguments --- @param t the table --- @param ... any extra arguments to the function --- @return a list with elements `f(t[i])` -function ml.imap(f,t,...) - f = ml.function_arg(f) - local res = {} - for i = 1,#t do - local val = f(t[i],...) - if val == nil then val = false end - res[i] = val - end - return res -end - ---- filter a list using a predicate. --- @param t a table --- @param pred the predicate function --- @param ... any extra arguments to the predicate --- @return a list such that `pred(t[i])` is true -function ml.ifilter(t,pred,...) - local res,k = {},1 - pred = ml.function_arg(pred) - for i = 1,#t do - if pred(t[i],...) then - res[k] = t[i] - k = k + 1 - end - end - return res -end - ---- find an item in a list using a predicate. --- @param t the list --- @param pred a function of at least one argument --- @param ... any extra arguments --- @return the item value -function ml.ifind(t,pred,...) - pred = ml.function_arg(pred) - for i = 1,#t do - if pred(t[i],...) then - return t[i] - end - end -end - ---- return the index of an item in a list. --- @param t the list --- @param value item value --- @return index, otherwise `nil` -function ml.index (t,value) - for i = 1,#t do - if t[i] == value then return i end - end -end - ---- return a slice of a list. --- Like string.sub, the end index may be negative. --- @param t the list --- @param i1 the start index --- @param i2 the end index, default #t -function ml.sub(t,i1,i2) - if not i2 or i2 > #t then - i2 = #t - elseif i2 < 0 then - i2 = #t + i2 + 1 - end - local res,k = {},1 - for i = i1,i2 do - res[k] = t[i] - k = k + 1 - end - return res -end - ---- map a function over a Lua table. --- @param f a function of one or more arguments --- @param t the table --- @param ... any optional arguments to the function -function ml.tmap(f,t,...) - f = ml.function_arg(f) - local res = {} - for k,v in pairs(t) do - res[k] = f(v,...) - end - return res -end - ---- filter a table using a predicate. --- @param t a table --- @param pred the predicate function --- @param ... any extra arguments to the predicate --- @usage tfilter({a=1,b='boo'},tonumber) == {a=1} -function ml.tfilter (t,pred,...) - local res = {} - pred = ml.function_arg(pred) - for k,v in pairs(t) do - if pred(v,...) then - res[k] = v - end - end - return res -end - ---- add the key/value pairs of `other` to `t`. --- For sets, this is their union. For the same keys, --- the values from the first table will be overwritten --- @param t table to be updated --- @param other table --- @return the updated table -function ml.update(t,other) - for k,v in pairs(other) do - t[k] = v - end - return t -end - ---- extend a list using values from another. --- @param t the list to be extended --- @param other a list --- @return the extended list -function ml.extend(t,other) - local n = #t - for i = 1,#other do - t[n+i] = other[i] - end - return t -end - ---- make a set from a list. --- @param t a list of values --- @return a table where the keys are the values --- @usage set{'one','two'} == {one=true,two=true} -function ml.set(t) - local res = {} - for i = 1,#t do - res[t[i]] = true - end - return res -end - ---- extract the keys of a table as a list. --- This is the opposite operation to tset --- @param t a table --- @param a list of keys -function ml.keys(t) - local res,k = {},1 - for key in pairs(t) do - res[k] = key - k = k + 1 - end - return res -end - ---- is `other` a subset of `t`? --- @param t a set --- @param other a possible subset --- @return true or false -function ml.subset(t,other) - for k,v in pairs(other) do - if t[k] ~= v then return false end - end - return true -end - ---- are these two tables equal? --- This is shallow equality. --- @param t a table --- @param other a table --- @return true or false -function ml.tequal(t,other) - return ml.subset(t,other) and ml.subset(other,t) -end - ---- the intersection of two tables. --- Works as expected for sets, otherwise note that the first --- table's values are preseved --- @param t a table --- @param other a table --- @return the intersection of the tables -function ml.intersect(t,other) - local res = {} - for k,v in pairs(t) do - if other[k] then - res[k] = v - end - end - return res -end - ---- collect the values of an iterator into a list. --- @param iter a single or double-valued iterator --- @param count an optional number of values to collect --- @return a list of values. --- @usage collect(ipairs{10,20}) == {{1,10},{2,20}} -function ml.collect (iter, count) - local res,k = {},1 - local v1,v2 = iter() - local dbl = v2 ~= nil - while v1 do - if dbl then v1 = {v1,v2} end - res[k] = v1 - k = k + 1 - if count and k > count then break end - v1,v2 = iter() - end - return res -end - ---- Functional helpers. --- @section function - ---- create a function which will throw an error on failure. --- @param f a function that returns nil,err if it fails --- @return an equivalent function that raises an error -function ml.throw(f) - f = ml.function_arg(f) - return function(...) - local res,err = f(...) - if err then error(err) end - return res - end -end - ---- create a function which will never throw an error. --- This is the opposite situation to throw; if the --- original function throws an error e, then this --- function will return nil,e. --- @param f a function which can throw an error --- @return a function which returns nil,error when it fails -function ml.safe(f) - f = ml.function_arg(f) - return function(...) - local ok,r1,r2,r3 = pcall(f,...) - if ok then return r1,r2,r3 - else - return nil,r1 - end - end -end ---memoize(f) - ---- bind the value `v` to the first argument of function `f`. --- @param f a function of at least one argument --- @param v a value --- @return a function of one less argument --- @usage (bind1(string.match,'hello')('^hell') == 'hell' -function ml.bind1(f,v) - f = ml.function_arg(f) - return function(...) - return f(v,...) - end -end - ---- compose two functions. --- For instance, `printf` can be defined as `compose(io.write,string.format)` --- @param f1 a function --- @param f2 a function --- @return f1(f2(...)) -function ml.compose(f1,f2) - f1 = ml.function_arg(f1) - f2 = ml.function_arg(f2) - return function(...) - return f1(f2(...)) - end -end - ---- is the object either a function or a callable object?. --- @param obj Object to check. --- @return true if callable -function ml.callable (obj) - return type(obj) == 'function' or getmetatable(obj) and getmetatable(obj).__call -end - -function ml.function_arg(f) - assert(ml.callable(f),"expecting a function or callable object") - return f -end - ---- Classes. --- @section class - ---- create a class with an optional base class. --- The resulting table has a new() function for invoking --- the constructor, which must be named `_init`. If the base --- class has a constructor, you can call it as the `super()` method. --- The `__tostring` metamethod is also inherited, but others need --- to be brought in explicitly. --- @param base optional base class --- @return the metatable representing the class -function ml.class(base) - local klass, base_ctor = {} - klass.__index = klass - if base then - setmetatable(klass,base) - klass._base = base - base_ctor = rawget(base,'_init') - klass.__tostring = base.__tostring - end - function klass.new(...) - local self = setmetatable({},klass) - if rawget(klass,'_init') then - klass.super = base_ctor -- make super available for ctor - klass._init(self,...) - elseif base_ctor then -- call base ctor automatically - base_ctor(self,...) - end - return self - end - return klass -end - ---- is an object derived from a class? --- @param self the object --- @param klass a class created with `class` --- @return true or false -function ml.is_a(self,klass) - local m = getmetatable(self) - if not m then return false end --*can't be an object! - while m do - if m == klass then return true end - m = rawget(m,'_base') - end - return false -end - -local _type = type - ---- extended type of an object. --- The type of a table is its metatable, otherwise works like standard type() --- @param obj a value --- @return the type, either a string or the metatable -function ml.type (obj) - if _type(obj) == 'table' then - return getmetatable(obj) or 'table' - else - return _type(obj) - end -end - -return ml