<commit_before>(ns workflo.macros.view
  (:require [clojure.string :as str]
            [workflo.macros.props :as p]
            [workflo.macros.util.string :refer [camel->kebab]]))

;;;; Om Next query generation

(def fn-specs
  "Function specifications for all functions that are not Object
   instance functions taking [this] as the sole argument."
  '{query-params [:static   (static om.next/IQueryParams) [this]]
    query        [:static   (static om.next/IQuery)       [this]]
    ident        [:instance (static om.next/Ident)        [this props]]
    keyfn        [:factory  nil                           [props]]
    validator    [:factory  nil                           [props]]})

(def fn-aliases
  "A few aliases allowing to define view functions with shorter or
   more logicial names."
  '{key      keyfn
    validate validator})

(defn fn-scope
  "Return the scope (:static, :instance, :props) for a view function."
  [[name & args-and-body]]
  (let [[scope _ _] (fn-specs name)]
    (or scope :instance)))

(defn fn-protocol
  "Return the scope (e.g. (static om.next/IQuery) for a view function."
  [[name & args-and-body]]
  (let [[_ protocol _ :as fn-spec] (fn-specs name)]
    (if fn-spec protocol '(Object))))

(defn fn-args
  "Return the arguments (e.g. [this]) for a view function."
  [[name & args-and-body]]
  (let [[_ _ args] (fn-specs name)]
    (or args '[this])))

(defn fn-alias
  "Return the alias for a view function or the name of the
   function itself if no alias is defined."
  [[name & _]]
  (or (fn-aliases name) name))

(defn resolve-fn-alias
  "Resolve the function alias for a view function."
  [[name & body :as f]]
  (let [alias (fn-alias f)]
    `(~alias ~@body)))

(defn generate-ident-fn
  "Generate a (ident ...) function from the props spec."
  [props]
  (list 'ident '[:db/id id]))

(defn generate-key-fn
  "Generate a (key ...) function from the props spec."
  [props]
  (list 'key 'id))

(defn generate-query-fn
  "Generate a (query ...) function from the props spec."
  [props]
  (list 'query (p/om-query props)))

(defn maybe-generate-ident-fn
  "If the props spec includes a :db/id property, an (ident ...)
   function is automatically generated based on this ID."
  [props fns]
  (cond-> fns
    (some #{'db/id} (map :name props))
    (conj (generate-ident-fn props))))

(defn maybe-generate-key-fn
  "If the props spec includes a :db/id property, a (key ...)
   function is automatically generated based on this ID."
  [props fns]
  (cond-> fns
    (some #{'db/id} (map :name props))
    (conj (generate-key-fn props))))

(defn maybe-generate-query-fn
  "If (query ...) is missing from fns, it is generated automatically
   from the props spec."
  [props fns]
  (cond-> fns
    (not (some #{'query} (map first fns)))
    (conj (generate-query-fn props))))

(defn raw-fn?
  "Returns true if f is a raw function, that is if its name
   starts with a ., indicating that its function signature
   should be left alone."
 [[name & body :as f]]
 (str/starts-with? (str name) "."))

(defn inject-fn-args
  "Inject a function argument binding vector into f if it doesn't
   already have one."
  [[name & body :as f]]
  (let [args (fn-args f)]
    (if args
      `(~name ~args ~@body)
      `(~name [~'this] ~@body))))

(defn maybe-inject-fn-args
  "Inject a function argument binding vector into f unless it
   is a raw function that is assumed to define its own arguments."
  [[name & body :as f]]
  (cond-> f<commit_msg>Only generate keyfn/ident if they are not defined by the user<commit_after>(ns workflo.macros.view
  (:require [clojure.string :as str]
            [workflo.macros.props :as p]
            [workflo.macros.util.string :refer [camel->kebab]]))

;;;; Om Next query generation

(def fn-specs
  "Function specifications for all functions that are not Object
   instance functions taking [this] as the sole argument."
  '{query-params [:static   (static om.next/IQueryParams) [this]]
    query        [:static   (static om.next/IQuery)       [this]]
    ident        [:instance (static om.next/Ident)        [this props]]
    keyfn        [:factory  nil                           [props]]
    validator    [:factory  nil                           [props]]})

(def fn-aliases
  "A few aliases allowing to define view functions with shorter or
   more logicial names."
  '{key      keyfn
    validate validator})

(defn fn-scope
  "Return the scope (:static, :instance, :props) for a view function."
  [[name & args-and-body]]
  (let [[scope _ _] (fn-specs name)]
    (or scope :instance)))

(defn fn-protocol
  "Return the scope (e.g. (static om.next/IQuery) for a view function."
  [[name & args-and-body]]
  (let [[_ protocol _ :as fn-spec] (fn-specs name)]
    (if fn-spec protocol '(Object))))

(defn fn-args
  "Return the arguments (e.g. [this]) for a view function."
  [[name & args-and-body]]
  (let [[_ _ args] (fn-specs name)]
    (or args '[this])))

(defn fn-alias
  "Return the alias for a view function or the name of the
   function itself if no alias is defined."
  [[name & _]]
  (or (fn-aliases name) name))

(defn resolve-fn-alias
  "Resolve the function alias for a view function."
  [[name & body :as f]]
  (let [alias (fn-alias f)]
    `(~alias ~@body)))

(defn generate-ident-fn
  "Generate a (ident ...) function from the props spec."
  [props]
  (list 'ident '[:db/id id]))

(defn generate-key-fn
  "Generate a (key ...) function from the props spec."
  [props]
  (list 'key 'id))

(defn generate-query-fn
  "Generate a (query ...) function from the props spec."
  [props]
  (list 'query (p/om-query props)))

(defn maybe-generate-ident-fn
  "If the props spec includes a :db/id property, an (ident ...)
   function is automatically generated based on this ID."
  [props fns]
  (cond-> fns
    (and (some #{'db/id} (map :name props))
         (not (some #{'ident} (map first fns))))
    (conj (generate-ident-fn props))))

(defn maybe-generate-key-fn
  "If the props spec includes a :db/id property, a (key ...)
   function is automatically generated based on this ID."
  [props fns]
  (cond-> fns
    (and (some #{'db/id} (map :name props))
         (not (some #{'keyfn 'key} (map first fns))))
    (conj (generate-key-fn props))))

(defn maybe-generate-query-fn
  "If (query ...) is missing from fns, it is generated automatically
   from the props spec."
  [props fns]
  (cond-> fns
    (not (some #{'query} (map first fns)))
    (conj (generate-query-fn props))))

(defn raw-fn?
  "Returns true if f is a raw function, that is if its name
   starts with a ., indicating that its function signature
   should be left alone."
 [[name & body :as f]]
 (str/starts-with? (str name) "."))

(defn inject-fn-args
  "Inject a function argument binding vector into f if it doesn't
   already have one."
  [[name & body :as f]]
  (let [args (fn-args f)]
    (if args
      `(~name ~args ~@body)
      `(~name [~'this] ~@body))))

(defn maybe-inject-fn-args
  "Inject a function argument binding vector into f unless it
   is a raw function that is assumed to define its own arguments."
  [[name & body :as f]]
  (cond-> f
{'fraction_non_alphanumeric': 0.14167018729756373, 'fraction_numerical': 0.0, 'mean_word_length': 2.8285714285714287, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 13, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4130309', 'n_tokens_mistral': 2357, 'n_tokens_neox': 2330, 'n_words': 870}