From fae6dbfebde8f1ea5ffeb311153d887320ee3fd2 Mon Sep 17 00:00:00 2001 From: Arfon Smith Date: Thu, 4 Sep 2014 13:49:30 -0500 Subject: [PATCH 1/2] Taking Heuristics for a spin. --- lib/linguist/heuristics.rb | 19 +- lib/linguist/language.rb | 2 +- lib/linguist/languages.yml | 6 +- lib/linguist/samples.json | 524 +++++++++++++++--- samples/Prolog/admin.pl | 1051 ++++++++++++++++++++++++++++++++++++ 5 files changed, 1514 insertions(+), 88 deletions(-) create mode 100755 samples/Prolog/admin.pl diff --git a/lib/linguist/heuristics.rb b/lib/linguist/heuristics.rb index c1116780..b22422c3 100644 --- a/lib/linguist/heuristics.rb +++ b/lib/linguist/heuristics.rb @@ -1,7 +1,7 @@ module Linguist # A collection of simple heuristics that can be used to better analyze languages. class Heuristics - ACTIVE = false + ACTIVE = true # Public: Given an array of String language names, # apply heuristics against the given data and return an array @@ -13,24 +13,13 @@ module Linguist # Returns an array of Languages or [] def self.find_by_heuristics(data, languages) if active? - if languages.all? { |l| ["Objective-C", "C++"].include?(l) } - disambiguate_c(data, languages) - end if languages.all? { |l| ["Perl", "Prolog"].include?(l) } - disambiguate_pl(data, languages) + result = disambiguate_pl(data, languages) end if languages.all? { |l| ["ECL", "Prolog"].include?(l) } - disambiguate_ecl(data, languages) - end - if languages.all? { |l| ["TypeScript", "XML"].include?(l) } - disambiguate_ts(data, languages) - end - if languages.all? { |l| ["Common Lisp", "OpenCL"].include?(l) } - disambiguate_cl(data, languages) - end - if languages.all? { |l| ["Rebol", "R"].include?(l) } - disambiguate_r(data, languages) + result = disambiguate_ecl(data, languages) end + return result end end diff --git a/lib/linguist/language.rb b/lib/linguist/language.rb index 6066b204..e42fbdc9 100644 --- a/lib/linguist/language.rb +++ b/lib/linguist/language.rb @@ -136,7 +136,7 @@ module Linguist elsif (determined = Heuristics.find_by_heuristics(data, possible_language_names)) && !determined.empty? determined.first # Lastly, fall back to the probablistic classifier. - elsif classified = Classifier.classify(Samples::DATA, data, possible_language_names ).first + elsif classified = Classifier.classify(Samples::DATA, data, possible_language_names).first # Return the actual Language object based of the string language name (i.e., first element of `#classify`) Language[classified[0]] end diff --git a/lib/linguist/languages.yml b/lib/linguist/languages.yml index e55c09eb..015c9577 100644 --- a/lib/linguist/languages.yml +++ b/lib/linguist/languages.yml @@ -1202,7 +1202,7 @@ LFE: LLVM: extensions: - .ll - + LabVIEW: type: programming lexer: Text only @@ -1784,9 +1784,9 @@ Prolog: type: programming color: "#74283c" extensions: - - .prolog - - .ecl - .pl + - .ecl + - .prolog Propeller Spin: type: programming diff --git a/lib/linguist/samples.json b/lib/linguist/samples.json index ef1b399e..273c5360 100644 --- a/lib/linguist/samples.json +++ b/lib/linguist/samples.json @@ -254,6 +254,9 @@ ".dlm", ".pro" ], + "IGOR Pro": [ + ".ipf" + ], "Idris": [ ".idr" ], @@ -845,8 +848,8 @@ "exception.zep.php" ] }, - "tokens_total": 654541, - "languages_total": 900, + "tokens_total": 659103, + "languages_total": 903, "tokens": { "ABAP": { "*/**": 1, @@ -28185,6 +28188,52 @@ "L": 1, "example": 1 }, + "IGOR Pro": { + "#pragma": 2, + "rtGlobals": 2, + "Function": 6, + "FooBar": 1, + "(": 10, + ")": 10, + "return": 7, + "End": 7, + "FooBarSubType": 1, + "ButtonControl": 1, + "Function/D": 1, + "FooBarVar": 1, + "static": 3, + "FooBarStatic": 1, + "threadsafe": 2, + "FooBarStaticThreadsafe": 1, + "FooBarThread": 1, + "CallOperationsAndBuiltInFuncs": 1, + "string": 4, + "var": 3, + "someDQString": 2, + "Make/N": 1, + "myWave": 2, + "Redimension/N": 1, + "-": 3, + "print": 1, + "strlen": 1, + "StrConstant": 1, + "myConstString": 1, + "constant": 1, + "myConst": 1, + "Structure": 2, + "struct1": 1, + "str": 2, + "variable": 2, + "EndStructure": 2, + "struct2": 1, + "#include": 1, + "#ifdef": 1, + "NOT_DEFINED": 1, + "//": 1, + "conditional": 1, + "compilation": 1, + "#endif": 1 + }, "INI": { ";": 1, "editorconfig.org": 1, @@ -55878,54 +55927,434 @@ "TWO_PI": 1 }, "Prolog": { - "-": 161, - "module": 3, - "(": 327, + "-": 348, + "module": 4, + "(": 1156, + "cpa_admin": 1, + "[": 290, + "change_password_form//1": 1, + "]": 288, + ")": 1153, + ".": 230, + "use_module": 20, + "user": 45, + "user_db": 1, + "library": 19, + "http/http_parameters": 1, + "http/http_session": 1, + "http/html_write": 1, + "http/html_head": 1, + "http/mimetype": 1, + "http/http_dispatch": 1, + "url": 1, + "debug": 5, + "lists": 1, + "option": 8, + "http_settings": 1, + "http_handler": 20, + "cliopatria": 38, + "list_users": 13, + "create_admin": 3, + "add_user_form": 4, + "add_openid_server_form": 4, + "add_user": 6, + "self_register": 4, + "add_openid_server": 3, + "edit_user_form": 7, + "edit_user": 4, + "del_user": 5, + "edit_openid_server_form": 6, + "edit_openid_server": 4, + "del_openid_server": 4, + "change_password_form": 7, + "change_password": 5, + "login_form": 4, + "user_login": 4, + "user_logout": 4, + "settings": 4, + "save_settings": 3, + "%": 193, + "+": 47, + "Request": 46, + "HTTP": 4, + "Handler": 1, + "listing": 1, + "registered": 3, + "users.": 2, + "_Request": 11, + "authorized": 13, + "admin": 31, + "if_allowed": 4, + "edit": 15, + "true": 32, + "UserOptions": 5, + "openid": 5, + "OpenIDOptions": 2, + "reply_html_page": 15, + "default": 16, + "title": 13, + "h1": 15, + "user_table": 3, + "p": 11, + "action": 18, + "location_by_id": 13, + "openid_server_table": 4, + "Token": 2, + "Options": 43, + "logged_on": 4, + "User": 77, + "anonymous": 2, + "catch": 2, + "check_permission": 1, + "_": 62, + "fail": 3, + "//": 7, + "HTML": 4, + "component": 3, + "generating": 1, + "a": 25, + "table": 9, + "of": 10, + "{": 22, + "setof": 3, + "U": 2, + "current_user": 6, + "Users": 2, + "}": 22, + "html": 25, + "class": 14, + "block": 2, + "tr": 16, + "th": 12, + "|": 44, + "T": 4, + "user_property": 8, + "realname": 18, + "Name": 19, + "findall": 1, + "Idle": 6, + "Login": 9, + "connection": 1, + "Pairs0": 2, + "keysort": 1, + "Pairs": 4, + "OnLine": 4, + ";": 37, + "length": 9, + "N": 7, + "online": 3, + "td": 20, + "on_since": 3, + "idle": 3, + "edit_user_button": 3, + "href": 6, + "encode": 4, + "_Idle": 1, + "_Connections": 2, + "format_time": 1, + "string": 10, + "Date": 2, + "_Login": 1, + "mmss_duration": 2, + "String": 10, + "Time": 3, + "in": 1, + "seconds": 1, + "Secs": 4, + "is": 24, + "round": 1, + "Hour": 2, + "Min": 4, + "mod": 2, + "Sec": 2, + "format": 9, + "Create": 2, + "the": 14, + "administrator": 1, + "login.": 2, + "throw": 12, + "error": 13, + "permission_error": 4, + "create": 3, + "context": 3, + "align": 16, + "center": 6, + "new_user_form": 3, + "real_name": 2, + "Form": 3, + "to": 19, + "register": 3, + "user.": 2, + "value": 11, + "PermUser": 3, + "form": 14, + "method": 6, + "input": 25, + "pwd1": 5, + "type": 16, + "password": 21, + "pwd2": 5, + "permissions": 5, + "buttons": 5, + "colspan": 6, + "right": 11, + "submit": 6, + "Label": 10, + "name": 8, + "size": 5, + "Only": 1, + "provide": 1, + "field": 4, + "if": 4, + "this": 1, + "not": 1, + "already": 2, + "given.": 1, + "This": 2, + "because": 1, + "firefox": 1, + "determines": 1, + "login": 3, + "from": 3, + "text": 6, + "immediately": 1, + "above": 1, + "entry.": 1, + "Other": 1, + "browsers": 1, + "may": 1, + "do": 1, + "it": 1, + "different": 1, + "so": 1, + "only": 2, + "having": 1, + "one": 1, + "probably": 1, + "savest": 1, + "solution.": 1, + "RealName": 13, + "hidden": 7, + "_Options": 1, + "API": 1, + "new": 6, + "The": 3, + "current": 3, + "must": 3, + "have": 1, + "administrative": 2, + "rights": 2, + "or": 3, + "database": 1, + "be": 6, + "empty.": 1, + "FirstUser": 2, + "http_parameters": 10, + "Password": 13, + "Retype": 4, + "read": 13, + "Read": 12, + "write": 11, + "Write": 12, + "Admin": 12, + "attribute_declarations": 10, + "attribute_decl": 21, + "password_mismatch": 2, + "password_hash": 3, + "Hash": 6, + "phrase": 6, + "allow": 17, + "Allow": 11, + "user_add": 3, + "reply_login": 5, + "Self": 1, + "and": 6, + "enable_self_register": 3, + "set": 2, + "true.": 1, + "limited": 1, + "annotate": 2, + "access.": 1, + "Returns": 1, + "forbidden": 3, + "false": 5, + "exists": 1, + "http_location_by_id": 1, + "MyUrl": 3, + "setting": 1, + "http_reply": 3, + "properties": 3, + "User.": 1, + "b": 6, + "i": 1, + "Term": 16, + "..": 11, + "Value": 15, + "O2": 6, + "p_name": 2, + "permission_checkbox": 4, + "Actions": 3, + "openid_server_property": 3, + "pterm": 5, + "Action": 17, + "memberchk": 4, + "Opts": 4, + "checked": 2, + "def_user_permissions": 3, + "DefPermissions": 2, + "checkbox": 1, + "Handle": 3, + "reply": 3, + "form.": 2, + "optional": 6, + "description": 18, + "modify_user": 2, + "modify_permissions": 2, + "Property": 6, + "_Name": 2, + "var": 7, + "set_user_property": 3, + "Access": 2, + "on": 2, + "_Access": 1, + "off": 5, + "_Repositiory": 2, + "_Action": 3, + "Delete": 2, + "delete": 2, + "user_del": 1, + "change": 2, + "context_error": 2, + "not_logged_in": 2, + "UserID": 1, + "that": 2, + "shows": 1, + "for": 4, + "changing": 1, + "UserID.": 1, + "id": 3, + "user_or_old": 3, + "pwd0": 2, + "handler": 2, + "password.": 1, + "logged": 1, + "on.": 1, + "New": 3, + "existence_error": 1, + "validate_password": 2, + "presents": 1, + "If": 2, + "there": 1, + "parameter": 2, + "return_to": 3, + "openid.return_to": 1, + "using": 1, + "redirect": 1, + "given": 2, + "URL.": 1, + "Otherwise": 1, + "display": 1, + "welcome": 1, + "page.": 1, + "ReturnTo": 6, + "Extra": 3, + "moved_temporary": 1, + "Logout": 1, + "logout": 1, + "Param": 1, + "DeclObtions": 1, + "semidet.": 4, + "Provide": 1, + "reusable": 1, + "declarations": 1, + "calls": 2, + "http_parameters/3.": 1, + "openid_server": 9, + "bool": 4, + "Def": 2, + "oneof": 1, + "Return": 1, + "an": 3, + "page": 1, + "add": 2, + "OpenID": 4, + "server.": 1, + "new_openid_form": 2, + "new_openid_form//": 1, + "det.": 5, + "Present": 1, + "provider.": 1, + "openid_description": 1, + "code": 2, + "canonical_url": 1, + "URL0": 2, + "URL": 4, + "parse_url": 2, + "Parts": 2, + "Server": 30, + "openid_property": 2, + "List": 1, + "servers": 1, + "S": 2, + "openid_current_server": 1, + "Servers": 2, + "openid_list_servers": 4, + "H": 2, + "openid_list_server": 2, + "openid_field": 3, + "edit_openid_button": 3, + "Field": 2, + "server": 1, + "Description": 2, + "modify_openid": 2, + "openid_modify_permissions": 2, + "openid_set_property": 2, + "openid_del_server": 1, + "Show": 1, + "settings.": 3, + "has": 1, + "editing": 1, + "edit_settings": 2, + "Edit": 4, + "http_show_settings": 1, + "hide_module": 1, + "warn_no_edit": 3, + "settings_no_edit": 1, + "Save": 1, + "modified": 1, + "http_apply_settings": 1, + "save": 1, + "with": 3, + "br": 1, "format_spec": 12, - "[": 87, "format_error/2": 1, "format_spec/2": 1, "format_spec//1": 1, "spec_arity/2": 1, "spec_types/2": 1, - "]": 87, - ")": 326, - ".": 107, - "use_module": 8, - "library": 8, "dcg/basics": 1, "eos//0": 1, "integer//1": 1, "string_without//2": 1, - "error": 6, "when": 3, "when/2": 1, - "%": 71, "mavis": 1, "format_error": 8, - "+": 14, "Goal": 29, "Error": 25, - "string": 8, - "is": 12, "nondet.": 1, - "format": 8, "Format": 23, "Args": 19, "format_error_": 5, - "_": 30, - "debug": 4, "Spec": 10, "is_list": 1, "spec_types": 8, "Types": 16, "types_error": 3, - "length": 4, "TypesLen": 3, "ArgsLen": 3, "types_error_": 4, "Arg": 6, - "|": 25, "Type": 3, "ground": 5, "is_of_type": 2, @@ -55940,13 +56369,9 @@ "format_fail/3.": 1, "prolog_walk_code": 1, "module_class": 1, - "user": 5, "infer_meta_predicates": 1, - "false": 2, "autoload": 1, "format/": 1, - "{": 7, - "}": 7, "are": 3, "always": 1, "loaded": 1, @@ -55967,7 +56392,6 @@ "checker.": 1, "succeed": 2, "even": 1, - "if": 1, "no": 1, "found": 1, "Module": 4, @@ -55975,12 +56399,10 @@ "predicate_property": 1, "imported_from": 1, "Source": 2, - "memberchk": 2, "system": 1, "prolog_debug": 1, "can_check": 2, "assert": 2, - "to": 5, "avoid": 1, "printing": 1, "goals": 1, @@ -55989,32 +56411,22 @@ "prolog": 2, "message": 1, "message_location": 1, - "//": 1, "eos.": 1, "escape": 2, "Numeric": 4, "Modifier": 2, - "Action": 15, "Rest": 12, "numeric_argument": 5, "modifier_argument": 3, - "action": 6, - "text": 4, - "String": 6, - ";": 12, "Codes": 21, "string_codes": 4, "string_without": 1, "list": 4, - "semidet.": 3, "text_codes": 6, - "phrase": 3, "spec_arity": 2, "FormatSpec": 2, "Arity": 3, "positive_integer": 1, - "det.": 4, - "type": 2, "Item": 2, "Items": 2, "item_types": 3, @@ -56029,17 +56441,14 @@ "Text": 1, "codes": 5, "Var": 5, - "var": 4, "Atom": 3, "atom": 6, - "N": 5, "integer": 7, "C": 5, "colon": 1, "no_colon": 1, "is_action": 4, "multi.": 1, - "a": 4, "d": 3, "e": 1, "float": 3, @@ -56047,7 +56456,6 @@ "G": 2, "I": 1, "n": 1, - "p": 1, "any": 3, "r": 1, "s": 2, @@ -56056,7 +56464,6 @@ "func": 13, "op": 2, "xfy": 2, - "of": 8, "/2": 3, "list_util": 1, "xfy_list/3": 1, @@ -56070,7 +56477,6 @@ "at": 3, "compile": 3, "time": 3, - "for": 1, "macro": 1, "expansion.": 1, "compile_function/4.": 1, @@ -56081,19 +56487,14 @@ "evaluable/1": 1, "throws": 1, "exception": 1, - "with": 2, "strings": 1, "evaluable": 1, "term_variables": 1, "F": 26, "function_composition_term": 2, "Functor": 8, - "true": 5, - "..": 6, "format_template": 7, "has_type": 2, - "fail": 1, - "be": 4, "explicit": 1, "Dict": 3, "is_dict": 1, @@ -56101,7 +56502,6 @@ "Function": 5, "Argument": 1, "Apply": 1, - "an": 1, "Argument.": 1, "A": 1, "predicate": 4, @@ -56110,18 +56510,15 @@ "argument": 2, "generates": 1, "output": 1, - "and": 2, "penultimate": 1, "accepts": 1, "input.": 1, - "This": 1, "realized": 1, "by": 2, "expanding": 1, "function": 2, "application": 2, "chained": 1, - "calls": 1, "time.": 1, "itself": 1, "can": 3, @@ -56130,12 +56527,8 @@ "reverse": 4, "sort": 2, "c": 2, - "b": 4, "meta_predicate": 2, - "throw": 1, - "permission_error": 1, "call": 4, - "context": 1, "X": 10, "Y": 7, "defer": 1, @@ -56143,13 +56536,10 @@ "run": 1, "P": 2, "Creates": 1, - "new": 2, "composing": 1, "G.": 1, - "The": 1, "functions": 2, "composed": 1, - "create": 1, "compiled": 1, "which": 1, "behaves": 1, @@ -56164,7 +56554,6 @@ "syntax": 1, "highlighting": 1, "functions_to_compose": 2, - "Term": 10, "Funcs": 7, "functor": 1, "Op": 3, @@ -56186,9 +56575,7 @@ "compile_predicates": 1, "Output": 2, "compound": 1, - "setof": 1, "arg": 1, - "Name": 2, "Args0": 2, "nth1": 2, "lib": 1, @@ -56199,11 +56586,9 @@ "#": 9, "labeling": 2, "vabsIC": 1, - "or": 1, "faitListe": 3, "First": 2, "Taille": 2, - "Min": 2, "Max": 2, "Min..Max": 1, "Taille1": 2, @@ -56258,7 +56643,6 @@ "Rs1": 2, "left": 4, "stay": 1, - "right": 1, "L": 2 }, "Propeller Spin": { @@ -72649,6 +73033,7 @@ "Haskell": 302, "Hy": 155, "IDL": 418, + "IGOR Pro": 97, "INI": 27, "Idris": 148, "Inform 7": 75, @@ -72725,7 +73110,7 @@ "PostScript": 107, "PowerShell": 12, "Processing": 74, - "Prolog": 2420, + "Prolog": 6885, "Propeller Spin": 13519, "Protocol Buffer": 63, "PureScript": 1652, @@ -72862,6 +73247,7 @@ "Haskell": 3, "Hy": 2, "IDL": 4, + "IGOR Pro": 2, "INI": 2, "Idris": 1, "Inform 7": 2, @@ -72938,7 +73324,7 @@ "PostScript": 1, "PowerShell": 2, "Processing": 1, - "Prolog": 5, + "Prolog": 6, "Propeller Spin": 10, "Protocol Buffer": 1, "PureScript": 4, @@ -73005,5 +73391,5 @@ "fish": 3, "wisp": 1 }, - "md5": "7a970958bd95602c130be259e8f3fc31" + "md5": "1500ca2d5506e7d4e02f8c1d14e348a4" } \ No newline at end of file diff --git a/samples/Prolog/admin.pl b/samples/Prolog/admin.pl new file mode 100755 index 00000000..39a6a538 --- /dev/null +++ b/samples/Prolog/admin.pl @@ -0,0 +1,1051 @@ +/* Part of ClioPatria SeRQL and SPARQL server + + Author: Jan Wielemaker + E-mail: J.Wielemaker@cs.vu.nl + WWW: http://www.swi-prolog.org + Copyright (C): 2004-2010, University of Amsterdam, + VU University Amsterdam + + This program is free software; you can redistribute it and/o ClioPatria administrative interface + +This module provides HTTP services to perform administrative actions. + +@tbd Ideally, this module should be split into an api-part, a + component-part and the actual pages. This also implies that + the current `action'-operations must (optionally) return + machine-friendly results. +*/ + + +:- http_handler(cliopatria('admin/listUsers'), list_users, []). +:- http_handler(cliopatria('admin/form/createAdmin'), create_admin, []). +:- http_handler(cliopatria('admin/form/addUser'), add_user_form, []). +:- http_handler(cliopatria('admin/form/addOpenIDServer'), add_openid_server_form, []). +:- http_handler(cliopatria('admin/addUser'), add_user, []). +:- http_handler(cliopatria('admin/selfRegister'), self_register, []). +:- http_handler(cliopatria('admin/addOpenIDServer'), add_openid_server, []). +:- http_handler(cliopatria('admin/form/editUser'), edit_user_form, []). +:- http_handler(cliopatria('admin/editUser'), edit_user, []). +:- http_handler(cliopatria('admin/delUser'), del_user, []). +:- http_handler(cliopatria('admin/form/editOpenIDServer'), edit_openid_server_form, []). +:- http_handler(cliopatria('admin/editOpenIDServer'), edit_openid_server, []). +:- http_handler(cliopatria('admin/delOpenIDServer'), del_openid_server, []). +:- http_handler(cliopatria('admin/form/changePassword'), change_password_form, []). +:- http_handler(cliopatria('admin/changePassword'), change_password, []). +:- http_handler(cliopatria('user/form/login'), login_form, []). +:- http_handler(cliopatria('user/login'), user_login, []). +:- http_handler(cliopatria('user/logout'), user_logout, []). +:- http_handler(cliopatria('admin/settings'), settings, []). +:- http_handler(cliopatria('admin/save_settings'), save_settings, []). + +%% list_users(+Request) +% +% HTTP Handler listing registered users. + +list_users(_Request) :- + authorized(admin(list_users)), + if_allowed(admin(user(edit)), [edit(true)], UserOptions), + if_allowed(admin(openid(edit)), [edit(true)], OpenIDOptions), + reply_html_page(cliopatria(default), + title('Users'), + [ h1('Users'), + \user_table(UserOptions), + p(\action(location_by_id(add_user_form), 'Add user')), + h1('OpenID servers'), + \openid_server_table(OpenIDOptions), + p(\action(location_by_id(add_openid_server_form), 'Add OpenID server')) + ]). + +if_allowed(Token, Options, Options) :- + logged_on(User, anonymous), + catch(check_permission(User, Token), _, fail), !. +if_allowed(_, _, []). + +%% user_table(+Options)// +% +% HTML component generating a table of registered users. + +user_table(Options) --> + { setof(U, current_user(U), Users) + }, + html([ table([ class(block) + ], + [ tr([ th('UserID'), + th('RealName'), + th('On since'), + th('Idle') + ]) + | \list_users(Users, Options) + ]) + ]). + +list_users([], _) --> + []. +list_users([User|T], Options) --> + { user_property(User, realname(Name)), + findall(Idle-Login, + user_property(User, connection(Login, Idle)), + Pairs0), + keysort(Pairs0, Pairs), + ( Pairs == [] + -> OnLine = (-) + ; length(Pairs, N), + Pairs = [Idle-Login|_], + OnLine = online(Login, Idle, N) + ) + }, + html(tr([ td(User), + td(Name), + td(\on_since(OnLine)), + td(\idle(OnLine)), + \edit_user_button(User, Options) + ])), + list_users(T, Options). + +edit_user_button(User, Options) --> + { option(edit(true), Options) }, !, + html(td(a(href(location_by_id(edit_user_form)+'?user='+encode(User)), 'Edit'))). +edit_user_button(_, _) --> + []. + +on_since(online(Login, _Idle, _Connections)) --> !, + { format_time(string(Date), '%+', Login) + }, + html(Date). +on_since(_) --> + html(-). + +idle(online(_Login, Idle, _Connections)) --> + { mmss_duration(Idle, String) + }, + html(String). +idle(_) --> + html(-). + + +mmss_duration(Time, String) :- % Time in seconds + Secs is round(Time), + Hour is Secs // 3600, + Min is (Secs // 60) mod 60, + Sec is Secs mod 60, + format(string(String), '~`0t~d~2|:~`0t~d~5|:~`0t~d~8|', [Hour, Min, Sec]). + + + + /******************************* + * ADD USERS * + *******************************/ + +%% create_admin(+Request) +% +% Create the administrator login. + +create_admin(_Request) :- + ( current_user(_) + -> throw(error(permission_error(create, user, admin), + context(_, 'Already initialized'))) + ; true + ), + reply_html_page(cliopatria(default), + title('Create administrator'), + [ h1(align(center), 'Create administrator'), + + p('No accounts are available on this server. \c + This form allows for creation of an administrative \c + account that can subsequently be used to create \c + new users.'), + + \new_user_form([ user(admin), + real_name('Administrator') + ]) + ]). + + +%% add_user_form(+Request) +% +% Form to register a user. + +add_user_form(_Request) :- + authorized(admin(add_user)), + reply_html_page(cliopatria(default), + title('Add new user'), + [ \new_user_form([]) + ]). + +new_user_form(Options) --> + { ( option(user(User), Options) + -> UserOptions = [value(User)], + PermUser = User + ; UserOptions = [], + PermUser = (-) + ) + }, + html([ h1('Add new user'), + form([ action(location_by_id(add_user)), + method('POST') + ], + table([ class((form)) + ], + [ \realname(Options), + \input(user, 'Login', + UserOptions), + \input(pwd1, 'Password', + [type(password)]), + \input(pwd2, 'Retype', + [type(password)]), + \permissions(PermUser), + tr(class(buttons), + td([ colspan(2), + align(right) + ], + input([ type(submit), + value('Create') + ]))) + ])) + ]). + + +input(Name, Label, Options) --> + html(tr([ th(align(right), Label), + td(input([name(Name),size(40)|Options])) + ])). + +% Only provide a realname field if this is not already given. This +% is because firefox determines the login user from the text field +% immediately above the password entry. Other browsers may do it +% different, so only having one text-field is probably the savest +% solution. + +realname(Options) --> + { option(real_name(RealName), Options) }, !, + hidden(realname, RealName). +realname(_Options) --> + input(realname, 'Realname', []). + + +%% add_user(+Request) +% +% API to register a new user. The current user must have +% administrative rights or the user-database must be empty. + +add_user(Request) :- + ( \+ current_user(_) + -> FirstUser = true + ; authorized(admin(add_user)) + ), + http_parameters(Request, + [ user(User), + realname(RealName), + pwd1(Password), + pwd2(Retype), + read(Read), + write(Write), + admin(Admin) + ], + [ attribute_declarations(attribute_decl) + ]), + ( current_user(User) + -> throw(error(permission_error(create, user, User), + context(_, 'Already present'))) + ; true + ), + ( Password == Retype + -> true + ; throw(password_mismatch) + ), + password_hash(Password, Hash), + phrase(allow(Read, Write, Admin), Allow), + user_add(User, + [ realname(RealName), + password(Hash), + allow(Allow) + ]), + ( FirstUser == true + -> user_add(anonymous, + [ realname('Define rights for not-logged in users'), + allow([read(_,_)]) + ]), + reply_login([user(User), password(Password)]) + ; list_users(Request) + ). + +%% self_register(Request) +% +% Self-register and login a new user if +% cliopatria:enable_self_register is set to true. +% Users are registered with full read +% and limited (annotate-only) write access. +% +% Returns a HTTP 403 forbidden error if: +% - cliopatria:enable_self_register is set to false +% - the user already exists + +self_register(Request) :- + http_location_by_id(self_register, MyUrl), + ( \+ setting(cliopatria:enable_self_register, true) + -> throw(http_reply(forbidden(MyUrl))) + ; true + ), + http_parameters(Request, + [ user(User), + realname(RealName), + password(Password) + ], + [ attribute_declarations(attribute_decl) + ]), + ( current_user(User) + -> throw(http_reply(forbidden(MyUrl))) + ; true + ), + password_hash(Password, Hash), + Allow = [ read(_,_), write(_,annotate) ], + user_add(User, [realname(RealName), password(Hash), allow(Allow)]), + reply_login([user(User), password(Password)]). + + +%% edit_user_form(+Request) +% +% Form to edit user properties + +edit_user_form(Request) :- + authorized(admin(user(edit))), + http_parameters(Request, + [ user(User) + ], + [ attribute_declarations(attribute_decl) + ]), + + reply_html_page(cliopatria(default), + title('Edit user'), + \edit_user_form(User)). + +%% edit_user_form(+User)// +% +% HTML component to edit the properties of User. + +edit_user_form(User) --> + { user_property(User, realname(RealName)) + }, + html([ h1(['Edit user ', User, ' (', RealName, ')']), + + form([ action(location_by_id(edit_user)), + method('POST') + ], + [ \hidden(user, User), + table([ class((form)) + ], + [ \user_property(User, realname, 'Real name', []), + \permissions(User), + tr(class(buttons), + td([ colspan(2), + align(right) + ], + input([ type(submit), + value('Modify') + ]))) + ]) + ]), + + p(\action(location_by_id(del_user)+'?user='+encode(User), + [ 'Delete user ', b(User), ' (', i(RealName), ')' ])) + ]). + +user_property(User, Name, Label, Options) --> + { Term =.. [Name, Value], + user_property(User, Term) + -> O2 = [value(Value)|Options] + ; O2 = Options + }, + html(tr([ th(class(p_name), Label), + td(input([name(Name),size(40)|O2])) + ])). + +permissions(User) --> + html(tr([ th(class(p_name), 'Permissions'), + td([ \permission_checkbox(User, read, 'Read'), + \permission_checkbox(User, write, 'Write'), + \permission_checkbox(User, admin, 'Admin') + ]) + ])). + +permission_checkbox(User, Name, Label) --> + { ( User \== (-), + ( user_property(User, allow(Actions)) + -> true + ; openid_server_property(User, allow(Actions)) + ), + pterm(Name, Action), + memberchk(Action, Actions) + -> Opts = [checked] + ; def_user_permissions(User, DefPermissions), + memberchk(Name, DefPermissions) + -> Opts = [checked] + ; Opts = [] + ) + }, + html([ input([ type(checkbox), + name(Name) + | Opts + ]), + Label + ]). + +def_user_permissions(-, [read]). +def_user_permissions(admin, [read, write, admin]). + + +%% edit_user(Request) +% +% Handle reply from edit user form. + +edit_user(Request) :- + authorized(admin(user(edit))), + http_parameters(Request, + [ user(User), + realname(RealName, + [ optional(true), + length > 2, + description('Comment on user identifier-name') + ]), + read(Read), + write(Write), + admin(Admin) + ], + [ attribute_declarations(attribute_decl) + ]), + modify_user(User, realname(RealName)), + modify_permissions(User, Read, Write, Admin), + list_users(Request). + + +modify_user(User, Property) :- + Property =.. [_Name|Value], + ( ( var(Value) + ; Value == '' + ) + -> true + ; set_user_property(User, Property) + ). + +modify_permissions(User, Read, Write, Admin) :- + phrase(allow(Read, Write, Admin), Allow), + set_user_property(User, allow(Allow)). + +allow(Read, Write, Admin) --> + allow(read, Read), + allow(write, Write), + allow(admin, Admin). + +allow(Access, on) --> + { pterm(Access, Allow) + }, !, + [ Allow + ]. +allow(_Access, off) --> !, + []. + +pterm(read, read(_Repositiory, _Action)). +pterm(write, write(_Repositiory, _Action)). +pterm(admin, admin(_Action)). + + +%% del_user(+Request) +% +% Delete a user + +del_user(Request) :- !, + authorized(admin(del_user)), + http_parameters(Request, + [ user(User) + ], + [ attribute_declarations(attribute_decl) + ]), + ( User == admin + -> throw(error(permission_error(delete, user, User), _)) + ; true + ), + user_del(User), + list_users(Request). + + +%% change_password_form(+Request) +% +% Allow user to change the password + +change_password_form(_Request) :- + logged_on(User), !, + user_property(User, realname(RealName)), + reply_html_page(cliopatria(default), + title('Change password'), + [ h1(['Change password for ', User, ' (', RealName, ')']), + + \change_password_form(User) + ]). +change_password_form(_Request) :- + throw(error(context_error(not_logged_in), _)). + + +%% change_password_form(+UserID)// +% +% HTML component that shows a form for changing the password for +% UserID. + +change_password_form(User) --> + html(form([ action(location_by_id(change_password)), + method('POST') + ], + [ table([ id('change-password-form'), + class(form) + ], + [ \user_or_old(User), + \input(pwd1, 'New Password', + [type(password)]), + \input(pwd2, 'Retype', + [type(password)]), + tr(class(buttons), + td([ align(right), + colspan(2) + ], + input([ type(submit), + value('Change password') + ]))) + ]) + ])). + +user_or_old(admin) --> !, + input(user, 'User', []). +user_or_old(_) --> + input(pwd0, 'Old password', [type(password)]). + + +%% change_password(+Request) +% +% HTTP handler to change the password. The user must be logged on. + +change_password(Request) :- + logged_on(Login), !, + http_parameters(Request, + [ user(User, [ optional(true), + description('User identifier-name') + ]), + pwd0(Password, [ optional(true), + description('Current password') + ]), + pwd1(New), + pwd2(Retype) + ], + [ attribute_declarations(attribute_decl) + ]), + ( Login == admin + -> ( current_user(User) + -> true + ; throw(error(existence_error(user, User), _)) + ) + ; Login = User, + validate_password(User, Password) + ), + ( New == Retype + -> true + ; throw(password_mismatch) + ), + password_hash(New, Hash), + set_user_property(User, password(Hash)), + reply_html_page(cliopatria(default), + 'Password changed', + [ h1(align(center), 'Password changed'), + p([ 'Your password has been changed successfully' ]) + ]). +change_password(_Request) :- + throw(error(context_error(not_logged_in), _)). + + + + /******************************* + * LOGIN * + *******************************/ + +%% login_form(+Request) +% +% HTTP handler that presents a form to login. + +login_form(_Request) :- + reply_html_page(cliopatria(default), + 'Login', + [ h1(align(center), 'Login'), + form([ action(location_by_id(user_login)), + method('POST') + ], + table([ tr([ th(align(right), 'User:'), + td(input([ name(user), + size(40) + ])) + ]), + tr([ th(align(right), 'Password:'), + td(input([ type(password), + name(password), + size(40) + ])) + ]), + tr([ td([ align(right), colspan(2) ], + input([ type(submit), + value('Login') + ])) + ]) + ]) + ) + ]). + +%% user_login(+Request) +% +% Handle =user= and =password=. If there is a parameter +% =return_to= or =|openid.return_to|=, reply using a redirect to +% the given URL. Otherwise display a welcome page. + +user_login(Request) :- !, + http_parameters(Request, + [ user(User), + password(Password), + 'openid.return_to'(ReturnTo, [optional(true)]), + 'return_to'(ReturnTo, [optional(true)]) + ], + [ attribute_declarations(attribute_decl) + ]), + ( var(ReturnTo) + -> Extra = [] + ; Extra = [ return_to(ReturnTo) ] + ), + reply_login([ user(User), + password(Password) + | Extra + ]). + + +reply_login(Options) :- + option(user(User), Options), + option(password(Password), Options), + validate_password(User, Password), !, + login(User), + ( option(return_to(ReturnTo), Options) + -> throw(http_reply(moved_temporary(ReturnTo))) + ; reply_html_page(cliopatria(default), + title('Login ok'), + h1(align(center), ['Welcome ', User])) + ). +reply_login(_) :- + reply_html_page(cliopatria(default), + title('Login failed'), + [ h1('Login failed'), + p(['Password incorrect']) + ]). + +%% user_logout(+Request) +% +% Logout the current user + +user_logout(_Request) :- + logged_on(User), !, + logout(User), + reply_html_page(cliopatria(default), + title('Logout'), + h1(align(center), ['Logged out ', User])). +user_logout(_Request) :- + reply_html_page(cliopatria(default), + title('Logout'), + [ h1(align(center), ['Not logged on']), + p(['Possibly you are logged out because the session ', + 'has timed out.']) + ]). + +%% attribute_decl(+Param, -DeclObtions) is semidet. +% +% Provide reusable parameter declarations for calls to +% http_parameters/3. + +attribute_decl(user, + [ description('User identifier-name'), + length > 1 + ]). +attribute_decl(realname, + [ description('Comment on user identifier-name') + ]). +attribute_decl(description, + [ optional(true), + description('Descriptive text') + ]). +attribute_decl(password, + [ description('Password') + ]). +attribute_decl(pwd1, + [ length > 5, + description('Password') + ]). +attribute_decl(pwd2, + [ length > 5, + description('Re-typed password') + ]). +attribute_decl(openid_server, + [ description('URL of an OpenID server') + ]). +attribute_decl(read, + [ description('Provide read-only access to the RDF store') + | Options]) :- bool(off, Options). +attribute_decl(write, + [ description('Provide write access to the RDF store') + | Options]) :- bool(off, Options). +attribute_decl(admin, + [ description('Provide administrative rights') + | Options]) :- bool(off, Options). + +bool(Def, + [ default(Def), + oneof([on, off]) + ]). + + + /******************************* + * OPENID ADMIN * + *******************************/ + +%% add_openid_server_form(+Request) +% +% Return an HTML page to add a new OpenID server. + +add_openid_server_form(_Request) :- + authorized(admin(add_openid_server)), + reply_html_page(cliopatria(default), + title('Add OpenID server'), + [ \new_openid_form + ]). + + +%% new_openid_form// is det. +% +% Present form to add a new OpenID provider. + +new_openid_form --> + html([ h1('Add new OpenID server'), + form([ action(location_by_id(add_openid_server)), + method('GET') + ], + table([ id('add-openid-server'), + class(form) + ], + [ \input(openid_server, 'Server homepage', []), + \input(openid_description, 'Server description', + []), + \permissions(-), + tr(class(buttons), + td([ colspan(2), + align(right) + ], + input([ type(submit), + value('Create') + ]))) + ])), + p([ 'Use this form to define access rights for users of an ', + a(href('http://www.openid.net'), 'OpenID'), ' server. ', + 'The special server ', code(*), ' specifies access for all OpenID servers. ', + 'Here are some examples of servers:' + ]), + ul([ li(code('http://myopenid.com')) + ]) + ]). + + +%% add_openid_server(+Request) +% +% Allow access from an OpenID server + +add_openid_server(Request) :- + authorized(admin(add_openid_server)), + http_parameters(Request, + [ openid_server(Server0, + [ description('URL of the server to allow')]), + openid_description(Description, + [ optional(true), + description('Description of the server') + ]), + read(Read), + write(Write) + ], + [ attribute_declarations(attribute_decl) + ]), + phrase(allow(Read, Write, off), Allow), + canonical_url(Server0, Server), + Options = [ description(Description), + allow(Allow) + ], + remove_optional(Options, Properties), + openid_add_server(Server, Properties), + list_users(Request). + +remove_optional([], []). +remove_optional([H|T0], [H|T]) :- + arg(1, H, A), + nonvar(A), !, + remove_optional(T0, T). +remove_optional([_|T0], T) :- + remove_optional(T0, T). + + +canonical_url(Var, Var) :- + var(Var), !. +canonical_url(*, *) :- !. +canonical_url(URL0, URL) :- + parse_url(URL0, Parts), + parse_url(URL, Parts). + + +%% edit_openid_server_form(+Request) +% +% Form to edit user properties + +edit_openid_server_form(Request) :- + authorized(admin(openid(edit))), + http_parameters(Request, + [ openid_server(Server) + ], + [ attribute_declarations(attribute_decl) + ]), + + reply_html_page(cliopatria(default), + title('Edit OpenID server'), + \edit_openid_server_form(Server)). + +edit_openid_server_form(Server) --> + html([ h1(['Edit OpenID server ', Server]), + + form([ action(location_by_id(edit_openid_server)), + method('GET') + ], + [ \hidden(openid_server, Server), + table([ class(form) + ], + [ \openid_property(Server, description, 'Description', []), + \permissions(Server), + tr(class(buttons), + td([ colspan(2), + align(right) + ], + input([ type(submit), + value('Modify') + ]))) + ]) + ]), + + p(\action(location_by_id(del_openid_server) + + '?openid_server=' + encode(Server), + [ 'Delete ', b(Server) ])) + ]). + + +openid_property(Server, Name, Label, Options) --> + { Term =.. [Name, Value], + openid_server_property(Server, Term) + -> O2 = [value(Value)|Options] + ; O2 = Options + }, + html(tr([ th(align(right), Label), + td(input([name(Name),size(40)|O2])) + ])). + + +%% openid_server_table(+Options)// +% +% List registered openid servers + +openid_server_table(Options) --> + { setof(S, openid_current_server(S), Servers), ! + }, + html([ table([ class(block) + ], + [ tr([ th('Server'), + th('Description') + ]) + | \openid_list_servers(Servers, Options) + ]) + ]). +openid_server_table(_) --> + []. + +openid_list_servers([], _) --> + []. +openid_list_servers([H|T], Options) --> + openid_list_server(H, Options), + openid_list_servers(T, Options). + +openid_list_server(Server, Options) --> + html(tr([td(\openid_server(Server)), + td(\openid_field(Server, description)), + \edit_openid_button(Server, Options) + ])). + +edit_openid_button(Server, Options) --> + { option(edit(true), Options) }, !, + html(td(a(href(location_by_id(edit_openid_server_form) + + '?openid_server='+encode(Server) + ), 'Edit'))). +edit_openid_button(_, _) --> []. + + + +openid_server(*) --> !, + html(*). +openid_server(Server) --> + html(a(href(Server), Server)). + +openid_field(Server, Field) --> + { Term =.. [Field, Value], + openid_server_property(Server, Term) + }, !, + html(Value). +openid_field(_, _) --> + []. + + +%% edit_openid_server(Request) +% +% Handle reply from OpenID server form. + +edit_openid_server(Request) :- + authorized(admin(openid(edit))), + http_parameters(Request, + [ openid_server(Server), + description(Description), + read(Read), + write(Write), + admin(Admin) + ], + [ attribute_declarations(attribute_decl) + ]), + modify_openid(Server, description(Description)), + openid_modify_permissions(Server, Read, Write, Admin), + list_users(Request). + + +modify_openid(User, Property) :- + Property =.. [_Name|Value], + ( ( var(Value) + ; Value == '' + ) + -> true + ; openid_set_property(User, Property) + ). + + +openid_modify_permissions(Server, Read, Write, Admin) :- + phrase(allow(Read, Write, Admin), Allow), + openid_set_property(Server, allow(Allow)). + + +%% del_openid_server(+Request) +% +% Delete an OpenID Server + +del_openid_server(Request) :- !, + authorized(admin(openid(delete))), + http_parameters(Request, + [ openid_server(Server) + ], + [ attribute_declarations(attribute_decl) + ]), + openid_del_server(Server), + list_users(Request). + + + /******************************* + * SETTINGS * + *******************************/ + +%% settings(+Request) +% +% Show current settings. If user has administrative rights, allow +% editing the settings. + +settings(_Request) :- + ( catch(authorized(admin(edit_settings)), _, fail) + -> Edit = true + ; authorized(read(admin, settings)), + Edit = false + ), + reply_html_page(cliopatria(default), + title('Settings'), + [ h1('Application settings'), + \http_show_settings([ edit(Edit), + hide_module(false), + action('save_settings') + ]), + \warn_no_edit(Edit) + ]). + +warn_no_edit(true) --> !. +warn_no_edit(_) --> + html(p(id(settings_no_edit), + [ a(href(location_by_id(login_form)), 'Login'), + ' as ', code(admin), ' to edit the settings.' ])). + +%% save_settings(+Request) +% +% Save modified settings. + +save_settings(Request) :- + authorized(admin(edit_settings)), + reply_html_page(cliopatria(default), + title('Save settings'), + \http_apply_settings(Request, [save(true)])). + + + /******************************* + * EMIT * + *******************************/ + +%% hidden(+Name, +Value) +% +% Create a hidden input field with given name and value + +hidden(Name, Value) --> + html(input([ type(hidden), + name(Name), + value(Value) + ])). + +action(URL, Label) --> + html([a([href(URL)], Label), br([])]). From bca9716fc64c41583a6aeb88df26ecf9246e4984 Mon Sep 17 00:00:00 2001 From: Arfon Smith Date: Thu, 4 Sep 2014 13:53:36 -0500 Subject: [PATCH 2/2] Another sample file --- lib/linguist/samples.json | 28 +++++++++++++++++----------- samples/Prolog/ex6.pl | 5 +++++ 2 files changed, 22 insertions(+), 11 deletions(-) create mode 100644 samples/Prolog/ex6.pl diff --git a/lib/linguist/samples.json b/lib/linguist/samples.json index 273c5360..81464828 100644 --- a/lib/linguist/samples.json +++ b/lib/linguist/samples.json @@ -848,8 +848,8 @@ "exception.zep.php" ] }, - "tokens_total": 659103, - "languages_total": 903, + "tokens_total": 659134, + "languages_total": 904, "tokens": { "ABAP": { "*/**": 1, @@ -55927,15 +55927,15 @@ "TWO_PI": 1 }, "Prolog": { - "-": 348, + "-": 350, "module": 4, - "(": 1156, + "(": 1161, "cpa_admin": 1, "[": 290, "change_password_form//1": 1, "]": 288, - ")": 1153, - ".": 230, + ")": 1158, + ".": 232, "use_module": 20, "user": 45, "user_db": 1, @@ -55973,7 +55973,7 @@ "user_logout": 4, "settings": 4, "save_settings": 3, - "%": 193, + "%": 194, "+": 47, "Request": 46, "HTTP": 4, @@ -56326,6 +56326,13 @@ "save": 1, "with": 3, "br": 1, + "subset": 2, + "Set": 4, + "Subset": 6, + "append": 3, + "L1": 1, + "powerset": 1, + "bagof": 1, "format_spec": 12, "format_error/2": 1, "format_spec/2": 1, @@ -56562,7 +56569,6 @@ "Goals": 2, "Tmp": 3, "instantiation_error": 1, - "append": 2, "NewArgs": 2, "variant_sha1": 1, "Sha": 2, @@ -73110,7 +73116,7 @@ "PostScript": 107, "PowerShell": 12, "Processing": 74, - "Prolog": 6885, + "Prolog": 6916, "Propeller Spin": 13519, "Protocol Buffer": 63, "PureScript": 1652, @@ -73324,7 +73330,7 @@ "PostScript": 1, "PowerShell": 2, "Processing": 1, - "Prolog": 6, + "Prolog": 7, "Propeller Spin": 10, "Protocol Buffer": 1, "PureScript": 4, @@ -73391,5 +73397,5 @@ "fish": 3, "wisp": 1 }, - "md5": "1500ca2d5506e7d4e02f8c1d14e348a4" + "md5": "50b2227d023291a6a909ca3866c171c8" } \ No newline at end of file diff --git a/samples/Prolog/ex6.pl b/samples/Prolog/ex6.pl new file mode 100644 index 00000000..0b1b74eb --- /dev/null +++ b/samples/Prolog/ex6.pl @@ -0,0 +1,5 @@ +%6.8 +subset(Set, Subset) :- + append(L1, Subset, Set). +powerset(Set, Subset) :- + bagof(Subset, subset(Set, Subset), Subset).