blob: 07fb52565b01074cb9fb8d4d54f2b600fb8c2d75 [file] [log] [blame]
hardlyb1e7e142014-08-06 00:43:51 +03001#! /usr/bin/env python
2
3# ==============================================================================
4# ==============================================================================
5# == NOTE THIS SCRIPT IS A MODIFIED VERSION OF
6# == https://github.com/ned14/Boost.APIBind/tree/master/scripts
7# == - SEARCHES FOR HEADERS WITH AN '.H' EXTENSION INSTEAD OF '.HPP'
8# == - NO BOOST, NEWEST COMPILER, ETC.
9# == REST API: https://github.com/melpon/wandbox/blob/master/kennel2/API.rst
10# ==============================================================================
11# ==============================================================================
12
13# This script uploads a directory to Wandbox (http://melpon.org/wandbox),
14# which is an online compiler environment, and prints a permalink to the
15# uploaded code. We use this to provide a "Try it online" version of the
16# library to make the barrier to entry as low as possible.
17#
18# This script was adapted from the script proposed in
19# https://github.com/melpon/wandbox/issues/153.
20#
21# To know how to use this script: ./wandbox.py --help
22#
23# Copyright Louis Dionne 2015
24# Distributed under the Boost Software License, Version 1.0.
25# (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
26
27import argparse
28import fnmatch
29import json
30import os
31import re
32import urllib2
33
34
35# Strips C and C++ comments from the given string.
36#
37# Copied from http://stackoverflow.com/a/241506/627587.
38def strip_comments(text):
39 def replacer(match):
40 s = match.group(0)
41 if s.startswith('/'):
42 return " " # note: a space and not an empty string
43 else:
44 return s
45 pattern = re.compile(
46 r'//.*?$|/\*.*?\*/|\'(?:\\.|[^\\\'])*\'|"(?:\\.|[^\\"])*"',
47 re.DOTALL | re.MULTILINE
48 )
49 return re.sub(pattern, replacer, text)
50
51
52# Post the given JSON data to Wandbox's API, and return the result
53# as a JSON object.
54def upload(options):
55 request = urllib2.Request('http://melpon.org/wandbox/api/compile.json')
56 request.add_header('Content-Type', 'application/json')
57 response = urllib2.urlopen(request, json.dumps(options))
58 return json.loads(response.read())
59
60
61# Returns a list of the '.h' headers in the given directory and in
62# subdirectories.
63#
64# The path must be absolute, and the returned paths are all absolute too.
65def headers(path):
66 return [
67 os.path.join(dir, file)
68 for (dir, _, files) in os.walk(path)
69 for file in fnmatch.filter(files, "*.h")
70 ]
71
72
73def main():
74 parser = argparse.ArgumentParser(description=
75 """Upload a directory to Wandbox (http://melpon.org/wandbox).
76
77 On success, the program prints a permalink to the uploaded
78 directory on Wandbox and returns 0. On error, it prints the
79 response from the Wandbox API and returns 1.
80
81 Note that the comments are stripped from all the headers in the
82 uploaded directory.
83 """
84 )
85 parser.add_argument('directory', type=str, help=
86 """A directory to upload to Wandbox.
87
88 The path may be either absolute or relative to the current directory.
89 However, the names of the files uploaded to Wandbox will all be
90 relative to this directory. This way, one can easily specify the
91 directory to be '/some/project/include', and the uploaded files
92 will be uploaded as-if they were rooted at '/some/project/include'
93 """)
94 parser.add_argument('main', type=str, help=
95 """The main source file.
96
97 The path may be either absolute or relative to the current directory.
98 """
99 )
100 args = parser.parse_args()
101 directory = os.path.abspath(args.directory)
102 if not os.path.exists(directory):
103 raise Exception("'%s' is not a valid directory" % args.directory)
104
105 cpp = os.path.abspath(args.main)
106 if not os.path.exists(cpp):
107 raise Exception("'%s' is not a valid file name" % args.main)
108
109 response = upload({
110 'code': open(cpp).read(),
111 'codes': [{
112 'file': os.path.relpath(header, directory),
113 'code': strip_comments(open(header).read())
114 } for header in headers(directory)],
115 'options': 'c++98,cpp-no-pedantic',
116 'compiler': 'gcc-head',
117 'save': True,
118 'compiler-option-raw': '-Wall\n-Wextra'
119 })
120
onqtam8126b562016-05-27 17:01:15 +0300121 if 'status' in response and not 'compiler_error' in response: # and response['status'] == '0':
hardlyb1e7e142014-08-06 00:43:51 +0300122 print response['url']
123 return 0
124 else:
125 print response
126 return 1
127
128
129exit(main())