# Path: tripoli/util.py
# class PlaceOrSymbol:
#     """A generic class for wrapping an Emacs value that can either be tied to a
#     symbol (representing that symbol's value binding) or, otherwise, any other
#     Emacs value.
# 
#     This is useful in certain cases. For example, an Emacs list technically
#     only a cons cell, but certain mutable operations (deletion, for example)
#     may be impossible to perform in-place without reassigning the head of the
#     list. That is why functions like Emacs' *delete* both mutates a list *and*
#     returns the new head cons cell, and why the Emacs manual recommends
#     expressions such as
# 
#     .. code:: lisp
# 
#        (setq foo (delete element foo))
# 
#     to correctly perform deletion.
# 
#     :param place: The place to track. May be a symbol, an Emacs namespace
#         object or a string (all interpreted as symbols), or any other Emacs
#         object or *None*.
#     """
#     def __init__(self, place=None):
#         if place is None:
#             self._place = intern('nil')
#         elif isinstance(place, EmacsNamespace):
#             self._symbol = place[bound(exists=False)]
#         elif isinstance(place, str):
#             self._symbol = intern(place)
#         elif not isinstance(place, EmacsObject):
#             raise TypeError('Invalid place')
#         elif not symbolp(place):
#             self._place = place
#         else:
#             self._symbol = place
# 
#     def __emacs__(self, prefer_symbol=False):
#         return self.place
# 
#     def __bool__(self):
#         return bool(self.place)
# 
#     @property
#     def place(self):
#         """Return the actual Emacs object being tracked. If tracking a symbol,
#         returns that symbol's value binding.
#         """
#         if hasattr(self, '_place'):
#             return self._place
#         return _symbol_value(self._symbol)
# 
#     @coerce()
#     def _bind(self, value):
#         """Rebind to a new object. If tracking a symbol, update that symbol's
#         value binding.
#         """
#         if hasattr(self, '_place'):
#             self._place = value
#         else:
#             _setq(self._symbol, value)


from tripoli.util import PlaceOrSymbol
import emacs_raw as er



def test_place():
    obj = PlaceOrSymbol()

    assert er.eq(obj.place, er.intern('nil'))
    assert er.eq(er.EmacsObject(obj), er.intern('nil'))

    new_place = er.list([er.int(1), er.int(2), er.int(3)])
    obj._bind(new_place)

    assert er.eq(obj.place, new_place)
    assert er.eq(er.EmacsObject(obj), new_place)


def test_symbol():
    mylist = er.list([er.int(1), er.int(2), er.int(3)])

    sym = er.intern('alpha')
    setq = er.intern('set')
    setq(sym, mylist)


# Path: tripoli/util.py
# class PlaceOrSymbol:
#     """A generic class for wrapping an Emacs value that can either be tied to a
#     symbol (representing that symbol's value binding) or, otherwise, any other
#     Emacs value.
# 
#     This is useful in certain cases. For example, an Emacs list technically
#     only a cons cell, but certain mutable operations (deletion, for example)
#     may be impossible to perform in-place without reassigning the head of the
#     list. That is why functions like Emacs' *delete* both mutates a list *and*
#     returns the new head cons cell, and why the Emacs manual recommends
#     expressions such as
# 
#     .. code:: lisp
# 
#        (setq foo (delete element foo))
# 
#     to correctly perform deletion.
# 
#     :param place: The place to track. May be a symbol, an Emacs namespace
#         object or a string (all interpreted as symbols), or any other Emacs
#         object or *None*.
#     """
#     def __init__(self, place=None):
#         if place is None:
#             self._place = intern('nil')
#         elif isinstance(place, EmacsNamespace):
#             self._symbol = place[bound(exists=False)]
#         elif isinstance(place, str):
#             self._symbol = intern(place)
#         elif not isinstance(place, EmacsObject):
#             raise TypeError('Invalid place')
#         elif not symbolp(place):
#             self._place = place
#         else:
#             self._symbol = place
# 
#     def __emacs__(self, prefer_symbol=False):
#         return self.place
# 
#     def __bool__(self):
#         return bool(self.place)
# 
#     @property
#     def place(self):
#         """Return the actual Emacs object being tracked. If tracking a symbol,
#         returns that symbol's value binding.
#         """
#         if hasattr(self, '_place'):
#             return self._place
#         return _symbol_value(self._symbol)
# 
#     @coerce()
#     def _bind(self, value):
#         """Rebind to a new object. If tracking a symbol, update that symbol's
#         value binding.
#         """
#         if hasattr(self, '_place'):
#             self._place = value
#         else:
#             _setq(self._symbol, value)


# Path: tripoli_tests/test_place_or_symbol.py
from tripoli.util import PlaceOrSymbol
import emacs_raw as er




def test_place():
    obj = PlaceOrSymbol()

    assert er.eq(obj.place, er.intern('nil'))
    assert er.eq(er.EmacsObject(obj), er.intern('nil'))

    new_place = er.list([er.int(1), er.int(2), er.int(3)])
    obj._bind(new_place)

    assert er.eq(obj.place, new_place)
    assert er.eq(er.EmacsObject(obj), new_place)


def test_symbol():
    mylist = er.list([er.int(1), er.int(2), er.int(3)])

    sym = er.intern('alpha')
    setq = er.intern('set')
    setq(sym, mylist)


    obj = PlaceOrSymbol(sym)