-
-
Save fowlmouth/8cc9ee26bcf509b5fea5 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# | |
# This module is dedicated to Marijuana. I love you. | |
# | |
# herein lies a macro called import_repo which accepts | |
# somewhat of a URL, something like github.com/you/repository/module | |
# the repository will be cloned and imported, like that other | |
# language's import statement. with metaprogramming, not baked | |
# into the compiler, like that other language. | |
# | |
# at the moment github.com and bitbucket.com (for git) is supported | |
# | |
# the programming language which may or may not be named | |
# 'go' can suck it. | |
# | |
# test included at the bottom of the file | |
# | |
import macros, os, strutils | |
proc createDirCT (dir:string) {.compiletime.} = | |
# hack | |
when defined(Linux): | |
discard staticExec("mkdir -p "&dir) | |
else: | |
{.error: "no implement".} | |
type | |
TDomain = enum | |
wtf, # repo field is an error message | |
github, | |
bitbucket | |
repo_import = tuple | |
domain:TDomain | |
repo, module:string | |
proc parse_import (x: pnimrodnode): repo_import {.compileTime.} = | |
var | |
repo = "" | |
n = x | |
cbs = newseq[proc(str:var string)]() | |
while true: | |
#echo n.kind | |
## TODO account for "as" here | |
if n.kind == nnkInfix and n[0].ident == !"/": | |
#echo treerepr(n) | |
let right = n[2] | |
n = n[1] | |
cbs.add(proc (str:var string) = | |
#echo "right: ", right | |
if right.kind == nnkIdent: | |
let dir = $ right.ident | |
if str.len > 0: str.add '/' | |
str.add dir | |
) | |
elif n.kind == nnkDotExpr: | |
let dom = repr(n) | |
if dom.eqIdent("github.com"): | |
result.domain = github | |
break | |
elif dom.eqIdent("bitbucket.org"): | |
result.domain = bitbucket | |
break | |
else: | |
return (wtf, "domain "& dom &" is unknown, please write support","") | |
break | |
else: | |
return (wtf, "wtf is "& repr(n),"") | |
assert result[0] != wtf | |
## run the callbacks backwards, since they are inside out | |
## good test of compiletime closures :) | |
assert cbs.len > 1 | |
for i in countdown(high(cbs),high(cbs)-1): cbs[i](repo) | |
var module = "" | |
for i in countdown(high(cbs)-2,0): cbs[i](module) | |
assert n.kind == nnkDotExpr | |
result.repo = repo | |
result.module = | |
if module.len == 0: repo[repo.rfind("/")+1 .. -1] | |
else: module | |
#echo "domain: ", result.repr | |
macro import_repo* (files: expr): stmt {.immediate.} = | |
let cs = callsite() | |
cs.expectKind nnkCommand | |
if cs.len == 1: return newEmptyNode() | |
var imports: seq[repo_import] = @[] | |
for i in 1.. <len(cs): | |
let f = cs[i] | |
let x = parse_import(f) | |
if x[0] == wtf: | |
echo x[1] | |
else: | |
imports.add x | |
if imports.len == 0: | |
return newEmptyNode() | |
proc git_clone (url,dir:string) = | |
when defined(Linux): | |
echo staticExec("""pushd $# ; pwd ; git clone --depth 1 $# . ; popd""".format( | |
dir, url | |
)) | |
else: | |
{.error: "implement me".} | |
# git@bitbucket.org:$2.git | |
proc github_clone (repos,dir:string) = | |
git_clone "git@github.com:$#.git" % repos, dir | |
proc gist_clone (repos,dir:string) = | |
git_clone "https://gist.github.com/$#.git" % repos[repos.rfind("/")+1 .. -1], dir | |
# https://gist.github.com/8cc9ee26bcf509b5fea5.git | |
proc bitbucket_clone (repos,dir:string)= | |
git_clone "git@bitbucket.org:$#.git" % repos, dir | |
result = newStmtList() | |
for i in imports: | |
#echo i | |
let repo_dir = "repos"/ $i.domain / i.repo | |
let module = repo_dir / i.module | |
case i.domain | |
of github: | |
createDirCT(repo_dir) | |
github_clone(i.repo, repo_dir) | |
of bitbucket: | |
createDirCT(repo_dir) | |
bitbucket_clone(i.repo, repo_dir) | |
else: | |
continue #shouldnt happen | |
result.add parseExpr("import \"./$1\"" % module) | |
when defined(Debug): | |
echo repr(result) | |
when isMainModule: | |
template echoCode (code:expr):stmt = | |
echo astToStr(code), ": ", code | |
macro test_parser (xpr,eqs): stmt {.immediate.}= | |
let res = parse_import(xpr) | |
result = parseExpr("echoCode(($#,\"$#\",\"$#\") == $#)".format( | |
res[0],res[1],res[2], eqs.repr | |
)) | |
when defined(debug): result.repr.echo | |
## tests that url parses correctly | |
test_parser github.com/a/b, (github,"a/b","b") | |
test_parser github.com/a/b/c, (github,"a/b","c") | |
test_parser bitbucket.org/a/b/c/d, (bitbucket,"a/b","c/d") | |
#test_parser gist.github.com/u/deadbeef/m, (gisthub,"u/deadbeef","m") | |
#test_parser hg.bitbucket.org/u/r/m, (bitbuckethg, "u/r", "m") | |
when isMainModule: | |
import_repo github.com/fowlmouth/glossolalia/src/glossolalia | |
echo charMatcher[int]('a','b').repeat(1).match("aaba") | |
when false: | |
#TODO this | |
import_repo github.com/x/y as z | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment