All these operations are very natural for buffer objects as well as
  strings, which leads me to the conclusion we should provide two
  flavours for each function, for buffers and for strings.  The way
  emacs does it is by specifying an object argument.  I find this
  suboptimal, but it is also possible solution (and would reduce the
  number of functions in half).  Note that there are also different
  indexing conventions, see the Question below.
All functions come in buffer and string flavours.  The “current
  position” is called point in buffer versions and offset in string
  versions.  In fact, buffer implementation is the “default” one, the
  wrapper for strings is added like so
(with-temp-buffer
  (insert string)
  (goto-char (point-min))
  (call-buffer-flavour-of-function))Insertion into buffers is very fast so there is virtually no performance hit.
Question: should be number everything from 0, from 1, or should we adhere to the “convention” in emacs (strings from 0, buffers from 1).
All range functions come with optional arguments beg and
  end.  Since we most of the time want to operate on the entire
  string/buffer, these are put to the end to not bother us.
Naming conventions:
- The suffix -p indicates a predicate. Functions marked so should have no side effects.
- The suffix -at indicates the function takes a point, or defaults to position under cursor.
- The suffix -with or -where indicates that we take name of a property. We use two suffices to make the name more natural in english.
- The suffix -value indicates that we also take a value of the property and only operate on regions where property’s value match this.
- The suffix -by indicates that we also take a predicate and only operate on regions where property’s value satisfies this.
- [ ] s-property-at prop&optionalpoint- Return value of property propatpoint.
 
- Return value of property 
- [ ] s-properties-at &optional point# text-properties-at- Return a plist of properties at point.
 
- Return a plist of properties at 
- [ ] s-property-at-p prop&optionalpoint- Return non-nil if propis set atpoint.
 
- Return non-nil if 
- [ ] s-properties-at-p props&optionalpoint- Return non-nil if any property from propsis set atpoint.
 
- Return non-nil if any property from 
- [ ] s-property-value-at-p
- [ ] s-properties-value-at-p
- [ ] s-property-by-at-p
- [ ] s-properties-by-at-p
- [ ] s-get-regions-with-property prop&optionalbegend# message-text-with-property, gnus-find-text-property-region- Return list of (beg . end)values describing regions wherepropis set.
 
- Return list of 
- [ ] s-get-regions-with-property-value
- [ ] s-get-regions-with-property-by
- [ ] s-alter-property propfn&optionalbegend# alter-text-property- Replace text property propwith result of callingfnon this property.fntakes two arguments:propand its value.
 
- Replace text property 
- [ ] s-alter-property-value
- [ ] s-alter-property-by
- [ ] s-map-regions-with-property propfn&optionalbegend# this can be used to implement s-alter-property- Replace all regions having propwith results of callingfnon these regions.
 
- Replace all regions having 
- [ ] s-map-regions-with-property-value
- [ ] s-map-regions-with-property-by
- [ ] s-add-property propvalue&optionalbegend- Add propwithvalue.
 
- Add 
- [ ] s-add-properties props&optionalbegend- Add props.propsis a plist of property/value pairs.
 
- Add 
- [ ] s-add-property-at propvalue&optionalpoint- Add propwithvalueatpoint.
 
- Add 
- [ ] s-add-properties-at props&optionalpoint- Add propsatpoint.propsis a plist of property/value pairs.
 
- Add 
- [ ] s-add-property-where propnew-propval&optionalbegend# gnus-add-text-properties-when- Add new-propwithvalto all regions wherepropis set.
 
- Add 
- [ ] s-add-property-where-value
- [ ] s-add-property-where-by
- [ ] s-add-properties-where propprops&optionalbegend- Add propsto all regions wherepropis set.propsis a plist of property/value pairs.
 
- Add 
- [ ] s-add-properties-where-value
- [ ] s-add-properties-where-by
- [ ] do we also want -set- flavours here?
    - It is the same as doing -remove- and then corresponding -add-
 
- [ ] s-remove-property old-prop&optionalbegend
- [ ] s-remove-property-where propold-prop&optionalbegend# gnus-remove-text-properties-when- Remove old-propfrom all regions wherepropis set.
 
- Remove 
- [ ] s-remove-property-where-value
- [ ] s-remove-property-where-by
- [ ] s-remove-properties props&optionalbegend- Remove props.
 
- Remove 
- [ ] s-remove-properties-where propprops&optionalbegend- Remove propsfrom all regions wherepropis set.
 
- Remove 
- [ ] s-remove-properties-where-value
- [ ] s-remove-properties-where-by
- [ ] s-strip-properties &optional begend- Remove all properties.
 
- [ ] s-has-property prop&optionalbegend- Return the first position where propis set or nil if it is never set.
 
- Return the first position where 
- [ ] s-has-property-p prop&optionalbegend- Return non-nil if propis set anywhere betweenbegandendor nil if it is never set.
 
- Return non-nil if 
- [ ] s-has-property-value
- [ ] s-has-property-value-p
- [ ] s-has-property-by
- [ ] s-has-property-by-p
- [ ] s-lacks-property prop&optionalbegend- Return the first position where propis not set or nil if it is always set.
 
- Return the first position where 
- [ ] s-lacks-property-p prop&optionalbegend- Return non-nil if propis not set somewhere or nil if it is always set.
 
- Return non-nil if 
- [ ] s-lacks-property-value
- [ ] s-lacks-property-value-p
- [ ] s-lacks-property-by
- [ ] s-lacks-property-by-p
- [ ] s-find-property prop&optionalpointlimit- Return the first non-nil value of propafterpointor nil if it is never set.
 
- Return the first non-nil value of 
- [ ] s-find-property-backward prop&optionalpointlimit- Return the first non-nil value of propbeforepointor nil if it is never set.
 
- Return the first non-nil value of 
- [ ] s-next-property-change &optional pointlimit- Return the position of next property change or nil if none occurs.
 
- [ ] s-previous-property-change &optional pointlimit- Return the position of previous property change or nil if none occurs.
 
- [ ] s-next-property-change-where prop&optionalpointlimit
- [ ] s-previous-property-change-where
- [ ] s-next-property-change-where-value
- [ ] s-previous-property-change-where-value
- [ ] s-next-property-change-where-by
- [ ] s-previous-property-change-where-by
- [ ] s-equal-including-properties-p
    - Return non-nil if two strings are equal, including properties.
 
More exotic properties we can implement later
- font-lock-fillin-text-property
- gnus-put-text-property-excluding-characters-with-faces ;; put property everywhere except on blocks with property (and value)
- font-lock-prepend-text-property ;; add more general ‘map property’
- font-lock-append-text-property
- circe-highlight-extend-properties ;; this can also be implemented using a map