diff --git a/.gitignore b/.gitignore
index eb60e6d..037b50c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,33 +1,12 @@
doc/build/
-env
.cask/*
-Cask.tmp
-index_error.py
-redirecting_server.py
-wiener_filtering.py
-UTF-8-demo.txt
-.gitmodules
-*.stackdump
-*.elc
-*.el#
-*.el~
-lisp/ein-autoloads.el
-*.py~
-*.org~
*.pyc
-*.ipynb~
-Makefile~
-*.ipynb_checkpoints*
-*.png
-tests/notebook
-*.log
log/*
-_images
-_static
-.travis.yml.swp
*.zip
.gitattributes
.ecukes*
dist
-.*ein*.ipynb
+.*ein*ipynb
.Rhistory
+.ipynb_checkpoints
+ein-autoloads.el
diff --git a/.travis.yml b/.travis.yml
index 963b0e5..0ee0c0c 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -38,8 +38,6 @@ matrix:
include:
- os: linux
env: EMACS_CI=emacs-25-1 IPYTHON=5.8.0 PY=python PIP="${PY} -m pip install --user"
- - os: linux
- env: EMACS_CI=emacs-26-1 IPYTHON=6.5.0 PY=python3 PIP="${PY} -m pip install --user"
- os: linux
env: EMACS_CI=emacs-26-3 IPYTHON=7.5.0 PY=python3 PIP="${PY} -m pip install --user"
- os: osx
@@ -56,7 +54,7 @@ install:
pyenv activate $TOXENV ;
fi
- ${PIP} --upgrade pip
- - ${PIP} wheel jupyter ipython\<=$IPYTHON jedi\>=0.15.1 ipykernel numpy\<=1.16.0 matplotlib\<=3.0.2
+ - ${PIP} wheel jupyter ipython\<=$IPYTHON ipykernel numpy\<=1.16.0 matplotlib\<=3.0.2
- ${PY} -m ipykernel install --user
- sh tools/install-R.sh
- sh tools/install-julia.sh
diff --git a/COPYING b/COPYING
deleted file mode 100644
index 94a9ed0..0000000
--- a/COPYING
+++ /dev/null
@@ -1,674 +0,0 @@
- GNU GENERAL PUBLIC LICENSE
- Version 3, 29 June 2007
-
- Copyright (C) 2007 Free Software Foundation, Inc.
- Everyone is permitted to copy and distribute verbatim copies
- of this license document, but changing it is not allowed.
-
- Preamble
-
- The GNU General Public License is a free, copyleft license for
-software and other kinds of works.
-
- The licenses for most software and other practical works are designed
-to take away your freedom to share and change the works. By contrast,
-the GNU General Public License is intended to guarantee your freedom to
-share and change all versions of a program--to make sure it remains free
-software for all its users. We, the Free Software Foundation, use the
-GNU General Public License for most of our software; it applies also to
-any other work released this way by its authors. You can apply it to
-your programs, too.
-
- When we speak of free software, we are referring to freedom, not
-price. Our General Public Licenses are designed to make sure that you
-have the freedom to distribute copies of free software (and charge for
-them if you wish), that you receive source code or can get it if you
-want it, that you can change the software or use pieces of it in new
-free programs, and that you know you can do these things.
-
- To protect your rights, we need to prevent others from denying you
-these rights or asking you to surrender the rights. Therefore, you have
-certain responsibilities if you distribute copies of the software, or if
-you modify it: responsibilities to respect the freedom of others.
-
- For example, if you distribute copies of such a program, whether
-gratis or for a fee, you must pass on to the recipients the same
-freedoms that you received. You must make sure that they, too, receive
-or can get the source code. And you must show them these terms so they
-know their rights.
-
- Developers that use the GNU GPL protect your rights with two steps:
-(1) assert copyright on the software, and (2) offer you this License
-giving you legal permission to copy, distribute and/or modify it.
-
- For the developers' and authors' protection, the GPL clearly explains
-that there is no warranty for this free software. For both users' and
-authors' sake, the GPL requires that modified versions be marked as
-changed, so that their problems will not be attributed erroneously to
-authors of previous versions.
-
- Some devices are designed to deny users access to install or run
-modified versions of the software inside them, although the manufacturer
-can do so. This is fundamentally incompatible with the aim of
-protecting users' freedom to change the software. The systematic
-pattern of such abuse occurs in the area of products for individuals to
-use, which is precisely where it is most unacceptable. Therefore, we
-have designed this version of the GPL to prohibit the practice for those
-products. If such problems arise substantially in other domains, we
-stand ready to extend this provision to those domains in future versions
-of the GPL, as needed to protect the freedom of users.
-
- Finally, every program is threatened constantly by software patents.
-States should not allow patents to restrict development and use of
-software on general-purpose computers, but in those that do, we wish to
-avoid the special danger that patents applied to a free program could
-make it effectively proprietary. To prevent this, the GPL assures that
-patents cannot be used to render the program non-free.
-
- The precise terms and conditions for copying, distribution and
-modification follow.
-
- TERMS AND CONDITIONS
-
- 0. Definitions.
-
- "This License" refers to version 3 of the GNU General Public License.
-
- "Copyright" also means copyright-like laws that apply to other kinds of
-works, such as semiconductor masks.
-
- "The Program" refers to any copyrightable work licensed under this
-License. Each licensee is addressed as "you". "Licensees" and
-"recipients" may be individuals or organizations.
-
- To "modify" a work means to copy from or adapt all or part of the work
-in a fashion requiring copyright permission, other than the making of an
-exact copy. The resulting work is called a "modified version" of the
-earlier work or a work "based on" the earlier work.
-
- A "covered work" means either the unmodified Program or a work based
-on the Program.
-
- To "propagate" a work means to do anything with it that, without
-permission, would make you directly or secondarily liable for
-infringement under applicable copyright law, except executing it on a
-computer or modifying a private copy. Propagation includes copying,
-distribution (with or without modification), making available to the
-public, and in some countries other activities as well.
-
- To "convey" a work means any kind of propagation that enables other
-parties to make or receive copies. Mere interaction with a user through
-a computer network, with no transfer of a copy, is not conveying.
-
- An interactive user interface displays "Appropriate Legal Notices"
-to the extent that it includes a convenient and prominently visible
-feature that (1) displays an appropriate copyright notice, and (2)
-tells the user that there is no warranty for the work (except to the
-extent that warranties are provided), that licensees may convey the
-work under this License, and how to view a copy of this License. If
-the interface presents a list of user commands or options, such as a
-menu, a prominent item in the list meets this criterion.
-
- 1. Source Code.
-
- The "source code" for a work means the preferred form of the work
-for making modifications to it. "Object code" means any non-source
-form of a work.
-
- A "Standard Interface" means an interface that either is an official
-standard defined by a recognized standards body, or, in the case of
-interfaces specified for a particular programming language, one that
-is widely used among developers working in that language.
-
- The "System Libraries" of an executable work include anything, other
-than the work as a whole, that (a) is included in the normal form of
-packaging a Major Component, but which is not part of that Major
-Component, and (b) serves only to enable use of the work with that
-Major Component, or to implement a Standard Interface for which an
-implementation is available to the public in source code form. A
-"Major Component", in this context, means a major essential component
-(kernel, window system, and so on) of the specific operating system
-(if any) on which the executable work runs, or a compiler used to
-produce the work, or an object code interpreter used to run it.
-
- The "Corresponding Source" for a work in object code form means all
-the source code needed to generate, install, and (for an executable
-work) run the object code and to modify the work, including scripts to
-control those activities. However, it does not include the work's
-System Libraries, or general-purpose tools or generally available free
-programs which are used unmodified in performing those activities but
-which are not part of the work. For example, Corresponding Source
-includes interface definition files associated with source files for
-the work, and the source code for shared libraries and dynamically
-linked subprograms that the work is specifically designed to require,
-such as by intimate data communication or control flow between those
-subprograms and other parts of the work.
-
- The Corresponding Source need not include anything that users
-can regenerate automatically from other parts of the Corresponding
-Source.
-
- The Corresponding Source for a work in source code form is that
-same work.
-
- 2. Basic Permissions.
-
- All rights granted under this License are granted for the term of
-copyright on the Program, and are irrevocable provided the stated
-conditions are met. This License explicitly affirms your unlimited
-permission to run the unmodified Program. The output from running a
-covered work is covered by this License only if the output, given its
-content, constitutes a covered work. This License acknowledges your
-rights of fair use or other equivalent, as provided by copyright law.
-
- You may make, run and propagate covered works that you do not
-convey, without conditions so long as your license otherwise remains
-in force. You may convey covered works to others for the sole purpose
-of having them make modifications exclusively for you, or provide you
-with facilities for running those works, provided that you comply with
-the terms of this License in conveying all material for which you do
-not control copyright. Those thus making or running the covered works
-for you must do so exclusively on your behalf, under your direction
-and control, on terms that prohibit them from making any copies of
-your copyrighted material outside their relationship with you.
-
- Conveying under any other circumstances is permitted solely under
-the conditions stated below. Sublicensing is not allowed; section 10
-makes it unnecessary.
-
- 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
-
- No covered work shall be deemed part of an effective technological
-measure under any applicable law fulfilling obligations under article
-11 of the WIPO copyright treaty adopted on 20 December 1996, or
-similar laws prohibiting or restricting circumvention of such
-measures.
-
- When you convey a covered work, you waive any legal power to forbid
-circumvention of technological measures to the extent such circumvention
-is effected by exercising rights under this License with respect to
-the covered work, and you disclaim any intention to limit operation or
-modification of the work as a means of enforcing, against the work's
-users, your or third parties' legal rights to forbid circumvention of
-technological measures.
-
- 4. Conveying Verbatim Copies.
-
- You may convey verbatim copies of the Program's source code as you
-receive it, in any medium, provided that you conspicuously and
-appropriately publish on each copy an appropriate copyright notice;
-keep intact all notices stating that this License and any
-non-permissive terms added in accord with section 7 apply to the code;
-keep intact all notices of the absence of any warranty; and give all
-recipients a copy of this License along with the Program.
-
- You may charge any price or no price for each copy that you convey,
-and you may offer support or warranty protection for a fee.
-
- 5. Conveying Modified Source Versions.
-
- You may convey a work based on the Program, or the modifications to
-produce it from the Program, in the form of source code under the
-terms of section 4, provided that you also meet all of these conditions:
-
- a) The work must carry prominent notices stating that you modified
- it, and giving a relevant date.
-
- b) The work must carry prominent notices stating that it is
- released under this License and any conditions added under section
- 7. This requirement modifies the requirement in section 4 to
- "keep intact all notices".
-
- c) You must license the entire work, as a whole, under this
- License to anyone who comes into possession of a copy. This
- License will therefore apply, along with any applicable section 7
- additional terms, to the whole of the work, and all its parts,
- regardless of how they are packaged. This License gives no
- permission to license the work in any other way, but it does not
- invalidate such permission if you have separately received it.
-
- d) If the work has interactive user interfaces, each must display
- Appropriate Legal Notices; however, if the Program has interactive
- interfaces that do not display Appropriate Legal Notices, your
- work need not make them do so.
-
- A compilation of a covered work with other separate and independent
-works, which are not by their nature extensions of the covered work,
-and which are not combined with it such as to form a larger program,
-in or on a volume of a storage or distribution medium, is called an
-"aggregate" if the compilation and its resulting copyright are not
-used to limit the access or legal rights of the compilation's users
-beyond what the individual works permit. Inclusion of a covered work
-in an aggregate does not cause this License to apply to the other
-parts of the aggregate.
-
- 6. Conveying Non-Source Forms.
-
- You may convey a covered work in object code form under the terms
-of sections 4 and 5, provided that you also convey the
-machine-readable Corresponding Source under the terms of this License,
-in one of these ways:
-
- a) Convey the object code in, or embodied in, a physical product
- (including a physical distribution medium), accompanied by the
- Corresponding Source fixed on a durable physical medium
- customarily used for software interchange.
-
- b) Convey the object code in, or embodied in, a physical product
- (including a physical distribution medium), accompanied by a
- written offer, valid for at least three years and valid for as
- long as you offer spare parts or customer support for that product
- model, to give anyone who possesses the object code either (1) a
- copy of the Corresponding Source for all the software in the
- product that is covered by this License, on a durable physical
- medium customarily used for software interchange, for a price no
- more than your reasonable cost of physically performing this
- conveying of source, or (2) access to copy the
- Corresponding Source from a network server at no charge.
-
- c) Convey individual copies of the object code with a copy of the
- written offer to provide the Corresponding Source. This
- alternative is allowed only occasionally and noncommercially, and
- only if you received the object code with such an offer, in accord
- with subsection 6b.
-
- d) Convey the object code by offering access from a designated
- place (gratis or for a charge), and offer equivalent access to the
- Corresponding Source in the same way through the same place at no
- further charge. You need not require recipients to copy the
- Corresponding Source along with the object code. If the place to
- copy the object code is a network server, the Corresponding Source
- may be on a different server (operated by you or a third party)
- that supports equivalent copying facilities, provided you maintain
- clear directions next to the object code saying where to find the
- Corresponding Source. Regardless of what server hosts the
- Corresponding Source, you remain obligated to ensure that it is
- available for as long as needed to satisfy these requirements.
-
- e) Convey the object code using peer-to-peer transmission, provided
- you inform other peers where the object code and Corresponding
- Source of the work are being offered to the general public at no
- charge under subsection 6d.
-
- A separable portion of the object code, whose source code is excluded
-from the Corresponding Source as a System Library, need not be
-included in conveying the object code work.
-
- A "User Product" is either (1) a "consumer product", which means any
-tangible personal property which is normally used for personal, family,
-or household purposes, or (2) anything designed or sold for incorporation
-into a dwelling. In determining whether a product is a consumer product,
-doubtful cases shall be resolved in favor of coverage. For a particular
-product received by a particular user, "normally used" refers to a
-typical or common use of that class of product, regardless of the status
-of the particular user or of the way in which the particular user
-actually uses, or expects or is expected to use, the product. A product
-is a consumer product regardless of whether the product has substantial
-commercial, industrial or non-consumer uses, unless such uses represent
-the only significant mode of use of the product.
-
- "Installation Information" for a User Product means any methods,
-procedures, authorization keys, or other information required to install
-and execute modified versions of a covered work in that User Product from
-a modified version of its Corresponding Source. The information must
-suffice to ensure that the continued functioning of the modified object
-code is in no case prevented or interfered with solely because
-modification has been made.
-
- If you convey an object code work under this section in, or with, or
-specifically for use in, a User Product, and the conveying occurs as
-part of a transaction in which the right of possession and use of the
-User Product is transferred to the recipient in perpetuity or for a
-fixed term (regardless of how the transaction is characterized), the
-Corresponding Source conveyed under this section must be accompanied
-by the Installation Information. But this requirement does not apply
-if neither you nor any third party retains the ability to install
-modified object code on the User Product (for example, the work has
-been installed in ROM).
-
- The requirement to provide Installation Information does not include a
-requirement to continue to provide support service, warranty, or updates
-for a work that has been modified or installed by the recipient, or for
-the User Product in which it has been modified or installed. Access to a
-network may be denied when the modification itself materially and
-adversely affects the operation of the network or violates the rules and
-protocols for communication across the network.
-
- Corresponding Source conveyed, and Installation Information provided,
-in accord with this section must be in a format that is publicly
-documented (and with an implementation available to the public in
-source code form), and must require no special password or key for
-unpacking, reading or copying.
-
- 7. Additional Terms.
-
- "Additional permissions" are terms that supplement the terms of this
-License by making exceptions from one or more of its conditions.
-Additional permissions that are applicable to the entire Program shall
-be treated as though they were included in this License, to the extent
-that they are valid under applicable law. If additional permissions
-apply only to part of the Program, that part may be used separately
-under those permissions, but the entire Program remains governed by
-this License without regard to the additional permissions.
-
- When you convey a copy of a covered work, you may at your option
-remove any additional permissions from that copy, or from any part of
-it. (Additional permissions may be written to require their own
-removal in certain cases when you modify the work.) You may place
-additional permissions on material, added by you to a covered work,
-for which you have or can give appropriate copyright permission.
-
- Notwithstanding any other provision of this License, for material you
-add to a covered work, you may (if authorized by the copyright holders of
-that material) supplement the terms of this License with terms:
-
- a) Disclaiming warranty or limiting liability differently from the
- terms of sections 15 and 16 of this License; or
-
- b) Requiring preservation of specified reasonable legal notices or
- author attributions in that material or in the Appropriate Legal
- Notices displayed by works containing it; or
-
- c) Prohibiting misrepresentation of the origin of that material, or
- requiring that modified versions of such material be marked in
- reasonable ways as different from the original version; or
-
- d) Limiting the use for publicity purposes of names of licensors or
- authors of the material; or
-
- e) Declining to grant rights under trademark law for use of some
- trade names, trademarks, or service marks; or
-
- f) Requiring indemnification of licensors and authors of that
- material by anyone who conveys the material (or modified versions of
- it) with contractual assumptions of liability to the recipient, for
- any liability that these contractual assumptions directly impose on
- those licensors and authors.
-
- All other non-permissive additional terms are considered "further
-restrictions" within the meaning of section 10. If the Program as you
-received it, or any part of it, contains a notice stating that it is
-governed by this License along with a term that is a further
-restriction, you may remove that term. If a license document contains
-a further restriction but permits relicensing or conveying under this
-License, you may add to a covered work material governed by the terms
-of that license document, provided that the further restriction does
-not survive such relicensing or conveying.
-
- If you add terms to a covered work in accord with this section, you
-must place, in the relevant source files, a statement of the
-additional terms that apply to those files, or a notice indicating
-where to find the applicable terms.
-
- Additional terms, permissive or non-permissive, may be stated in the
-form of a separately written license, or stated as exceptions;
-the above requirements apply either way.
-
- 8. Termination.
-
- You may not propagate or modify a covered work except as expressly
-provided under this License. Any attempt otherwise to propagate or
-modify it is void, and will automatically terminate your rights under
-this License (including any patent licenses granted under the third
-paragraph of section 11).
-
- However, if you cease all violation of this License, then your
-license from a particular copyright holder is reinstated (a)
-provisionally, unless and until the copyright holder explicitly and
-finally terminates your license, and (b) permanently, if the copyright
-holder fails to notify you of the violation by some reasonable means
-prior to 60 days after the cessation.
-
- Moreover, your license from a particular copyright holder is
-reinstated permanently if the copyright holder notifies you of the
-violation by some reasonable means, this is the first time you have
-received notice of violation of this License (for any work) from that
-copyright holder, and you cure the violation prior to 30 days after
-your receipt of the notice.
-
- Termination of your rights under this section does not terminate the
-licenses of parties who have received copies or rights from you under
-this License. If your rights have been terminated and not permanently
-reinstated, you do not qualify to receive new licenses for the same
-material under section 10.
-
- 9. Acceptance Not Required for Having Copies.
-
- You are not required to accept this License in order to receive or
-run a copy of the Program. Ancillary propagation of a covered work
-occurring solely as a consequence of using peer-to-peer transmission
-to receive a copy likewise does not require acceptance. However,
-nothing other than this License grants you permission to propagate or
-modify any covered work. These actions infringe copyright if you do
-not accept this License. Therefore, by modifying or propagating a
-covered work, you indicate your acceptance of this License to do so.
-
- 10. Automatic Licensing of Downstream Recipients.
-
- Each time you convey a covered work, the recipient automatically
-receives a license from the original licensors, to run, modify and
-propagate that work, subject to this License. You are not responsible
-for enforcing compliance by third parties with this License.
-
- An "entity transaction" is a transaction transferring control of an
-organization, or substantially all assets of one, or subdividing an
-organization, or merging organizations. If propagation of a covered
-work results from an entity transaction, each party to that
-transaction who receives a copy of the work also receives whatever
-licenses to the work the party's predecessor in interest had or could
-give under the previous paragraph, plus a right to possession of the
-Corresponding Source of the work from the predecessor in interest, if
-the predecessor has it or can get it with reasonable efforts.
-
- You may not impose any further restrictions on the exercise of the
-rights granted or affirmed under this License. For example, you may
-not impose a license fee, royalty, or other charge for exercise of
-rights granted under this License, and you may not initiate litigation
-(including a cross-claim or counterclaim in a lawsuit) alleging that
-any patent claim is infringed by making, using, selling, offering for
-sale, or importing the Program or any portion of it.
-
- 11. Patents.
-
- A "contributor" is a copyright holder who authorizes use under this
-License of the Program or a work on which the Program is based. The
-work thus licensed is called the contributor's "contributor version".
-
- A contributor's "essential patent claims" are all patent claims
-owned or controlled by the contributor, whether already acquired or
-hereafter acquired, that would be infringed by some manner, permitted
-by this License, of making, using, or selling its contributor version,
-but do not include claims that would be infringed only as a
-consequence of further modification of the contributor version. For
-purposes of this definition, "control" includes the right to grant
-patent sublicenses in a manner consistent with the requirements of
-this License.
-
- Each contributor grants you a non-exclusive, worldwide, royalty-free
-patent license under the contributor's essential patent claims, to
-make, use, sell, offer for sale, import and otherwise run, modify and
-propagate the contents of its contributor version.
-
- In the following three paragraphs, a "patent license" is any express
-agreement or commitment, however denominated, not to enforce a patent
-(such as an express permission to practice a patent or covenant not to
-sue for patent infringement). To "grant" such a patent license to a
-party means to make such an agreement or commitment not to enforce a
-patent against the party.
-
- If you convey a covered work, knowingly relying on a patent license,
-and the Corresponding Source of the work is not available for anyone
-to copy, free of charge and under the terms of this License, through a
-publicly available network server or other readily accessible means,
-then you must either (1) cause the Corresponding Source to be so
-available, or (2) arrange to deprive yourself of the benefit of the
-patent license for this particular work, or (3) arrange, in a manner
-consistent with the requirements of this License, to extend the patent
-license to downstream recipients. "Knowingly relying" means you have
-actual knowledge that, but for the patent license, your conveying the
-covered work in a country, or your recipient's use of the covered work
-in a country, would infringe one or more identifiable patents in that
-country that you have reason to believe are valid.
-
- If, pursuant to or in connection with a single transaction or
-arrangement, you convey, or propagate by procuring conveyance of, a
-covered work, and grant a patent license to some of the parties
-receiving the covered work authorizing them to use, propagate, modify
-or convey a specific copy of the covered work, then the patent license
-you grant is automatically extended to all recipients of the covered
-work and works based on it.
-
- A patent license is "discriminatory" if it does not include within
-the scope of its coverage, prohibits the exercise of, or is
-conditioned on the non-exercise of one or more of the rights that are
-specifically granted under this License. You may not convey a covered
-work if you are a party to an arrangement with a third party that is
-in the business of distributing software, under which you make payment
-to the third party based on the extent of your activity of conveying
-the work, and under which the third party grants, to any of the
-parties who would receive the covered work from you, a discriminatory
-patent license (a) in connection with copies of the covered work
-conveyed by you (or copies made from those copies), or (b) primarily
-for and in connection with specific products or compilations that
-contain the covered work, unless you entered into that arrangement,
-or that patent license was granted, prior to 28 March 2007.
-
- Nothing in this License shall be construed as excluding or limiting
-any implied license or other defenses to infringement that may
-otherwise be available to you under applicable patent law.
-
- 12. No Surrender of Others' Freedom.
-
- If conditions are imposed on you (whether by court order, agreement or
-otherwise) that contradict the conditions of this License, they do not
-excuse you from the conditions of this License. If you cannot convey a
-covered work so as to satisfy simultaneously your obligations under this
-License and any other pertinent obligations, then as a consequence you may
-not convey it at all. For example, if you agree to terms that obligate you
-to collect a royalty for further conveying from those to whom you convey
-the Program, the only way you could satisfy both those terms and this
-License would be to refrain entirely from conveying the Program.
-
- 13. Use with the GNU Affero General Public License.
-
- Notwithstanding any other provision of this License, you have
-permission to link or combine any covered work with a work licensed
-under version 3 of the GNU Affero General Public License into a single
-combined work, and to convey the resulting work. The terms of this
-License will continue to apply to the part which is the covered work,
-but the special requirements of the GNU Affero General Public License,
-section 13, concerning interaction through a network will apply to the
-combination as such.
-
- 14. Revised Versions of this License.
-
- The Free Software Foundation may publish revised and/or new versions of
-the GNU General Public License from time to time. Such new versions will
-be similar in spirit to the present version, but may differ in detail to
-address new problems or concerns.
-
- Each version is given a distinguishing version number. If the
-Program specifies that a certain numbered version of the GNU General
-Public License "or any later version" applies to it, you have the
-option of following the terms and conditions either of that numbered
-version or of any later version published by the Free Software
-Foundation. If the Program does not specify a version number of the
-GNU General Public License, you may choose any version ever published
-by the Free Software Foundation.
-
- If the Program specifies that a proxy can decide which future
-versions of the GNU General Public License can be used, that proxy's
-public statement of acceptance of a version permanently authorizes you
-to choose that version for the Program.
-
- Later license versions may give you additional or different
-permissions. However, no additional obligations are imposed on any
-author or copyright holder as a result of your choosing to follow a
-later version.
-
- 15. Disclaimer of Warranty.
-
- THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
-APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
-HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
-OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
-THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
-IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
-ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
-
- 16. Limitation of Liability.
-
- IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
-WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
-THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
-GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
-USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
-DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
-PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
-EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
-SUCH DAMAGES.
-
- 17. Interpretation of Sections 15 and 16.
-
- If the disclaimer of warranty and limitation of liability provided
-above cannot be given local legal effect according to their terms,
-reviewing courts shall apply local law that most closely approximates
-an absolute waiver of all civil liability in connection with the
-Program, unless a warranty or assumption of liability accompanies a
-copy of the Program in return for a fee.
-
- END OF TERMS AND CONDITIONS
-
- How to Apply These Terms to Your New Programs
-
- If you develop a new program, and you want it to be of the greatest
-possible use to the public, the best way to achieve this is to make it
-free software which everyone can redistribute and change under these terms.
-
- To do so, attach the following notices to the program. It is safest
-to attach them to the start of each source file to most effectively
-state the exclusion of warranty; and each file should have at least
-the "copyright" line and a pointer to where the full notice is found.
-
-
- Copyright (C)
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program. If not, see .
-
-Also add information on how to contact you by electronic and paper mail.
-
- If the program does terminal interaction, make it output a short
-notice like this when it starts in an interactive mode:
-
- Copyright (C)
- This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
- This is free software, and you are welcome to redistribute it
- under certain conditions; type `show c' for details.
-
-The hypothetical commands `show w' and `show c' should show the appropriate
-parts of the General Public License. Of course, your program's commands
-might be different; for a GUI interface, you would use an "about box".
-
- You should also get your employer (if you work as a programmer) or school,
-if any, to sign a "copyright disclaimer" for the program, if necessary.
-For more information on this, and how to apply and follow the GNU GPL, see
-.
-
- The GNU General Public License does not permit incorporating your program
-into proprietary programs. If your program is a subroutine library, you
-may consider it more useful to permit linking proprietary applications with
-the library. If this is what you want to do, use the GNU Lesser General
-Public License instead of this License. But first, please read
-.
diff --git a/Cask b/Cask
index 13832ef..35e5476 100644
--- a/Cask
+++ b/Cask
@@ -11,13 +11,9 @@
(depends-on "ert-runner")
(depends-on "ecukes")
(depends-on "espuds")
- ;; (depends-on "org-plus-contrib") ;; see https://github.com/cask/cask/issues/119
(depends-on "mocker")
- (depends-on "skewer-mode")
(depends-on "deferred")
- (depends-on "auto-complete")
(depends-on "company")
- (depends-on "smartrep")
(depends-on "polymode")
(depends-on "markdown-mode")
(depends-on "julia-mode")
diff --git a/Demo.ipynb b/Demo.ipynb
deleted file mode 100644
index 4e5ca3c..0000000
--- a/Demo.ipynb
+++ /dev/null
@@ -1,490 +0,0 @@
-{
- "cells": [
- {
- "cell_type": "code",
- "execution_count": 1,
- "metadata": {
- "autoscroll": false,
- "collapsed": false,
- "ein.hycell": false,
- "ein.tags": "worksheet-0",
- "execute-time": [
- "2018-11-05T22:48:49.882723Z",
- "2018-11-05T22:48:49.898378Z"
- ],
- "slideshow": {
- "slide_type": "-"
- }
- },
- "outputs": [],
- "source": [
- "import ast"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "autoscroll": false,
- "collapsed": false,
- "ein.hycell": false,
- "ein.tags": "worksheet-0",
- "slideshow": {
- "slide_type": "-"
- }
- },
- "outputs": [],
- "source": [
- "ast.literal_eval()"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 2,
- "metadata": {
- "autoscroll": false,
- "collapsed": false,
- "ein.hy_cell": true,
- "ein.hycell": false,
- "ein.tags": "worksheet-0",
- "execute-time": [
- "2018-11-05T22:49:00.227520Z",
- "2018-11-05T22:49:00.243212Z"
- ],
- "slideshow": {
- "slide_type": "-"
- }
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "'3.6.6 | packaged by conda-forge | (default, Jul 26 2018, 11:48:23) [MSC v.1900 64 bit (AMD64)]'"
- ]
- },
- "execution_count": 2,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "import sys\n",
- "sys.version\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {
- "ein.tags": "worksheet-0",
- "slideshow": {
- "slide_type": "-"
- }
- },
- "source": [
- "c:/Users/mille/Miniconda3/envs/datascience/Library/bin/"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 7,
- "metadata": {
- "autoscroll": false,
- "collapsed": false,
- "ein.hycell": false,
- "ein.tags": "worksheet-0",
- "execute-time": [
- "2018-11-05T22:34:50.809004Z",
- "2018-11-05T22:34:50.824630Z"
- ],
- "slideshow": {
- "slide_type": "-"
- }
- },
- "outputs": [],
- "source": [
- "sys.path.append('C:\\\\Users\\\\Miniconda3\\\\envs\\\\datascience\\\\Library\\\\bin\\\\')"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 5,
- "metadata": {
- "autoscroll": false,
- "collapsed": false,
- "ein.hycell": false,
- "ein.tags": "worksheet-0",
- "execute-time": [
- "2018-11-05T22:49:41.133042Z",
- "2018-11-05T22:49:41.164290Z"
- ],
- "slideshow": {
- "slide_type": "-"
- }
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "['',\n 'C:\\\\Users\\\\mille\\\\Miniconda3\\\\envs\\\\datascience\\\\python36.zip',\n 'C:\\\\Users\\\\mille\\\\Miniconda3\\\\envs\\\\datascience\\\\DLLs',\n 'C:\\\\Users\\\\mille\\\\Miniconda3\\\\envs\\\\datascience\\\\lib',\n 'C:\\\\Users\\\\mille\\\\Miniconda3\\\\envs\\\\datascience',\n 'C:\\\\Users\\\\mille\\\\Miniconda3\\\\envs\\\\datascience\\\\lib\\\\site-packages',\n 'C:\\\\Users\\\\mille\\\\Miniconda3\\\\envs\\\\datascience\\\\lib\\\\site-packages\\\\win32',\n 'C:\\\\Users\\\\mille\\\\Miniconda3\\\\envs\\\\datascience\\\\lib\\\\site-packages\\\\win32\\\\lib',\n 'C:\\\\Users\\\\mille\\\\Miniconda3\\\\envs\\\\datascience\\\\lib\\\\site-packages\\\\Pythonwin',\n 'C:\\\\Users\\\\mille\\\\Miniconda3\\\\envs\\\\datascience\\\\lib\\\\site-packages\\\\IPython\\\\extensions',\n 'C:\\\\Users\\\\mille\\\\.ipython']"
- ]
- },
- "execution_count": 5,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "sys.path"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 7,
- "metadata": {
- "autoscroll": false,
- "collapsed": false,
- "ein.hycell": false,
- "ein.tags": "worksheet-0",
- "execute-time": [
- "2018-11-05T22:50:28.971341Z",
- "2018-11-05T22:50:28.986926Z"
- ],
- "slideshow": {
- "slide_type": "-"
- }
- },
- "outputs": [],
- "source": [
- "a = np.zeros((10,10))"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 4,
- "metadata": {
- "autoscroll": false,
- "collapsed": false,
- "ein.hy_cell": true,
- "ein.hycell": false,
- "ein.tags": "worksheet-0",
- "execute-time": [
- "2018-11-05T22:49:25.379578Z",
- "2018-11-05T22:49:27.232239Z"
- ],
- "slideshow": {
- "slide_type": "-"
- }
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "[]"
- ]
- },
- "execution_count": 4,
- "metadata": {},
- "output_type": "execute_result"
- },
- {
- "data": {
- "image/png": [
- "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\n"
- ],
- "text/plain": [
- ""
- ]
- },
- "metadata": {},
- "output_type": "display_data"
- }
- ],
- "source": [
- "%matplotlib inline\n",
- "import matplotlib.pyplot as plt\n",
- "import numpy as np\n",
- "def plotnormal():\n",
- " return plt.plot(np.random.randn(1000), np.random.randn(1000), 'o', alpha=0.3)\n",
- "plotnormal()"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "autoscroll": false,
- "collapsed": false,
- "ein.hycell": false,
- "ein.tags": "worksheet-0",
- "slideshow": {
- "slide_type": "-"
- }
- },
- "outputs": [],
- "source": [
- "np.zeros_like()"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {
- "ein.tags": "worksheet-0",
- "slideshow": {
- "slide_type": "-"
- }
- },
- "source": [
- "Errors are shown in informative ways:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 2,
- "metadata": {
- "autoscroll": false,
- "collapsed": false,
- "ein.hy_cell": true,
- "ein.hycell": false,
- "ein.tags": "worksheet-0",
- "slideshow": {
- "slide_type": "-"
- }
- },
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "ERROR: File `'non_existent_file.py'` not found.\n"
- ]
- }
- ],
- "source": [
- "%run non_existent_file"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 4,
- "metadata": {
- "autoscroll": false,
- "collapsed": false,
- "ein.hy_cell": true,
- "ein.hycell": false,
- "ein.tags": "worksheet-0",
- "slideshow": {
- "slide_type": "-"
- }
- },
- "outputs": [
- {
- "ename": "ZeroDivisionError",
- "evalue": "division by zero",
- "output_type": "error",
- "traceback": [
- "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
- "\u001b[1;31mZeroDivisionError\u001b[0m Traceback (most recent call last)",
- "\u001b[1;32m\u001b[0m in \u001b[0;36m\u001b[1;34m()\u001b[0m\n\u001b[0;32m 1\u001b[0m \u001b[0mx\u001b[0m \u001b[1;33m=\u001b[0m \u001b[1;36m1\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 2\u001b[0m \u001b[0my\u001b[0m \u001b[1;33m=\u001b[0m \u001b[1;36m4\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m----> 3\u001b[1;33m \u001b[0mz\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0my\u001b[0m\u001b[1;33m/\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;36m1\u001b[0m\u001b[1;33m-\u001b[0m\u001b[0mx\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m",
- "\u001b[1;31mZeroDivisionError\u001b[0m: division by zero"
- ]
- }
- ],
- "source": [
- "x = 1\n",
- "y = 4\n",
- "z = y/(1-x)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 7,
- "metadata": {
- "autoscroll": false,
- "collapsed": false,
- "ein.hy_cell": true,
- "ein.hycell": false,
- "ein.tags": "worksheet-0",
- "slideshow": {
- "slide_type": "-"
- }
- },
- "outputs": [],
- "source": [
- "ip = get_ipython()"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 8,
- "metadata": {
- "autoscroll": false,
- "collapsed": false,
- "ein.hy_cell": true,
- "ein.hycell": false,
- "ein.tags": "worksheet-0",
- "slideshow": {
- "slide_type": "-"
- }
- },
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "Installed hierarchymagic.py. To use it, type:\n",
- " %load_ext hierarchymagic\n"
- ]
- }
- ],
- "source": [
- "%install_ext https://raw.github.com/anaderi/ipython-hierarchymagic/master/hierarchymagic.py"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 1,
- "metadata": {
- "autoscroll": false,
- "collapsed": false,
- "ein.hy_cell": true,
- "ein.hycell": false,
- "ein.tags": "worksheet-0",
- "slideshow": {
- "slide_type": "-"
- }
- },
- "outputs": [],
- "source": [
- "%load_ext hierarchymagic"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {
- "ein.tags": "worksheet-0",
- "slideshow": {
- "slide_type": "-"
- }
- },
- "source": [
- "You need graphviz installed and on your PATH for the following to work."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 2,
- "metadata": {
- "autoscroll": false,
- "collapsed": false,
- "ein.hy_cell": true,
- "ein.hycell": false,
- "ein.tags": "worksheet-0",
- "slideshow": {
- "slide_type": "-"
- }
- },
- "outputs": [
- {
- "ename": "FileNotFoundError",
- "evalue": "[WinError 2] The system cannot find the file specified",
- "output_type": "error",
- "traceback": [
- "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
- "\u001b[1;31mFileNotFoundError\u001b[0m Traceback (most recent call last)",
- "\u001b[1;32m\u001b[0m in \u001b[0;36m\u001b[1;34m()\u001b[0m\n\u001b[1;32m----> 1\u001b[1;33m \u001b[0mget_ipython\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mmagic\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;34m'hierarchy get_ipython()'\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m",
- "\u001b[1;32mC:\\Users\\millejoh\\Anaconda3\\lib\\site-packages\\IPython\\core\\interactiveshell.py\u001b[0m in \u001b[0;36mmagic\u001b[1;34m(self, arg_s)\u001b[0m\n\u001b[0;32m 2161\u001b[0m \u001b[0mmagic_name\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0m_\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mmagic_arg_s\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0marg_s\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mpartition\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;34m' '\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 2162\u001b[0m \u001b[0mmagic_name\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mmagic_name\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mlstrip\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mprefilter\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mESC_MAGIC\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m-> 2163\u001b[1;33m \u001b[1;32mreturn\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mrun_line_magic\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mmagic_name\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mmagic_arg_s\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 2164\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 2165\u001b[0m \u001b[1;31m#-------------------------------------------------------------------------\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n",
- "\u001b[1;32mC:\\Users\\millejoh\\Anaconda3\\lib\\site-packages\\IPython\\core\\interactiveshell.py\u001b[0m in \u001b[0;36mrun_line_magic\u001b[1;34m(self, magic_name, line)\u001b[0m\n\u001b[0;32m 2082\u001b[0m \u001b[0mkwargs\u001b[0m\u001b[1;33m[\u001b[0m\u001b[1;34m'local_ns'\u001b[0m\u001b[1;33m]\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0msys\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0m_getframe\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mstack_depth\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mf_locals\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 2083\u001b[0m \u001b[1;32mwith\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mbuiltin_trap\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m-> 2084\u001b[1;33m \u001b[0mresult\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mfn\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m*\u001b[0m\u001b[0margs\u001b[0m\u001b[1;33m,\u001b[0m\u001b[1;33m**\u001b[0m\u001b[0mkwargs\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 2085\u001b[0m \u001b[1;32mreturn\u001b[0m \u001b[0mresult\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 2086\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n",
- "\u001b[1;32m\u001b[0m in \u001b[0;36mhierarchy\u001b[1;34m(self, parameter_s)\u001b[0m\n",
- "\u001b[1;32mC:\\Users\\millejoh\\Anaconda3\\lib\\site-packages\\IPython\\core\\magic.py\u001b[0m in \u001b[0;36m\u001b[1;34m(f, *a, **k)\u001b[0m\n\u001b[0;32m 191\u001b[0m \u001b[1;31m# but it's overkill for just that one bit of state.\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 192\u001b[0m \u001b[1;32mdef\u001b[0m \u001b[0mmagic_deco\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0marg\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m--> 193\u001b[1;33m \u001b[0mcall\u001b[0m \u001b[1;33m=\u001b[0m \u001b[1;32mlambda\u001b[0m \u001b[0mf\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;33m*\u001b[0m\u001b[0ma\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;33m**\u001b[0m\u001b[0mk\u001b[0m\u001b[1;33m:\u001b[0m \u001b[0mf\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m*\u001b[0m\u001b[0ma\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;33m**\u001b[0m\u001b[0mk\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 194\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 195\u001b[0m \u001b[1;32mif\u001b[0m \u001b[0mcallable\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0marg\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n",
- "\u001b[1;32mC:\\Users\\millejoh\\.ipython\\extensions\\hierarchymagic.py\u001b[0m in \u001b[0;36mhierarchy\u001b[1;34m(self, parameter_s)\u001b[0m\n\u001b[0;32m 245\u001b[0m graph_attrs={'rankdir': args.rankdir,\n\u001b[0;32m 246\u001b[0m 'size': '\"{0}\"'.format(args.size)})\n\u001b[1;32m--> 247\u001b[1;33m \u001b[0mstdout\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mrun_dot\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mcode\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mformat\u001b[0m\u001b[1;33m=\u001b[0m\u001b[1;34m'png'\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 248\u001b[0m \u001b[0mdisplay_png\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mstdout\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mraw\u001b[0m\u001b[1;33m=\u001b[0m\u001b[1;32mTrue\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 249\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n",
- "\u001b[1;32mC:\\Users\\millejoh\\.ipython\\extensions\\hierarchymagic.py\u001b[0m in \u001b[0;36mrun_dot\u001b[1;34m(code, options, format)\u001b[0m\n\u001b[0;32m 111\u001b[0m \u001b[1;31m# * http://stackoverflow.com/a/2935727/727827\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 112\u001b[0m p = Popen(dot_args, stdout=PIPE, stdin=PIPE, stderr=PIPE,\n\u001b[1;32m--> 113\u001b[1;33m creationflags=0x08000000)\n\u001b[0m\u001b[0;32m 114\u001b[0m \u001b[1;32melse\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 115\u001b[0m \u001b[0mp\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mPopen\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mdot_args\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mstdout\u001b[0m\u001b[1;33m=\u001b[0m\u001b[0mPIPE\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mstdin\u001b[0m\u001b[1;33m=\u001b[0m\u001b[0mPIPE\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mstderr\u001b[0m\u001b[1;33m=\u001b[0m\u001b[0mPIPE\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n",
- "\u001b[1;32mC:\\Users\\millejoh\\Anaconda3\\lib\\subprocess.py\u001b[0m in \u001b[0;36m__init__\u001b[1;34m(self, args, bufsize, executable, stdin, stdout, stderr, preexec_fn, close_fds, shell, cwd, env, universal_newlines, startupinfo, creationflags, restore_signals, start_new_session, pass_fds)\u001b[0m\n\u001b[0;32m 948\u001b[0m \u001b[0mc2pread\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mc2pwrite\u001b[0m\u001b[1;33m,\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 949\u001b[0m \u001b[0merrread\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0merrwrite\u001b[0m\u001b[1;33m,\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m--> 950\u001b[1;33m restore_signals, start_new_session)\n\u001b[0m\u001b[0;32m 951\u001b[0m \u001b[1;32mexcept\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 952\u001b[0m \u001b[1;31m# Cleanup if the child failed starting.\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n",
- "\u001b[1;32mC:\\Users\\millejoh\\Anaconda3\\lib\\subprocess.py\u001b[0m in \u001b[0;36m_execute_child\u001b[1;34m(self, args, executable, preexec_fn, close_fds, pass_fds, cwd, env, startupinfo, creationflags, shell, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite, unused_restore_signals, unused_start_new_session)\u001b[0m\n\u001b[0;32m 1218\u001b[0m \u001b[0menv\u001b[0m\u001b[1;33m,\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 1219\u001b[0m \u001b[0mcwd\u001b[0m\u001b[1;33m,\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m-> 1220\u001b[1;33m startupinfo)\n\u001b[0m\u001b[0;32m 1221\u001b[0m \u001b[1;32mfinally\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 1222\u001b[0m \u001b[1;31m# Child is launched. Close the parent's copy of those pipe\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n",
- "\u001b[1;31mFileNotFoundError\u001b[0m: [WinError 2] The system cannot find the file specified"
- ]
- }
- ],
- "source": [
- "%hierarchy get_ipython()"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {
- "ein.tags": "worksheet-0",
- "slideshow": {
- "slide_type": "-"
- }
- },
- "source": [
- "EIN also supports pretty printing from SymPy."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 0,
- "metadata": {
- "autoscroll": false,
- "collapsed": false,
- "ein.hy_cell": true,
- "ein.hycell": false,
- "ein.tags": "worksheet-0",
- "slideshow": {
- "slide_type": "-"
- }
- },
- "outputs": [],
- "source": [
- "from sympy.interactive import printing\n",
- "printing.init_printing()\n",
- "\n",
- "import sympy as sym\n",
- "from sympy import *\n",
- "x, y, z = symbols(\"x y z\")\n",
- "\n",
- "Rational(3,2)*pi + exp(I*x) / (x**2 + y)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {
- "ein.tags": "worksheet-0",
- "slideshow": {
- "slide_type": "-"
- }
- },
- "source": [
- "If you install px can you get the below to work?\n",
- "\n",
- "$a^2=b$\n",
- "\n",
- "\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 0,
- "metadata": {
- "autoscroll": false,
- "collapsed": false,
- "ein.hy_cell": true,
- "ein.hycell": false,
- "ein.tags": "worksheet-0",
- "slideshow": {
- "slide_type": "-"
- }
- },
- "outputs": [],
- "source": []
- }
- ],
- "metadata": {
- "kernelspec": {
- "display_name": "Data Science (py36)",
- "name": "datascience"
- },
- "name": "Demo.ipynb"
- },
- "nbformat": 4,
- "nbformat_minor": 0
-}
diff --git a/Development Ideas.ipynb b/Development Ideas.ipynb
deleted file mode 100644
index 24a5ac1..0000000
--- a/Development Ideas.ipynb
+++ /dev/null
@@ -1,833 +0,0 @@
-{
- "cells": [
- {
- "cell_type": "markdown",
- "metadata": {
- "ein.tags": "worksheet-0",
- "slideshow": {
- "slide_type": "-"
- }
- },
- "source": [
- "# Object Inspector"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {
- "ein.tags": "worksheet-0",
- "slideshow": {
- "slide_type": "-"
- }
- },
- "source": [
- "Need to get python objects from strings. Is eval the best way?"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 1,
- "metadata": {
- "autoscroll": false,
- "collapsed": false,
- "ein.hycell": false,
- "ein.tags": "worksheet-0",
- "execute-time": [
- "2018-11-01T21:27:17.435516Z",
- "2018-11-01T21:27:17.469860Z"
- ],
- "slideshow": {
- "slide_type": "-"
- }
- },
- "outputs": [],
- "source": [
- "import inspect"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 3,
- "metadata": {
- "autoscroll": false,
- "collapsed": false,
- "ein.hycell": false,
- "ein.tags": "worksheet-0",
- "execute-time": [
- "2018-11-01T21:33:50.033296Z",
- "2018-11-01T21:33:50.064574Z"
- ],
- "slideshow": {
- "slide_type": "-"
- }
- },
- "outputs": [],
- "source": [
- "import ein"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "autoscroll": false,
- "collapsed": false,
- "ein.hycell": false,
- "ein.tags": "worksheet-0",
- "slideshow": {
- "slide_type": "-"
- }
- },
- "outputs": [],
- "source": [
- "ein.pyto"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 4,
- "metadata": {
- "autoscroll": false,
- "collapsed": false,
- "ein.hycell": false,
- "ein.tags": "worksheet-0",
- "execute-time": [
- "2018-11-01T21:33:55.629201Z",
- "2018-11-01T21:33:55.663747Z"
- ],
- "slideshow": {
- "slide_type": "-"
- }
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "['CodeMagics',\n '__builtins__',\n '__cached__',\n '__doc__',\n '__file__',\n '__loader__',\n '__name__',\n '__package__',\n '__spec__',\n '_find_edit_target',\n '_find_edit_target_012',\n '_find_edit_target_013',\n '_find_edit_target_python',\n 'eval_hy_string',\n 'export_nb',\n 'find_source',\n 'print_object_info_for',\n 'run_docstring_examples',\n 'set_figure_size']"
- ]
- },
- "execution_count": 4,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "dir(ein)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 5,
- "metadata": {
- "autoscroll": false,
- "collapsed": false,
- "ein.hycell": false,
- "ein.tags": "worksheet-0",
- "execute-time": [
- "2018-11-01T21:34:15.247868Z",
- "2018-11-01T21:34:15.283595Z"
- ],
- "slideshow": {
- "slide_type": "-"
- }
- },
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "{\"type_name\": \"module\", \"base_class\": \"\", \"string_form\": \"\", \"namespace\": null, \"length\": null, \"file\": \"c:\\\\users\\\\mille\\\\miniconda3\\\\lib\\\\inspect.py\", \"definition\": null, \"docstring\": \"Get useful information from live Python objects.\\n\\nThis module encapsulates the interface provided by the internal special\\nattributes (co_*, im_*, tb_*, etc.) in a friendlier fashion.\\nIt also provides some help for examining source code and class layout.\\n\\nHere are some of the useful functions provided by this module:\\n\\n ismodule(), isclass(), ismethod(), isfunction(), isgeneratorfunction(),\\n isgenerator(), istraceback(), isframe(), iscode(), isbuiltin(),\\n isroutine() - check object types\\n getmembers() - get members of an object that satisfy a given condition\\n\\n getfile(), getsourcefile(), getsource() - find an object's source code\\n getdoc(), getcomments() - get documentation on an object\\n getmodule() - determine the module that an object came from\\n getclasstree() - arrange classes so as to represent their hierarchy\\n\\n getargvalues(), getcallargs() - get info about function arguments\\n getfullargspec() - same, with support for Python 3 features\\n formatargspec(), formatargvalues() - format an argument spec\\n getouterframes(), getinnerframes() - get info about frames\\n currentframe() - get the current stack frame\\n stack(), trace() - get info about frames on the stack or in a traceback\\n\\n signature() - get a Signature object for the callable\", \"source\": null, \"init_definition\": null, \"class_docstring\": null, \"init_docstring\": null, \"call_def\": null, \"call_docstring\": null, \"ismagic\": false, \"isalias\": false, \"isclass\": null, \"argspec\": null, \"found\": true, \"name\": \"\"}\n"
- ]
- }
- ],
- "source": [
- "__import__('ein').print_object_info_for(inspect)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "autoscroll": false,
- "collapsed": false,
- "ein.hycell": false,
- "ein.tags": "worksheet-0",
- "slideshow": {
- "slide_type": "-"
- }
- },
- "outputs": [],
- "source": [
- "inspect.B"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 2,
- "metadata": {
- "autoscroll": false,
- "collapsed": false,
- "ein.hycell": false,
- "ein.tags": "worksheet-0",
- "slideshow": {
- "slide_type": "-"
- }
- },
- "outputs": [],
- "source": [
- "a=10"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 4,
- "metadata": {
- "autoscroll": false,
- "collapsed": false,
- "ein.hycell": false,
- "ein.tags": "worksheet-0",
- "slideshow": {
- "slide_type": "-"
- }
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "{'error': 'Object ax not found.', 'name': 'ax'}"
- ]
- },
- "execution_count": 4,
- "metadata": {},
- "output_type": "execute_result"
- },
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "{\"name\": \"ax\", \"error\": \"Object ax not found.\"}\n"
- ]
- }
- ],
- "source": [
- "__import__('ein_inspector').generate_inspector_data('ax', globals(), locals())"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 5,
- "metadata": {
- "autoscroll": false,
- "collapsed": false,
- "ein.hycell": false,
- "ein.tags": "worksheet-0",
- "slideshow": {
- "slide_type": "-"
- }
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "module"
- ]
- },
- "execution_count": 5,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "mylst = [1, 2, 3]\n",
- "type(inspect)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 6,
- "metadata": {
- "autoscroll": false,
- "collapsed": false,
- "ein.hycell": false,
- "ein.tags": "worksheet-0",
- "slideshow": {
- "slide_type": "-"
- }
- },
- "outputs": [
- {
- "ename": "TypeError",
- "evalue": "[1, 2, 3] is not a module, class, method, function, traceback, frame, or code object",
- "output_type": "error",
- "traceback": [
- "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
- "\u001b[0;31mTypeError\u001b[0m Traceback (most recent call last)",
- "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0minspect\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mgetsourcefile\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mmylst\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m",
- "\u001b[0;32mc:\\Users\\mille\\Miniconda3\\envs\\anaconda\\lib\\inspect.py\u001b[0m in \u001b[0;36mgetsourcefile\u001b[0;34m(object)\u001b[0m\n\u001b[1;32m 658\u001b[0m \u001b[0mReturn\u001b[0m \u001b[1;32mNone\u001b[0m \u001b[1;32mif\u001b[0m \u001b[0mno\u001b[0m \u001b[0mway\u001b[0m \u001b[0mcan\u001b[0m \u001b[0mbe\u001b[0m \u001b[0midentified\u001b[0m \u001b[0mto\u001b[0m \u001b[0mget\u001b[0m \u001b[0mthe\u001b[0m \u001b[0msource\u001b[0m\u001b[1;33m.\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m 659\u001b[0m \"\"\"\n\u001b[0;32m--> 660\u001b[0;31m \u001b[0mfilename\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mgetfile\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mobject\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 661\u001b[0m \u001b[0mall_bytecode_suffixes\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mimportlib\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mmachinery\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mDEBUG_BYTECODE_SUFFIXES\u001b[0m\u001b[1;33m[\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m 662\u001b[0m \u001b[0mall_bytecode_suffixes\u001b[0m \u001b[1;33m+=\u001b[0m \u001b[0mimportlib\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mmachinery\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mOPTIMIZED_BYTECODE_SUFFIXES\u001b[0m\u001b[1;33m[\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n",
- "\u001b[0;32mc:\\Users\\mille\\Miniconda3\\envs\\anaconda\\lib\\inspect.py\u001b[0m in \u001b[0;36mgetfile\u001b[0;34m(object)\u001b[0m\n\u001b[1;32m 623\u001b[0m \u001b[1;32mreturn\u001b[0m \u001b[0mobject\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mco_filename\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m 624\u001b[0m raise TypeError('{!r} is not a module, class, method, '\n\u001b[0;32m--> 625\u001b[0;31m 'function, traceback, frame, or code object'.format(object))\n\u001b[0m\u001b[1;32m 626\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m 627\u001b[0m \u001b[0mModuleInfo\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mnamedtuple\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;34m'ModuleInfo'\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;34m'name suffix mode module_type'\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n",
- "\u001b[0;31mTypeError\u001b[0m: [1, 2, 3] is not a module, class, method, function, traceback, frame, or code object"
- ]
- }
- ],
- "source": [
- "inspect.getsourcefile(mylst)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 6,
- "metadata": {
- "autoscroll": false,
- "collapsed": false,
- "ein.hycell": false,
- "ein.tags": "worksheet-0",
- "slideshow": {
- "slide_type": "-"
- }
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- ""
- ]
- },
- "execution_count": 6,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "eval('inspect')"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 7,
- "metadata": {
- "autoscroll": false,
- "collapsed": false,
- "ein.hycell": false,
- "ein.tags": "worksheet-0",
- "slideshow": {
- "slide_type": "-"
- }
- },
- "outputs": [
- {
- "ename": "TypeError",
- "evalue": "10 is not a module, class, method, function, traceback, frame, or code object",
- "output_type": "error",
- "traceback": [
- "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
- "\u001b[0;31mTypeError\u001b[0m Traceback (most recent call last)",
- "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0minspect\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mgetsource\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0ma\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m",
- "\u001b[0;32mc:\\Users\\mille\\Anaconda3\\lib\\inspect.py\u001b[0m in \u001b[0;36mgetsource\u001b[0;34m(object)\u001b[0m\n\u001b[1;32m 942\u001b[0m \u001b[1;32mor\u001b[0m \u001b[0mcode\u001b[0m \u001b[0mobject\u001b[0m\u001b[1;33m.\u001b[0m \u001b[0mThe\u001b[0m \u001b[0msource\u001b[0m \u001b[0mcode\u001b[0m \u001b[1;32mis\u001b[0m \u001b[0mreturned\u001b[0m \u001b[1;32mas\u001b[0m \u001b[0ma\u001b[0m \u001b[0msingle\u001b[0m \u001b[0mstring\u001b[0m\u001b[1;33m.\u001b[0m \u001b[0mAn\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m 943\u001b[0m OSError is raised if the source code cannot be retrieved.\"\"\"\n\u001b[0;32m--> 944\u001b[0;31m \u001b[0mlines\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mlnum\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mgetsourcelines\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mobject\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 945\u001b[0m \u001b[1;32mreturn\u001b[0m \u001b[1;34m''\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mjoin\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mlines\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m 946\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n",
- "\u001b[0;32mc:\\Users\\mille\\Anaconda3\\lib\\inspect.py\u001b[0m in \u001b[0;36mgetsourcelines\u001b[0;34m(object)\u001b[0m\n\u001b[1;32m 929\u001b[0m raised if the source code cannot be retrieved.\"\"\"\n\u001b[1;32m 930\u001b[0m \u001b[0mobject\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0munwrap\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mobject\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m--> 931\u001b[0;31m \u001b[0mlines\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mlnum\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mfindsource\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mobject\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 932\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m 933\u001b[0m \u001b[1;32mif\u001b[0m \u001b[0mismodule\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mobject\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n",
- "\u001b[0;32mc:\\Users\\mille\\Anaconda3\\lib\\inspect.py\u001b[0m in \u001b[0;36mfindsource\u001b[0;34m(object)\u001b[0m\n\u001b[1;32m 742\u001b[0m is raised if the source code cannot be retrieved.\"\"\"\n\u001b[1;32m 743\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m--> 744\u001b[0;31m \u001b[0mfile\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mgetsourcefile\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mobject\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 745\u001b[0m \u001b[1;32mif\u001b[0m \u001b[0mfile\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m 746\u001b[0m \u001b[1;31m# Invalidate cache if needed.\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n",
- "\u001b[0;32mc:\\Users\\mille\\Anaconda3\\lib\\inspect.py\u001b[0m in \u001b[0;36mgetsourcefile\u001b[0;34m(object)\u001b[0m\n\u001b[1;32m 658\u001b[0m \u001b[0mReturn\u001b[0m \u001b[1;32mNone\u001b[0m \u001b[1;32mif\u001b[0m \u001b[0mno\u001b[0m \u001b[0mway\u001b[0m \u001b[0mcan\u001b[0m \u001b[0mbe\u001b[0m \u001b[0midentified\u001b[0m \u001b[0mto\u001b[0m \u001b[0mget\u001b[0m \u001b[0mthe\u001b[0m \u001b[0msource\u001b[0m\u001b[1;33m.\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m 659\u001b[0m \"\"\"\n\u001b[0;32m--> 660\u001b[0;31m \u001b[0mfilename\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mgetfile\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mobject\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 661\u001b[0m \u001b[0mall_bytecode_suffixes\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mimportlib\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mmachinery\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mDEBUG_BYTECODE_SUFFIXES\u001b[0m\u001b[1;33m[\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m 662\u001b[0m \u001b[0mall_bytecode_suffixes\u001b[0m \u001b[1;33m+=\u001b[0m \u001b[0mimportlib\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mmachinery\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mOPTIMIZED_BYTECODE_SUFFIXES\u001b[0m\u001b[1;33m[\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n",
- "\u001b[0;32mc:\\Users\\mille\\Anaconda3\\lib\\inspect.py\u001b[0m in \u001b[0;36mgetfile\u001b[0;34m(object)\u001b[0m\n\u001b[1;32m 623\u001b[0m \u001b[1;32mreturn\u001b[0m \u001b[0mobject\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mco_filename\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m 624\u001b[0m raise TypeError('{!r} is not a module, class, method, '\n\u001b[0;32m--> 625\u001b[0;31m 'function, traceback, frame, or code object'.format(object))\n\u001b[0m\u001b[1;32m 626\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m 627\u001b[0m \u001b[0mModuleInfo\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mnamedtuple\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;34m'ModuleInfo'\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;34m'name suffix mode module_type'\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n",
- "\u001b[0;31mTypeError\u001b[0m: 10 is not a module, class, method, function, traceback, frame, or code object"
- ]
- }
- ],
- "source": [
- "inspect.getsource(a)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 8,
- "metadata": {
- "autoscroll": false,
- "collapsed": false,
- "ein.hycell": false,
- "ein.tags": "worksheet-0",
- "slideshow": {
- "slide_type": "-"
- }
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "False"
- ]
- },
- "execution_count": 8,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "inspect.isbuiltin(a)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 9,
- "metadata": {
- "autoscroll": false,
- "collapsed": false,
- "ein.hycell": false,
- "ein.tags": "worksheet-0",
- "slideshow": {
- "slide_type": "-"
- }
- },
- "outputs": [
- {
- "data": {
- "image/png": "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\nGXaFQqEYMv4/kyesq/afEWYAAAAASUVORK5CYII=\n",
- "text/plain": [
- ""
- ]
- },
- "metadata": {},
- "output_type": "display_data"
- }
- ],
- "source": [
- "%matplotlib inline\n",
- "import matplotlib.pyplot as plt\n",
- "import numpy as np\n",
- "ax = plt.plot(np.random.randn(1000), np.random.randn(1000), 'o', alpha=0.3)\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 5,
- "metadata": {
- "autoscroll": false,
- "collapsed": false,
- "ein.hycell": false,
- "ein.tags": "worksheet-0",
- "slideshow": {
- "slide_type": "-"
- }
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "[]"
- ]
- },
- "execution_count": 5,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "ax"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 7,
- "metadata": {
- "autoscroll": false,
- "collapsed": false,
- "ein.hycell": false,
- "ein.tags": "worksheet-0",
- "slideshow": {
- "slide_type": "-"
- }
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "[]"
- ]
- },
- "execution_count": 7,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "eval('ax')"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 6,
- "metadata": {
- "autoscroll": false,
- "collapsed": false,
- "ein.hycell": false,
- "ein.tags": "worksheet-0",
- "slideshow": {
- "slide_type": "-"
- }
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "\"list() -> new empty list\\nlist(iterable) -> new list initialized from iterable's items\""
- ]
- },
- "execution_count": 6,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "inspect.getdoc(ax)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 18,
- "metadata": {
- "autoscroll": false,
- "collapsed": false,
- "ein.hycell": false,
- "ein.tags": "worksheet-0",
- "slideshow": {
- "slide_type": "-"
- }
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "[('__abs__', ),\n",
- " ('__add__', ),\n",
- " ('__and__', ),\n",
- " ('__bool__', ),\n",
- " ('__ceil__', ),\n",
- " ('__class__', int),\n",
- " ('__delattr__',\n",
- " ),\n",
- " ('__dir__', ),\n",
- " ('__divmod__',\n",
- " ),\n",
- " ('__doc__',\n",
- " \"int(x=0) -> integer\\nint(x, base=10) -> integer\\n\\nConvert a number or string to an integer, or return 0 if no arguments\\nare given. If x is a number, return x.__int__(). For floating point\\nnumbers, this truncates towards zero.\\n\\nIf x is not a number or if base is given, then x must be a string,\\nbytes, or bytearray instance representing an integer literal in the\\ngiven base. The literal can be preceded by '+' or '-' and be surrounded\\nby whitespace. The base defaults to 10. Valid bases are 0 and 2-36.\\nBase 0 means to interpret the base from the string as an integer literal.\\n>>> int('0b100', base=0)\\n4\"),\n",
- " ('__eq__', ),\n",
- " ('__float__',\n",
- " ),\n",
- " ('__floor__', ),\n",
- " ('__floordiv__',\n",
- " ),\n",
- " ('__format__', ),\n",
- " ('__ge__', ),\n",
- " ('__getattribute__',\n",
- " ),\n",
- " ('__getnewargs__', ),\n",
- " ('__gt__', ),\n",
- " ('__hash__', ),\n",
- " ('__index__',\n",
- " ),\n",
- " ('__init__', ),\n",
- " ('__int__', ),\n",
- " ('__invert__',\n",
- " ),\n",
- " ('__le__', ),\n",
- " ('__lshift__',\n",
- " ),\n",
- " ('__lt__', ),\n",
- " ('__mod__', ),\n",
- " ('__mul__', ),\n",
- " ('__ne__', ),\n",
- " ('__neg__', ),\n",
- " ('__new__', ),\n",
- " ('__or__', ),\n",
- " ('__pos__', ),\n",
- " ('__pow__', ),\n",
- " ('__radd__', ),\n",
- " ('__rand__', ),\n",
- " ('__rdivmod__',\n",
- " ),\n",
- " ('__reduce__', ),\n",
- " ('__reduce_ex__', ),\n",
- " ('__repr__', ),\n",
- " ('__rfloordiv__',\n",
- " ),\n",
- " ('__rlshift__',\n",
- " ),\n",
- " ('__rmod__', ),\n",
- " ('__rmul__', ),\n",
- " ('__ror__', ),\n",
- " ('__round__', ),\n",
- " ('__rpow__', ),\n",
- " ('__rrshift__',\n",
- " ),\n",
- " ('__rshift__',\n",
- " ),\n",
- " ('__rsub__', ),\n",
- " ('__rtruediv__',\n",
- " ),\n",
- " ('__rxor__', ),\n",
- " ('__setattr__',\n",
- " ),\n",
- " ('__sizeof__', ),\n",
- " ('__str__', ),\n",
- " ('__sub__', ),\n",
- " ('__subclasshook__', ),\n",
- " ('__truediv__',\n",
- " ),\n",
- " ('__trunc__', ),\n",
- " ('__xor__', ),\n",
- " ('bit_length', ),\n",
- " ('conjugate', ),\n",
- " ('denominator', 1),\n",
- " ('from_bytes', ),\n",
- " ('imag', 0),\n",
- " ('numerator', 10),\n",
- " ('real', 10),\n",
- " ('to_bytes', )]"
- ]
- },
- "execution_count": 18,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "inspect.getmembers(a)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {
- "ein.tags": "worksheet-0",
- "slideshow": {
- "slide_type": "-"
- }
- },
- "source": [
- "# Adding Imenu Support"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {
- "ein.tags": "worksheet-0",
- "slideshow": {
- "slide_type": "-"
- }
- },
- "source": [
- "## Subheader"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {
- "ein.tags": "worksheet-0",
- "slideshow": {
- "slide_type": "-"
- }
- },
- "source": [
- "Seems to be a couple ways of doing this:\n",
- "\n",
- "1. Configuring a [imenu-generic-expression](http://emacswiki.org/emacs/ImenuMode#toc12) regex's.\n",
- "\n",
- "2. Redifining imenu-create-index ala python.el.\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 19,
- "metadata": {
- "autoscroll": false,
- "collapsed": false,
- "ein.hycell": false,
- "ein.tags": "worksheet-0",
- "slideshow": {
- "slide_type": "-"
- }
- },
- "outputs": [],
- "source": [
- "def func():\n",
- " pass\n",
- "\n",
- "\n",
- "class my_class(object):\n",
- " def __init__(self):\n",
- " pass\n",
- "\n",
- "\n",
- "class my_class(object):\n",
- " def __init__(self):\n",
- " pass\n",
- "\n",
- " def funcme(arg1):\n",
- " pass\n",
- "\n",
- "\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {
- "ein.tags": "worksheet-0",
- "slideshow": {
- "slide_type": "-"
- }
- },
- "source": [
- "# Another Header"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 2,
- "metadata": {
- "autoscroll": false,
- "collapsed": false,
- "ein.hycell": false,
- "ein.tags": "worksheet-0",
- "slideshow": {
- "slide_type": "-"
- }
- },
- "outputs": [
- {
- "ename": "ZeroDivisionError",
- "evalue": "division by zero",
- "output_type": "error",
- "traceback": [
- "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
- "\u001b[1;31mZeroDivisionError\u001b[0m Traceback (most recent call last)",
- "\u001b[1;32m\u001b[0m in \u001b[0;36m\u001b[1;34m()\u001b[0m\n\u001b[1;32m----> 1\u001b[1;33m \u001b[1;36m1\u001b[0m\u001b[1;33m/\u001b[0m\u001b[1;36m0\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m",
- "\u001b[1;31mZeroDivisionError\u001b[0m: division by zero"
- ]
- }
- ],
- "source": [
- "1/0"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 3,
- "metadata": {
- "autoscroll": false,
- "collapsed": false,
- "ein.hycell": false,
- "ein.tags": "worksheet-0",
- "slideshow": {
- "slide_type": "-"
- }
- },
- "outputs": [],
- "source": [
- "import inspect"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 4,
- "metadata": {
- "autoscroll": false,
- "collapsed": false,
- "ein.hycell": false,
- "ein.tags": "worksheet-0",
- "slideshow": {
- "slide_type": "-"
- }
- },
- "outputs": [],
- "source": []
- },
- {
- "cell_type": "code",
- "execution_count": 4,
- "metadata": {
- "autoscroll": false,
- "collapsed": false,
- "ein.hycell": false,
- "ein.tags": "worksheet-0",
- "slideshow": {
- "slide_type": "-"
- }
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "2"
- ]
- },
- "execution_count": 4,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "1+1"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 5,
- "metadata": {
- "autoscroll": false,
- "collapsed": false,
- "ein.hycell": false,
- "ein.tags": "worksheet-0",
- "slideshow": {
- "slide_type": "-"
- }
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- ""
- ]
- },
- "execution_count": 5,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "inspect"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 0,
- "metadata": {
- "autoscroll": false,
- "collapsed": false,
- "ein.hycell": false,
- "ein.tags": "worksheet-0",
- "slideshow": {
- "slide_type": "-"
- }
- },
- "outputs": [],
- "source": []
- }
- ],
- "metadata": {
- "kernelspec": {
- "display_name": "Python 3",
- "name": "python3"
- },
- "language_info": {
- "codemirror_mode": {
- "name": "ipython",
- "version": 3
- },
- "file_extension": ".py",
- "mimetype": "text/x-python",
- "name": "python",
- "nbconvert_exporter": "python",
- "pygments_lexer": "ipython3",
- "version": "3.4.3"
- },
- "name": "Development Ideas.ipynb"
- },
- "nbformat": 4,
- "nbformat_minor": 0
-}
diff --git a/EIN_Manual.org b/EIN_Manual.org
deleted file mode 100644
index c1f9fb4..0000000
--- a/EIN_Manual.org
+++ /dev/null
@@ -1,1105 +0,0 @@
-#+TITLE: The Emacs IPython Notebook Design Manual
-#+STARTUP: indent
-#+TYP_TODO: TODAY WEEK LATER
-
-* Overview
-** [ANN] The Continued Existence of the Emacs IPython Notebook
-
-After the recent, exciting announcement of the eminent [[https://conferences.oreilly.com/jupyter/jup-ny][JupyterCon]], I was
-somewhat saddened to see no mention of the EIN, or the Emacs IPython Notebook,
-as an available client to the Jupyter notebook server. Drama queen that I am, I
-quickly wrote a note to Fernando, who patiently and kindly explained that not
-many were aware that this project still existed and that perhaps an announcement
-or note to the main Jupyter list might be warranted. Hence the following, brief
-history. I also promise not to be a drama queen.
-
-Some of you may remember, from back when the Jupyter project was still known as
-the [[http://ipython.org/ipython-doc/rel-0.12/interactive/htmlnotebook.html][IPython notebook]], a talented and prolific coder of the name Takafumi
-Arakaki, or tkf, who created an alternative client to the notebook server's
-default web browser interface.
-
-This client, which he called the Emacs IPython Notebook (which you can still
-find his project on [[https://github.com/tkf/emacs-ipython-notebook][github]]), or EIN, provided a complete ipython notebook
-experience in the venerable Emacs editor. Not only was EIN nearly [[https://github.com/tkf/emacs-ipython-notebook/wiki/Screenshots][feature
-complete]] when compared to the browser interface it also provided some useful
-features for the Python programmer, like allowing one to [[https://github.com/tkf/emacs-ipython-notebook/wiki/Screenshots#connected-buffer][connect]] Python buffers
-to a notebook and using jedi for autocompletion in the notebook buffer.
-
-Around March/April of 2014, just as IPython was advancing towards 1.0 and making
-big changes in the notebook/contents API and the kernel communication protocol,
-tkf mysteriously stopped pushing commits to his github repository.
-
-I did not know tkf other than from a couple brief conversations. I sincerely
-hope tkf's story has a happy end (he does appear to still push the occasional
-[[https://github.com/tkf/comparatist][commit]]); he is clearly a talented programmer and without him this impressive
-piece of software would not exist.
-
-This is the point where yours truly enters the story. I had discovered the
-IPython notebook the previous year and had found it an exteremly useful for
-analyzing the performance of catalytic process units in the refining industry
-and working with Python in general, but being a long-time Emacs user I had
-somewhat bounced of the web interface. Discovering EIN was a godsend, and it
-quickly became a mainstay in my set of analytic tools.
-
-Unfortunately the changes in going to v1.0 of the ipython notebook broke EIN,
-and with tkf apparently out of the picture there did not seem much hope in EIN
-staying compatible. Considering that I am a father of two with a full-time job
-that has absolutely nothing to do with programming (and yet I am a long-time
-Emacs user - it's complicated, don't ask), I can only describe what happened
-next as an act of complete insanity: I decided to fork tkf's code, dig in and
-try to keep up with the changes in ipython.
-
-Truthfully, no one was more surprised than I when I was actually able to keep
-ein working with versions 1.0 and, soon after, 2.0 of IPython. In fact that
-compatibility, in theory, is still in the code. One, again in theory, should be
-able to fire up a 1.x or 2.x version of the IPython notebook and connect to it
-using my fork of EIN. I say in theory, though, as I haven't touched that part of
-the code in some time and it undoubtedly has suffered some bit rot in the
-intervening years.
-
-The rest of the story is less interesting. Eventually I managed to convince
-github and MELPA to treat my repository as the official version of ein. There
-was some short-lived talk of renaming my fork to 'zwei', but the consensus was
-that things were confusing enough with the change in ownership and to keep the
-name as ein.
-
-Currently one can download ein through either [[http://melpa.org/#/ein][MELPA]] or [[https://github.com/dimitri/el-get][el-get]], and someone has
-even been kind enough to create a spacemacs [[http://spacemacs.org/layers/+lang/ipython-notebook/README.html][layer]] with convenient VIM
-keybindings for the heathens.
-
-At the moment EIN supports the recent incarnations of Jupyter, v4.3.1, token
-authentication, _xsrf cookies and all. By the time you read this I may even have
-pushed some commits that allow one to start and automatically log in to a
-jupyter notebook server all from Emacs without having to drop into the terminal.
-
-In all, EIN continues to be a viable alternative to the web browser client. It
-is not 100% feature complete, though, as it notably does not support widgets and
-quite possibly never will.
-
-I haven't kept close track of who is using EIN, but it has 341 stars on github
-and 28,175 downloads from MELPA. I know EIN is being used in at least a couple
-businesses and from what I have heard it tends to be more popular among those
-with a programming background - scientists and engineers tend to prefer the web
-client which is not surprising since Emacs is not so much a text editor as it is
-a Way of Life.
-
-I encourage anyone who is interested in trying out ein to install it via MELPA
-or from the spacemacs ipython-notebook layer. There is [[http://millejoh.github.io/emacs-ipython-notebook/][documentation]], but it is
-not perfect and I cannot guarantee it is 100% correct. Do not hesitate to open
-an [[https://github.com/millejoh/emacs-ipython-notebook/issues][issue]] on github if you run into troubles, this is a hobby project but I do my
-best to support it.
-
-If you have made it this far then my sincere thanks for staying patient through
-my ramblings. As a parting thought I want to express my sincere thanks to
-Takafumi Arakaki, wherever he may be, and to the [[http://jupyter.org/about.html][Jupyter]] team for their
-fantastic work in creating this amazing piece of software.
-
-* Reference
-** [[https://cask.readthedocs.io/en/latest/index.html][Cask]]
-** Learning Git
-https://help.github.com/articles/about-pull-requests/
-https://yangsu.github.io/pull-request-tutorial/
-
-** Testing
-ert.
-
-[[https://github.com/ecukes/ecukes][ecukes]].
-
-Travis token: 2yP9mWPstlPi9kUoK9DIKw 2yP9mWPstlPi9kUoK9DIKw
-
-* Design
-** Version update checklist:
-
-- ein.el
-- ein-pkg.el
-- ein-core.el
-- doc/source/conf.py
-
-** Notebook Security
-Life gets more complicated with jupyter notebook [[https://blog.jupyter.org/2016/12/21/jupyter-notebook-4-3-1/][v4.3.1]], though the intentions
-are purely altruistic. The notebook server now requires a
-~[[http://www.tornadoweb.org/en/stable/guide/security.html#cross-site-request-forgery-protection][xsrf]]~
-token via cookies to validate requests.
-
-If I interpret the documentation correctly, a successful login should set a
-_xsrf cookie, which then needs to be included in the header with all additional
-REST queries.
-
-What is supposed to happen when EIN connects to a token-enabled notebook server.
-
-If we are using the curl backend for request:
-
-Once a user succesfully authenticates against a running jupyter server via
-either ~ein:notebooklist-login~ curl will store two cookies in the
-~curl-cookie-jar~ file. The location of this file is set by the variable
-~[[help:request-storage-directory][request-storage-directory]]~. One cookie is
-for the token authentication, and the other is the xsrf token. [[*Example curl cookie jar file][Below]] is an
-example of cookies that were set after authenticating against a jupyter notebook
-server running on my personal aws instance. On subsequent calls to the content
-API request/curl will automatically supply the correct cookies. The websocket
-package uses the ~[[info:url#Top][url]]~ package to set cookies, and so will not
-know about the authentication and ~xsrf~ tokens unless EIN does some extra work.
-EIN does this in the
-~[[file:c:/Users/mille/Dropbox/Projects/emacs-ipython-notebook/lisp/ein-websocket.el::(defun
-ein:websocket--prepare-cookies (url)][ein:websocket--prepare-cookies]]~
-function. The function does some extra work to only copy over cookies pertaining
-to the host the websocket is connecting on.
-
-
-*** Example curl cookie jar file
-
-ec2-13-58-41-203.us-east-2.compute.amazonaws.com FALSE / FALSE 0 _xsrf 2|164f26da|390fef85a22a21f913024720d16e0328|1535314712
-#HttpOnly_ec2-13-58-41-203.us-east-2.compute.amazonaws.com FALSE / TRUE 1539117935 username-ec2-13-58-41-203-us-east-2-compute-amazonaws-com-8888 "2|1:0|10:1536525935|62:username-ec2-13-58-41-203-us-east-2-compute-amazonaws-com-8888|44:NmMwYzg5NDA2MDBkNDVjNzk1MmY3ZGEwMzg0ZDUwNTA=|b975a41e86cea678fd2b97be9e447254bdb109e7e04e8f72f74fe6a151812c4d"
-
-** Notebook Format
-
-Version 4.0 [[http://nbformat.readthedocs.org/en/latest/][documented]].
-
-Earlier versions might be documented less formally on the wiki. Can
-also look at the IPython source in the json files.
-
-** Notebook Buffer
-
-Notebook information is stored as a [[file:lisp/ein-notebook.el::ein:$notebook][struct]]. Always associated with a buffer,
-[[file:lisp/ein-notebook.el::ein:notebook-buffer][ein:notebook-buffer]] is used to find buffer associated with a notebook.
-
-Notebook does not hold cells, that is delegated to instances of the [[file:emacs-ipython-notebook/lisp/ein-worksheet.el::ein:worksheet][worksheet]]
-class. Instances are stored as a list in the ~ein:$notebook-worksheets~ slot.
-
-Opened notebooks are kept in the ~ein:notebook--opened-map~ hash
-table. Keys are cons cells of ~url-or-port~ and ~path~.
-
-There are a number of helper functions for returning the struct for an opened notebook:
-
- - ~[[file:lisp/ein-notebook.el::(defun ein:notebook-get-opened-notebook (url-or-port path)][ein:notebook-get-opened-notebook]]~ ::
- - ~[[file:lisp/ein-notebook.el::(defun ein:notebook-get-opened-buffer (url-or-port path)][ein:notebook-get-opened-buffer]]~ ::
-
-** Notebooklist Buffer
-** Cell Execution
-Entry point is usually
-~[[file:~/Dropbox/Projects/emacs-ipython-notebook/lisp/ein-worksheet.el::(defun ein:worksheet-execute-cell (ws cell)][ein:worksheet-execute-cell-and-goto-next]]~,
-but the fun doesn't really start until we get to ~ein:cell-execute~.
-
-The cell [[file:~/Dropbox/Projects/emacs-ipython-notebook/lisp/ein-classes.el::(defclass%20ein:basecell%20()][class]] (if it is a codecell) will know the kernel it is associated with,
-and the actual code gets run via ~ein:kernel-execute~. The callbacks are set via
-~ein:cell-make-callbacks~, which make sure the cell output is updated
-appropriate after the kernel finishes executing the code.
-
-
-*** Patching to automatically detect hy code
-
-We could subclass ein:codecell and make an ein:hy-codecell class. Then we could have a
-specialized ein:cell-execute-internal which run a pytools helper that parses and
-evaluates the hy code.
-
-** Kernel communication
-
-The [[https://jupyter-client.readthedocs.io/en/latest/messaging.html#messaging][messaging protocol]].
-
-** Contents API
-
-Documented at the IPython Github [[https://github.com/ipython/ipython/wiki/IPEP-27%253A-Contents-Service][wiki.]]
-
-There is also [[http://petstore.swagger.io/?url=https://raw.githubusercontent.com/jupyter/notebook/master/notebook/services/api/api.yaml][another]] great online resource for session and kernel
-REST API.
-
-** Connecting to a running Kernel
-Entry point is ~[[file:lisp/ein-notebook.el::ein:notebook-start-kernel][ein:notebook-start-kernel]]~ which is called from
-~ein:notebook-request-open-callback~ after successful call to the notebook
-server requesting the contents of a given notebook.
-
-~[[file:lisp/ein-kernel.el::ein:kernel-start][ein:kernel-start]]~ starts/gets a session with a running kernel using the REST API.
-
-On a [[file:lisp/ein-kernel.el::ein:kernel--kernel-s][successful]] return ein [[file:lisp/ein-websocket.el::ein:websocket][creates]] a websocket channel (channels for
-IPython 2.x) via a call to ~websocket-open~ in the [[https://github.com/ahyatt/emacs-websocket][emacs-websocket]]
-package. The URL request is of the form:
-
-#+BEGIN_QUOTE
-ws://{server_address}:{port}/api/kernels/{kernel id from previous REST query}/channels?session_id={session id}
-#+END_QUOTE
-
-** How a Worksheet is Displayed
-EIN relies heavily on EIEIO and EWOC.
-
-EWOC information is stored as part of the ~[[file:emacs-ipython-notebook/lisp/ein-cell.el::(defclass ein:basecell ()][ein:basecell]]~ class. Presumably there
-are cells for input and output (when input is code) nodes???
-
-EWOC PP eventually calls ~[[file:lisp/ein-cell.el::ein:cell-append-mime-type][ein:cell-append-mime-type]]~ for output. Latex is
-considered text, but should be able to convert to image using dvitopng,
-imagemagick, other?
-
-** Jupyterhub Integration
-
-REST API [[http://jupyterhub.readthedocs.io/en/latest/api/index.html][documentation]] (and in [[http://petstore.swagger.io/?url%3Dhttps://raw.githubusercontent.com/jupyterhub/jupyterhub/master/docs/rest-api.yml#!/default][swagger]]).
-
-There is a login request (http[s]://{url}/hub/login). But it doesn't seem to
-work so well unless you are in a browser.
-
-Jupyterhub requires authentication using username/password, as opposed to just
-providing a secret when logging into ipython 3.x and earlier.
-
-On logging in a cookie of form "jupyter-hub-token-" is generated and
-propogated with all calls to server. Emacs request should automatically handle
-this.
-
-Also looks like the content REST API has been modified so that queries are of the
-form: /user//.
-
-*** [[https://jupyterhub.readthedocs.io/en/latest/howitworks.html][How Jupyterhub works]]
-
-Steps:
-
-1. +Log in at the hub via ~/hub/login~+. Get a token from the authenticator by
- POST'ing to ~[[https://jupyterhub.readthedocs.io/en/latest/_static/rest-api/index.html#path--authorizations-token][/authorizations/token]]~. The authenticator returns an API token if
- succesful. Doesn't work with OAuth.
-2. Logging in sets two cookies, one for ~/hub~ and other for ~/user/[username]~
- with encrypted token. (Also for ~/authorizations/token~?)
-3. Access the user's single instance jupyter via ~/user/[username]~. This will
- return a [[https://jupyterhub.readthedocs.io/en/latest/_static/rest-api/index.html#/definitions/User][user]] json object that has the address of the user's notebook server.
-
-To use the REST API need to have an [[https://jupyterhub.readthedocs.io/en/latest/rest.html][API token]]?
-
-*** Sample Code
-#+BEGIN_SRC ein :session 8888/JupyterHub.ipynb :results drawer
- import requests
-
- api_login = 'http://192.168.0.13:8000/hub/login'
- user = 'millejoh'
- password = 'number10ox'
-
- r = requests.post(api_login,
- data={
- 'username':user,
- 'password':password
- }
- )
-
- r.raise_for_status()
- r
-#+END_SRC
-
-#+RESULTS:
-
-
-Per the documentation you need to supply an authorization token with requests to
-server:
-
-#+BEGIN_SRC ein :session 8888/Untitled.ipynb
- import requests
-
- api_url = 'http://192.168.0.13:8000/hub/api'
- token = ''
-
- r = requests.get(api_url + '/users',
- headers={
- 'Authorization': 'token %s' % token,
- }
- )
-
- r.raise_for_status()
- users = r.json()
- users
-#+END_SRC
-
-#+RESULTS:
-
-* Enhancements/Fixes
-
-** Refactor Kernel Communication
-
-New module to start kernel session and handle communication built off deferred.
-
-** Seamless Jupyterhub and ssh support
-For jupyterhub need to support its multiple authentication methods.
-
-For ssh need to figure out how to set cookies when tunneling.
-
-See [[https://elpa.gnu.org/packages/oauth2.html][emacs-oauth2]].
-
-** Integrate with eldoc
-
-Hook is through buffer local variable ~eldoc-documentation-function~, which is a
-function of no variables that returns the docstring for the object at point.
-
-** Inspector
-The way it works:
-
- 1. Get the object at point, which will be a string representing a python object.
- 2. Send that string via the kernel to python code that does some introspection
- and returns a json representation of the object.
- 3. Create a buffer and prettily display the data returned by the kernel.
-
-The way that pycharm does it is that each variable has it's own line with the format:
-
-#+BEGIN_CENTER
-~/variable name/ = {/type/} /value/~
-#+END_CENTER
-
-If the object is made up of many items- like a module, list, class- then you can
-expand the object and see its individual elements. Hence why we are so
-interested in a easy to use folding overlay system thingy.
-
-Spyder has a [[https://pythonhosted.org/spyder/variableexplorer.html][variable explorer]] and its UI is a modal dialog that displays a
-table of information.
-
-The active console variables of Pycharm is neat, we should borrow and steal.
-
-*** LATER Prototype Folding Overlay
-Maybe first adapt abstract display [[info:elisp#Abstract%20Display%20Example][example]] to current inspector display code?
-
-Or adapt magit [[file:c:/Users/mille/OneDrive/Documents/GitHub/magit/lisp/magit-section.el::(defgroup%20magit-section%20nil][sections]].
-
-Use the [[info:elisp#Abstract%20Display][abstract display]] and [[info:elisp#Overlays][overlays]] for displaying, managing the buffer?
-
-Should take some time to understand how magit manages its buffers. Magic seems to happen
-in ~[[magit-insert-section][magit-insert-section]]~.
-
-Magit's sections are interesting, but I do not think I am smart enough to use
-them. I really would like to avoid reinventing the wheel, but maybe I can get by
-just reinventing the spokes.
-
-#+BEGIN_SRC elisp
- (require 'cl-lib)
- (require 'dash)
-
- (cl-defstruct $section
- type content parent children)
-
- (defun section:new ()
-
- )
-#+END_SRC
-
-#+RESULTS:
-: section:new
-
-*** Introspection
-For inspecting, think of something like in [[https://common-lisp.net/project/slime/doc/html/Inspector.html#Inspector][SLIME]]. No good pictures there, but
-this [[http://malisper.me/2015/07/14/debugging-lisp-part-2-inspecting/][blog]] does a bit better.
-
-Python has facilities for [[https://docs.python.org/3/library/inspect.html][introspection]]. There is also the [[https://docs.python.org/3/library/pyclbr.html#module-pyclbr][pyclbr]], a module for
-implementing a class browser. Jedi has excellent facilities for static analysis
-of code.
-
-IPython wraps the python inspector with ~IPython.core.oinspect~ module.
-
-First let's create a few inspectable objects:
-#+NAME: cee67d1f-dc69-41e8-a109-a3fb78e2990b
-#+BEGIN_SRC ein :session 8888/Brain/Inspector.ipynb
- import numpy as np
-
- num = 1.0
- lst = [0,1,2,3]
- hash = {'a':0, 'b':1, 'c':2}
-
- def fn(a,b):
- return a+b
-
- class Hello(object):
- def __init__(self):
- self.num = 1.0
- self.lst = [0,1,2,3]
- self.hash = {'a':0, 'b':1, 'c':2}
-
- def fn(self, a, b):
- return a+b
-
- def fn2(a, b):
- return Hello().fn(a,b)
-#+END_SRC
-
-#+RESULTS: cee67d1f-dc69-41e8-a109-a3fb78e2990b
-: ---------------------------------------------------------------------------
-ModuleNotFoundError Traceback (most recent call last)
- in
-----> 1 import numpy as np
- 2
- 3 num = 1.0
- 4 lst = [0,1,2,3]
- 5 hash = {'a':0, 'b':1, 'c':2}
-
-ModuleNotFoundError: No module named 'numpy'
-
-
-#+RESULTS:
-#+begin_example
----------------------------------------------------------------------------
-ModuleNotFoundError Traceback (most recent call last)
- in ()
-----> 1 import numpy as np
- 2
- 3 num = 1.0
- 4 lst = [0,1,2,3]
- 5 hash = {'a':0, 'b':1, 'c':2}
-
-ModuleNotFoundError: No module named 'numpy'
-#+end_example
-
-Now let's inspect:
-
-#+BEGIN_SRC ein :session 8888/emacs-ipython-notebook/Inspector.ipynb
- import inspect
-
- hello = Hello()
-
- sig = inspect.signature(fn)
- dir(sig)
-#+END_SRC
-
-#+RESULTS:
-#+begin_example
----------------------------------------------------------------------------
-NameError Traceback (most recent call last)
- in ()
- 1 import inspect
- 2
-----> 3 hello = Hello()
- 4
- 5 sig = inspect.signature(fn)
-
-NameError: name 'Hello' is not defined
-#+end_example
-
-Tactic is to wrap information returned by the inspect module.
-
-#+BEGIN_SRC elisp :session t
- (defclass ein:iobject ()
- ((name :accessor ein:iobject-name :documentation "String representation can be evaluated in python to generate the object being inspected.")
- (kernel :accessor ein:iobject-kernel :documentation "Kernel where the object exists."))
- :documentation "Class to hold information returned by Python `inspect` module for a Python object identified in the `name` slot.")
-#+END_SRC
-
-#+RESULTS:
-: ein:iobject
-
-Is it time to use deferred for kernel execute queries?
-
-#+BEGIN_SRC elisp :session t
- (ein:kernel-execute (ein:iobject-kernel))
-
- ein:iobject
-#+END_SRC
-
-*** Mockup for inspector
-
-**** Classes
- <--- Hyperlink to source definition?
--------------------------------
-Class:
-Module defined in?
--------------------------------
-Collapsable documentation?
--------------------------------
-
-All slots:
-
-[set] slot_name = slot_value
-[set] slot2_name = slot2_value
-
-**** Functions/Callables
-**** Generator
-**** Coroutine
-**** Builtin
-**** Module
-*** Variable watchlist
-
-** Pymacs w/ein-kernel as a backend
-
-Not sure if pymacs still works, but wouldn't it be cool to have Pymacs
-have the ability to interact with Jupyter kernels?
-
-What we want is to translate Python datastructures to lisp and vice versa. Not
-sure what the wire protocol is for pymacs, but for ein the intermediary is JSON.
-
-Do this like in
-
-** A Tramp backend for EIN
-*** Finding files for remote session ([[https://github.com/millejoh/emacs-ipython-notebook/issues/263][#263]])
-sam-s suggests using tramp.
-*** Make notebooks more file-like?
-
-Start by setting ~[[help:set-visited-file-name][set-visitied-file-name]]~, but what about notebooks from remote
-servers? This is dangerous as it could result in the buffer accidentally getting
-written to disk using Emacs, bypassing conversion into JSON and irreparably
-corrupting the notebook.
-
-Make EIN buffer/notebook names "[[info:elisp#Magic%20File%20Names][magic]]"?
-
-Is is it possible to define new type of [[info:emacs#Remote%20Files][remote]] files? For jupyter have something
-like ~/ein:HOST:FILENAME~. Sounds possible by configuring ~[[help:tramp-methods][tramp-methods]]~. NO!
-Won't work as TRAMP calls out to external processes.
-** Integrating other Emacs python tools
-*** Integrate with [[https://github.com/donkirkby/live-py-plugin][live-py-plugin]]
-*** Refactoring support?
-Via [[https://github.com/python-rope/rope/blob/master/docs/library.rst][rope]]?
-** Proper command history
-[[http://jupyter-client.readthedocs.io/en/latest/messaging.html#history][Documentation]] for the jupyter protocol.
-
-EIN's interface is through [[file:emacs-ipython-notebook/lisp/ein-worksheet.el::(defun%20ein:worksheet-previous-input-history%20(ws%20cell%20index)][ein:worksheet-previous-input-history]].
-
-Looks like EIN is using history protocol supplied by kernel, but I don't fully
-understand difference betwee 'range', 'tail' and 'search' access types.
-
-** Run dynamic javascript
-
-The development [[ipynb:(:url-or-port%208888%20:name%20"emacs-ipython-notebook/Embedding%20Altair%20Graphs.ipynb")][notebook]].
-
-Emacs is not a web browser, hence does not know how to execute javascript.
-
-Maybe we can get around this using [[https://github.com/skeeto/skewer-mode][skewer-mode]] or [[http://js-comint-el.sourceforge.net/][js-comint.el]].
-
-Skewer-mode uses JS client provided by a web browser, while js-comint depends on
-nodejs (you understand this difference, right? Right?).
-
-Skewer mode seems to work for basic javascript evaluation, and according to
-comments in [[https://github.com/millejoh/emacs-ipython-notebook/issues/65#issuecomment-322084969][github]] it might be possible to get things like bokeh graphs working.
-
-Another thought is to get python to do this for us. The packages [[][naked]] (an
-unfortunate name given my corporate firewall) and [[https://github.com/doloopwhile/PyExecJs][PyExecJs]].
-
-What does the html for a notebook cell output look like?
-
-#+BEGIN_SRC html
-
-
-
-
-
-
-
-
-
-
Out[3]:
-
<tf.Tensor 'MatMul:0' shape=(1, 1) dtype=float32>
-
-
-
-
. . .
-
-#+END_SRC
-*** Embedding [[https://github.com/ellisonbg/altair][Altair]] plots
-
-First get [[*Run dynamic javascript][dynamic javascript]] working...
-
-Relevant [[https://github.com/vega/ipyvega/issues/31][issue]], [[https://github.com/vega/ipyvega/pull/32][pull request]] and [[https://github.com/ellisonbg/ipyvega/blob/be19059068557c44cbdcbcf5ad509c3312b25763/src/index.js][code]].
-
-Appears the code has capability of returning javascript and png output. When
-calling from ein all that gets returned is javascript, which
-`ein:cell-append-mime-type` chokes on.
-
-Somehow, when running [[https://nbconvert.readthedocs.io/en/latest/][nbconvert]], the javascript gets turned into a png. How to trigger
-that when normally executing cells?
-*** XWidget Support/Interactive Widgets
-
-For the most part this is a non-starter since in Jupyter this is built on web
-and javascript, but maybe with emacs 25's coming integration with [[https://www.emacswiki.org/emacs/EmacsXWidgets][xwidgets]] there
-is hope?
-
-**** What Does ipywidgets.interact() return?
-
-A call to `ipywidgets.interact()` creates a [[http://jupyter-client.readthedocs.org/en/latest/messaging.html#custom-messages][custom communications channel]]
-with the jupyter server.
-
-1. What are message types (msg_type) comm_msg and comm_open for?
-
- These are received when calling interact().
-
-***** Websocket data for comm_open
-#+BEGIN_SRC
-[WS] Received: {"msg_id": "56821eaa-cc32-4a34-bac3-8468ea08b7a0", "content": {"execution_state": "busy"}, "channel": "iopub", "metadata": {}, "msg_type": "status", "buffers": [], "header": {"username": "username", "session": "eb518e76-61af-4bff-9fb0-49fb78883056", "msg_id": "56821eaa-cc32-4a34-bac3-8468ea08b7a0", "date": "2016-03-24T07:24:50.879558", "version": "5.0", "msg_type": "status"}, "parent_header": {"username": "username", "session": "5b01e727-3ce9-416f-bb67-f9400b719e33", "msg_id": "6dd8ea4c-325a-4938-8ad9-d68e2e4dbb0b", "date": "2016-03-24T07:24:50.879558", "version": "5.0", "msg_type": "execute_request"}} {"msg_id": "95f88fb5-2e4b-45b5-b78b-79d9274d392a", "content": {"execution_count": 3, "code": "interact(f, x=10)"}, "channel": "iopub", "metadata": {}, "msg_type": "execute_input", "buffers": [], "header": {"username": "username", "session": "eb518e76-61af-4bff-9fb0-49fb78883056", "msg_id": "95f88fb5-2e4b-45b5-b78b-79d9274d392a", "date": "2016-03-24T07:24:50.879558", "version": "5.0", "msg_type": "execute_input"}, "parent_header": {"username": "username", "session": "5b01e727-3ce9-416f-bb67-f9400b719e33", "msg_id": "6dd8ea4c-325a-4938-8ad9-d68e2e4dbb0b", "date": "2016-03-24T07:24:50.879558", "version": "5.0", "msg_type": "execute_request"}} {"msg_id": "ef75371f-9047-46de-8eda-2c8697e2b60b", "content": {"data": {"width": "", "_model_name": "BoxModel", "font_size": "", "children": [], "overflow_x": "", "padding": "", "font_style": "", "_dom_classes": ["widget-interact"], "box_style": "", "height": "", "_view_module": "", "margin": "", "color": null, "msg_throttle": 3, "border_color": null, "font_family": "", "_view_name": "BoxView", "_model_module": null, "version": 0, "overflow_y": "", "background_color": null, "font_weight": "", "_css": [], "border_width": "", "visible": true, "border_style": "", "border_radius": ""}, "target_name": "ipython.widget", "comm_id": "237329515cca473985d6fa52ec0c93a1", "target_module": null}, "channel": "iopub", "metadata": {}, "msg_type": "comm_open", "buffers": [], "header": {"username": "username", "session": "eb518e76-61af-4bff-9fb0-49fb78883056", "msg_id": "ef75371f-9047-46de-8eda-2c8697e2b60b", "date": "2016-03-24T07:24:50.910702", "version": "5.0", "msg_type": "comm_open"}, "parent_header": {"username": "username", "session": "5b01e727-3ce9-416f-bb67-f9400b719e33", "msg_id": "6dd8ea4c-325a-4938-8ad9-d68e2e4dbb0b", "date": "2016-03-24T07:24:50.879558", "version": "5.0", "msg_type": "execute_request"}}
-#+END_SRC
-
-***** Websocket data for comm_msg
-#+BEGIN_SRC emacs-lisp
-[WS] Received: {"msg_id": "fe357d60-e83a-49ac-821f-7d99cdf20b8a", "content": {"data": {"description": "", "orientation": "horizontal", "continuous_update": true, "_model_name": "WidgetModel", "font_size": "", "step": 1, "background_color": null, "padding": "", "slider_color": null, "height": "", "_view_module": "", "margin": "", "color": null, "width": "", "font_family": "", "border_color": null, "_dom_classes": [], "min": -10, "_range": false, "disabled": false, "_model_module": null, "_view_name": "IntSliderView", "max": 30, "version": 0, "font_style": "", "msg_throttle": 3, "value": 10, "readout": true, "font_weight": "", "_css": [], "border_width": "", "visible": true, "border_style": "", "border_radius": ""}, "target_name": "ipython.widget", "comm_id": "c1059008e6d046209c9d63de036c1aff", "target_module": null}, "channel": "iopub", "metadata": {}, "msg_type": "comm_open", "buffers": [], "header": {"username": "username", "session": "eb518e76-61af-4bff-9fb0-49fb78883056", "msg_id": "fe357d60-e83a-49ac-821f-7d99cdf20b8a", "date": "2016-03-24T07:24:50.948495", "version": "5.0", "msg_type": "comm_open"}, "parent_header": {"username": "username", "session": "5b01e727-3ce9-416f-bb67-f9400b719e33", "msg_id": "6dd8ea4c-325a-4938-8ad9-d68e2e4dbb0b", "date": "2016-03-24T07:24:50.879558", "version": "5.0", "msg_type": "execute_request"}} {"msg_id": "30514644-45e1-45c7-a5db-42c9ee22e9ec", "content": {"data": {"buffers": [], "state": {"description": "x"}, "method": "update"}, "comm_id": "c1059008e6d046209c9d63de036c1aff"}, "channel": "iopub", "metadata": {}, "msg_type": "comm_msg", "buffers": [], "header": {"username": "username", "session": "eb518e76-61af-4bff-9fb0-49fb78883056", "msg_id": "30514644-45e1-45c7-a5db-42c9ee22e9ec", "date": "2016-03-24T07:24:50.964124", "version": "5.0", "msg_type": "comm_msg"}, "parent_header": {"username": "username", "session": "5b01e727-3ce9-416f-bb67-f9400b719e33", "msg_id": "6dd8ea4c-325a-4938-8ad9-d68e2e4dbb0b", "date": "2016-03-24T07:24:50.879558", "version": "5.0", "msg_type": "execute_request"}} {"msg_id": "fc005b54-774c-4920-860f-cec08cb5b5ba", "content": {"data": {"buffers": [], "state": {"children": ["IPY_MODEL_c1059008e6d046209c9d63de036c1aff"]}, "method": "update"}, "comm_id": "237329515cca473985d6fa52ec0c93a1"}, "channel": "iopub", "metadata": {}, "msg_type": "comm_msg", "buffers": [], "header": {"username": "username", "session": "eb518e76-61af-4bff-9fb0-49fb78883056", "msg_id": "fc005b54-774c-4920-860f-cec08cb5b5ba", "date": "2016-03-24T07:24:50.964124", "version": "5.0", "msg_type": "comm_msg"}, "parent_header": {"username": "username", "session": "5b01e727-3ce9-416f-bb67-f9400b719e33", "msg_id": "6dd8ea4c-325a-4938-8ad9-d68e2e4dbb0b", "date": "2016-03-24T07:24:50.879558", "version": "5.0", "msg_type": "execute_request"}} {"msg_id": "65240518-737e-4614-8ad1-7d9fcfc567bd", "content": {"data": {"method": "display"}, "comm_id": "237329515cca473985d6fa52ec0c93a1"}, "channel": "iopub", "metadata": {}, "msg_type": "comm_msg", "buffers": [], "header": {"username": "username", "session": "eb518e76-61af-4bff-9fb0-49fb78883056", "msg_id": "65240518-737e-4614-8ad1-7d9fcfc567bd", "date": "2016-03-24T07:24:50.964124", "version": "5.0", "msg_type": "comm_msg"}, "parent_header": {"username": "username", "session": "5b01e727-3ce9-416f-bb67-f9400b719e33", "msg_id": "6dd8ea4c-325a-4938-8ad9-d68e2e4dbb0b", "date": "2016-03-24T07:24:50.879558", "version": "5.0", "msg_type": "execute_request"}} {"msg_id": "6b0b41e2-5af0-4690-9902-9e73a61cf0e3", "content": {"wait": true}, "channel": "iopub", "metadata": {}, "msg_type": "clear_output", "buffers": [], "header": {"username": "username", "session": "eb518e76-61af-4bff-9fb0-49fb78883056", "msg_id": "6b0b41e2-5af0-4690-9902-9e73a61cf0e3", "date": "2016-03-24T07:24:50.964124", "version": "5.0", "msg_type": "clear_output"}, "parent_header": {"username": "username", "session": "5b01e727-3ce9-416f-bb67-f9400b719e33", "msg_id": "6dd8ea4c-325a-4938-8ad9-d68e2e4dbb0b", "date": "2016-03-24T07:24:50.879558", "version": "5.0", "msg_type": "execute_request"}}
-#+END_SRC
-** Inline latex
-See issue [[https://github.com/millejoh/emacs-ipython-notebook/issues/88][#88]].
-
-*** For Further Investigation
-
-- [[https://github.com/zk-phi/magic-latex-buffer][magic-latex-buffer.el]]
-- [[https://www.gnu.org/software/auctex/preview-latex.html][preview-latex.el]]
-- Another [[https://github.com/aaptel/preview-latex/][preview-latex]] package (based on org-latex-preview).
-
-*** Inline using org-latex-preview
-
-[[http://orgmode.org/manual/Previewing-LaTeX-fragments.html#Previewing-LaTeX-fragments][Documentation]] for this facility in org.
-
-Does it work here?
-
-\begin{equation}
-x=\sqrt{b}
-\end{equation}
-
-Some inline Latex math $a^2=b$.
-
-Yes, but nedd MiKTeX installed if on windows.
-
-If org-latex-preview is working then [[https://github.com/aaptel/preview-latex][p]]x will also work, though the code for
-~[[file:~/.emacs.d/elpa/px-20141006.548/px.el::(defun px--create-preview (at)][px--create-preview]]~ needs to be patched as the signature for `org-format-latex`
-has changed.
-
-*** Using magic-latex-buffer
-Per the [[https://github.com/zk-phi/magic-latex-buffer][documentation]] all you need to do to configure is to add a hook:
-
-#+BEGIN_SRC emacs-lisp
- (add-hook 'latex-mode-hook 'magic-latex-buffer)
-#+END_SRC
-
-#+RESULTS:
-
-Or manually activate by calling ~M-x magic-latex-buffer~.
-
-Use variable ~ein:notebook-first-open-hook~ to enable?
-
-This works, at least for viewing, but the images that get inserted confuse ein
-when saving a notebook and generate errors in Jupter. Can be worked around by
-disabling ~magic-latex-buffer~ before saving. One hack is to advise
-~ein:notebook-save-notebook-command~?
-
-#+BEGIN_SRC emacs-lisp
- (defvar ein:magic-latex-enabled-p nil)
-
- (defun ein:disable-magic-latex-maybe (&rest args)
- (when ein:magic-latex-enabled-p
- (ein:log 'debug "Disabling magic-latex.")
- (magic-latex-buffer -1)))
-
- (defun ein:enable-magic-latex-maybe (&rest args)
- (when ein:magic-latex-enabled-p
- (ein:log 'debug "Enabling magic-latex.")
- (magic-latex-buffer t)))
-
- (advice-add #'ein:notebook-save-notebook :before #'ein:disable-magic-latex-maybe)
- (advice-add #'ein:notebook-save-notebook :after #'ein:enable-magic-latex-maybe)
-
- (advice-add #'ein:cell-execute-internal :before #'ein:disable-magic-latex-maybe)
- (advice-add #'ein:cell-execute-internal :after #'ein:enable-magic-latex-maybe)
-
-#+END_SRC
-** The Return of Worksheets
-
-tkf/ein and IPython 2.x allowed for multiple worksheets within an individual
-notebook. This feature was removed in 3.0 since multiple worksheets do not make
-much sense in the context of a tabbed web browser interface. EIN's legacy code
-still supports worksheets, though at the moment that information is lost upon
-saving a notebook.
-
-Having multiple worksheet support makes some sense for ein; below is thinking on
-how to reimplement this feature.
-
-IPython nbformat 4 specifies a [[http://ipython.org/ipython-doc/3/notebook/nbformat.html#metadata][metadata]] key which can be used to store general
-information. Cell metadad has a tag key which is a "A list of string tags on the
-cell. Commas are not allowed in a tag."
-
-Best place to set the tag key is when generating [[content]] for saving a notebook.
-** Outside Wish and Bug List
-*** Wishlist
-
-- [X] switch kernel (4 hours)
-
-- [X] getting a true Python mode when editing code in cells, without messing up the
- other formatting (8 hours)
-
-- [X] Auto-saving and checkpoints (4 hours)
-
-- [X] Save a copy of the notebook (1 hour)
-
-- [ ] If one cuts and pastes read-only text into a cell it can’t be edited
-
-- [ ] A full undo history
-
-- [ ] Command history / autocomplete like one gets in regular ipython
-
-- [ ] Image resizing
-
-- [X] Better debug support (maybe via [[https://github.com/realgud/realgud][realgud]]?)
-
-*** Bugs
-
-- [X] emacs ipython notebook fails to follow redirects properly - This is mainly
- due to the fact that it holds on the original site name internally.
-
-- [X] cookie expiration for long running notebooks - On long running notebooks
- tornado's default cookie expiration is 30 days. After the cookie expires emacs
- will continue to attempt autosave, but the notebook will not save. The
- workaround is to run ein:notebooklist-open to generate a new GET request
- against /login to get another cookie.
-** Implemented/Archived
-*** Tracebacks in ob-ein blocks
-Error/traceback information should be communicated when executing ein blocks
-from org buffers.
-*** Issue #126: Support checkpoints/autosave
-Per the REST [[http://petstore.swagger.io/?url=https://raw.githubusercontent.com/jupyter/notebook/master/notebook/services/api/api.yaml][api]] this is supported via /contents/path/checkpoints. GET to
-retrieve checkpoints for notebook, POST to create one. Current
-FileContentsManager implementation only keeps one checkpoint at a time.
-
-Work this as a [[info:elisp#Timers][timer]] that runs after user customizable period of time.
-
-#+BEGIN_SRC elisp
- (setq ein:force-sync t)
- (setq content (ein:content-query-contents "Untitled.ipynb" 8888))
- (ein:content-query-checkpoints content)
- (list (ein:$content-path content)
- (ein:$content-checkpoints content))
-
-#+END_SRC
-
-#+RESULTS:
-| Untitled.ipynb | ((:id checkpoint :last_modified 2016-10-19T18:35:39.391740+00:00)) |
-
-Create a checkpoint:
-
-#+BEGIN_SRC elisp
- (ein:content-create-checkpoint content)
- (ein:$content-checkpoints content)
-#+END_SRC
-
-#+RESULTS:
-| :id | checkpoint | :last_modified | 2016-10-19T18:35:39.391740+00:00 |
-
-
-Delete a checkpoint:
-
-#+BEGIN_SRC elisp
- (ein:content-delete-checkpoint content "checkpoint")
- (ein:content-query-checkpoints content)
- (ein:$content-checkpoints content)
-#+END_SRC
-
-#+RESULTS:
-*** Edit cells ala ~org-edit-src-code~
-#+BEGIN_SRC python
-#+END_SRC
-
-anaconda-mode breaks unless the following change is made:
-#+BEGIN_SRC elisp
- (defun anaconda-mode-jsonrpc-request-data (command)
- "Prepare buffer data for COMMAND call."
- `((jsonrpc . "2.0")
- (id . 1)
- (method . ,command)
- (params . ((source . ,(buffer-substring-no-properties (point-min) (point-max)))
- (line . ,(line-number-at-pos (point)))
- (column . ,(- (point) (line-beginning-position)))
- (path . ,(if (buffer-file-name)
- (progn
- (if (pythonic-remote-p)
- (and
- (tramp-tramp-file-p (buffer-file-name))
- (equal (tramp-file-name-host
- (tramp-dissect-file-name
- (pythonic-tramp-connection)))
- (tramp-file-name-host
- (tramp-dissect-file-name
- (buffer-file-name))))
- (pythonic-file-name (buffer-file-name)))
- (buffer-file-name)))
- "")))))) ;; So simple, but so necessary.
-#+END_SRC
-*** Org Babel Support
-Should be doable through ~[[file:emacs-ipython-notebook/lisp/ein-shared-output.el::(defun ein:shared-output-eval-string (code &optional popup verbose kernel][ein:shared-output-eval-string]]~.
-
-Need to specify session and/or a kernel. Kernel will be via the :kernelspec
-argument. In case of :session the argument is path (including url or port) for
-notebook to use for executing code. In case just a kernel ein will generate a
-notebook using the value of the ~~ variable.
-
-To get result can call ~ein:get-cell-at-point--shared-output~?. For sure needs
-to be done as a callback. Questionable how to insert output into results
-
-**** Test blocks
-
-#+BEGIN_SRC ein :session 8888/Untitled.ipynb
- import sys
-
- a = 14500
- b = a+1000
- sys.version
-#+END_SRC
-
-#+RESULTS:
-| '3.5.2 | Anaconda 4.2.0 (64-bit) | (default, Jul 5 2016, 11:41:13) [MSC v.1900 64 bit (AMD64)]' |
-
-
-#+BEGIN_SRC ein :session 8888/Untitled.ipynb
- a
-#+END_SRC
-
-#+RESULTS:
-| 14500 |
-
-#+BEGIN_SRC ein :session 8888
- a
-#+END_SRC
-
-#+RESULTS:
-
-#+BEGIN_SRC ein :session 8888/Untitled.ipynb :file C:/Temp/img.png :kernelspec conda-env-anaconda-py
- import sys
- from scipy.spatial import Voronoi, voronoi_plot_2d, KDTree
-
- import numpy as np
- import matplotlib.pyplot as plt
-
-
- %matplotlib inline
-
- points = np.array([[0., 0.], [0., 1.], [0., 2.], [1., 0.], [1., 1.], [1., 2.],
- [2., 0.], [2., 1.], [2., 2.]])
-
- plt.plot(points[:,0], points[:,1], 'ko')
- plt.show()
-#+END_SRC
-
-#+RESULTS:
-[[file:C:/Temp/img.png]]
-*** Imenu/Speedbar Cooperation
-Seems to be a couple ways of doing this:
-
- 1. Configuring ~[[http://emacswiki.org/emacs/ImenuMode#toc12][imenu-generic-expression]]~ regex's.
-
- 2. Redefining imenu-create-index ala python.el.
-
-(2) seems to be the more elegant solution.
-
-EIN currently has minimal support for imenu through
-~[[file:lisp/ein-worksheet.el::ein:worksheet-imenu-create-index][ein:worksheet-imenu-create-index]]~, but all it does is look for
-headings. Somehow this fails to work with speedbar and also does not handle
-indexing Python code (i.e. variables, function, classes, etc.).
-
-To get the speedbar working we will need to define a minor mode per the
-following [[http://www.gnu.org/software/emacs/manual/html_node/speedbar/Minor-Display-Modes.html#Minor-Display-Modes][instructions]].
-
-For /name/~-speedbar-menu-items~ can I just use ~imenu-generic-expression~?
-
-Maybe the way to do this is for each ~[[file:lisp/ein-cell.el::ein:codecell][codecell]]~ create a temp buffer with the text
-of that cell and call ~ein:imenu-create-index~.
-
-#+BEGIN_SRC elisp
- (let ((text (ein:cell-get-text cell)))
- (with-temp-buffer
- (insert text)
- (ein:imenu-create-index)))
-#+END_SRC
-
-Still will need way to map temp buffer positions to actual positions in the
-notebook buffer (~ein:cell-input-pos-min~ and ~ein:cell-input-pos-max~)
-*** Access password protected notebooks (issue [[https://github.com/millejoh/emacs-ipython-notebook/issues/57][#57]])
-This is what I have found out so far:
-
-You can authenticate with the IPython/Jupyter notebook server using
-ein:notebooklist-login. After calling this a cookie is generated (very easy to
-see if you are using curl as the backend for emacs-request) and you can then use
-the REST API to list and get notebook data.
-
-Once authenticated REST calls to get notebook json data and create sessions work
-fine. After EIN starts a session one can see the kernel is running from the web
-interface. The problem starts when ein tries to open a websocket connection to
-the kernel. The notebook server generates a 403 forbidden response. I think
-because emacs-websocket doesn't know anything about the security cookie
-generated during the curl request.
-
-Not sure if that makes sense, but for the moment that is my theory on what's
-happening. Somehow we need to provide the security cookie with the websocket
-connect request.
-
-<2015-06-09 Tue> SOLVED(?) - issue is that emacs-websocket needs to provide more
-info with the connection header:
-
-1. Specify the port along with the url.
-2. Pass along a security cookie.
-*** Jump to notebook code in traceback (issue [[https://github.com/millejoh/emacs-ipython-notebook/issues/42][#42]])
-
-What needs to be done:
-
-1. Carry notebook reference in the ~[[file:lisp/ein-traceback.el::ein:traceback][ein:traceback]]~ structure.
-2. Look for ~ in ()~. The number 3 means
- input #3 in the notebook.
-3. Find cell based on input number. Can iterate through list of cells () and look for matching
- ~input-prompt-number~.
-4. Call ~ein:cell-goto~ on that cell. May need to swap buffers first.
-*** MuMaMo or Polymode or mmm-mode
-
-For better support of Python editing either of these may be the way to go. EIN
-already supports MuMaMo, but the project is no longer maintained. I could
-incorporate it into ein-mumamo. Unfortunately it seems MuMaMo is broken under
-emacs 25.1. Not sure where it is breaking, but something is causing redisplay
-function to error out due to too many args (600+)
-
-Other option is to support [[https://github.com/vspinu/polymode][Polymode]], which uses indirect buffers, which may or
-may not be a good solution for ein notebooks (why did I write this - JMM
-<2016-10-05 Wed>?). I think this is what nxhtml is doing...
-
-The problem with Polymode is that it seems to depend on regex's to determine
-start and end of chunks and to support this in EIN I would have to make
-adjustments to how the buffer is displayed.
-
-One thought would be to do away with the cell's metaphor and make things more
-freeform - more like an org-mode buffer?
-
-**** Using org-edit-src-code
-
-Check the [[help:org-edit-src-code][documentation]] and read the [[file:c:/Users/millejoh/emacs25/share/emacs/25.1/lisp/org/org-src.el::(defun%20org-edit-src-code%20(&optional%20context%20code%20edit-buffer-name)][source]].
-
-**** Understanding Polymode
-
-Inner modes are defined as pm-hbtchunkmode objects. Need to specify regex's for
-head and tail, but appears that these can be functions of one argument ~(lambda
-(ahead) )~. See ~[[file:~/.emacs.d/elpa/polymode-20160805.448/polymode-methods.el::(defun pm--span-at-point (head-matcher tail-matcher &optional pos)][pm--span-at-point]]~. If ahead is -1 search backwords, otherwise
-search forwards. Return is (cons BEG END) where BEG and END mark span of head or
-tail.
-
-Default behavior for polymode is to call re-search-forward or
-re-search-backward. These functions set point and return position at beginning
-of regex. Setting point is not necessary for polymode to work, I think.
-
-polymode may not work well since it uses indirect buffers. This seems to cause
-problems with ein's ewoc data structures.
-
-**** Understanding [[info:mmm#Top][mmm-mode]]
-
-Does not appear to use indirect buffers, so may work better.
-
-*** Support %load ([[https://github.com/millejoh/emacs-ipython-notebook/issues/104][#104]])
-
-Support was already there, just needed to get the source name right in the code.
-
-*** Better debug interface
-
-Something like what Inferior Python mode [[file:c:/emacs26/share/emacs/26.0.50/lisp/progmodes/python.el.gz::;;;%20PDB%20Track%20integration][implements]].
-
-Could we make [[file:emacs-ipython-notebook/lisp/ein-ipdb.el::(define-derived-mode%20ein:ipdb-mode%20comint-mode%20"EIN:IPDB"][ipdb]] buffer mode derive from [[file:c:/emacs26/share/emacs/26.0.50/lisp/progmodes/python.el.gz::(define-derived-mode%20inferior-python-mode%20comint-mode%20"Inferior%20Python"][inferior-python-mode]]?
-
-*** Support other python and text files
-Allow ein to open, edit and save python and other text files. This will likely
-involve similar tactics as required for notebook/buffer integration [[*Make notebooks more file-like?][enhancment]].
-*** Integrate with [[http://docs.hylang.org/en/master/index.html][hy]]
-Initial support in v0.14!
-
-We can get read-eval via [[http://docs.hylang.org/en/master/language/interop.html][this]]. Just need to wrap kernel calls with some
-appropriate python code?
-
-Need to have two 'types' of python notebooks, however. Difference between
-notebooks will be a flag in the header metadata. That way EIN will know when to
-call the right wrapping function.
-
-Doing autocomplete may also be possible, but will need to figure out how to
-mangle and unmangle on the fly. Trick will be dealing with modules, as the
-[[http://docs.hylang.org/en/master/language/interop.html#using-python-from-hy][syntax]] in hy is not as simple and EIN will have to do more to determine context.
-
-Also look into a [[https://github.com/dsblank/simple_kernel][custom kernel]] that implement's hy read-eval-print.
-
-
-Running hy code from python appears to be a two-step process:
-
-#+BEGIN_SRC python
- import hy
- import hy.cmdline
-
- def hy_read_eval(string):
- hy.cmdline.hy_eval(hy.read_str(string)
-#+END_SRC
-*** Fixing Tests
-Testing is beyond broken at this point. I barely understand the code, async is
-causing far too much instability and travis never works. I think it is time to
-completely redo testing, i.e. throw out all the existing code and start anew.
-
-First is to take advantage of modern testing tools in Emacs
-**** Emacs Testing Frameworks
-
-There is the venerable [[https://www.emacswiki.org/emacs/ErtTestLibrary][ERT]].
-
-For working with asyn frameworks: [[https://github.com/rejeep/ert-async.el][ert-async]].
-
-Mocking: [[https://github.com/rejeep/el-mock.el][el-mock]].
-
-Thens there is [[http://cask.readthedocs.io/en/latest/][Cask]] + [[https://github.com/rejeep/ert-runner.el][ert-runner]]. [[https://github.com/tonini/overseer.el][Overseer]] lets you use ert-runner. from within emacs
-
-[[https://en.wikipedia.org/wiki/Integration_testing][Integration testing]] using [[https://github.com/ecukes/ecukes][ecukes]]. There is a lot to learn with this one, though.
-*** Asynchronous org-babel
-As inspiration should look at [[https://github.com/khinsen/ob-ipython-async/blob/master/ob-ipython-async.el][@khinsen's]] implementation
-for ob-ipython.
-
-Implemented in v0.14!
-
-* Tests
-
-This is a [[ipynb:(:url-or-port%20"http://localhost:8888"%20:name%20"emacs-ipython-notebook/The%20Emacs%20IPython%20Notebook.ipynb")][link]] to an ein notebook.
-
-#+BEGIN_SRC elisp :session
- (setq str0 "8888/Untitled.ipynb")
- (setq str1 "8888/Path/Untitled.ipynb")
-#+END_SRC
-
-#+RESULTS:
-: 8888/Path/Untitled.ipynb
-
-#+BEGIN_SRC elisp :session
-(ein:trim-left str0 "\/")
-#+END_SRC
-
-#+RESULTS:
-: 8888/Untitled.ipynb
-
-#+NAME: 29cc91f8-fcad-4afa-9dc7-e2bbb9821870
-#+BEGIN_SRC ein :session http://localhost:8888/Untitled.ipynb
- import sys
- import time
-
- time.sleep(10)
- print("Hello dood!")
-
-#+END_SRC
-
-#+RESULTS: 29cc91f8-fcad-4afa-9dc7-e2bbb9821870
-: Hello dood!
-
-#+NAME: 87f665e5-0314-4491-9666-edf15604aa21
-#+BEGIN_SRC ein :session http://localhost:8888/Untitled.ipynb
- 1+4
-#+END_SRC
-
-#+RESULTS: 87f665e5-0314-4491-9666-edf15604aa21
-: 5
-
-#+NAME: d934f2ea-e2fe-4a8f-9db0-c0496dbfc013
-#+BEGIN_SRC ein :session http://localhost:8888/Untitled.ipynb :results output drawer
- 1/0
-#+END_SRC
-
-#+RESULTS: d934f2ea-e2fe-4a8f-9db0-c0496dbfc013
-:RESULTS:
----------------------------------------------------------------------------
-ZeroDivisionError Traceback (most recent call last)
- in ()
-----> 1 1/0
-
-ZeroDivisionError: division by zero
-
-:END:
-
-#+NAME: 26e1891a-abaf-4a6b-831e-59d73fcf5170
-#+BEGIN_SRC ein :session http://localhost:8888/Untitled.ipynb :results output drawer
- import matplotlib.pyplot as plt
- import numpy as np
-
- %matplotlib inline
- x = np.linspace(0, 1, 100)
- y = np.random.rand(100,1)
- plt.plot(x,y)
- x
-
-#+END_SRC
-
-
-#+NAME: 36a8b735-8e7d-4503-addc-57165c651d7d
-#+BEGIN_SRC ein :session http://localhost:8888/Untitled.ipynb :results output
- from sympy import *
-
- init_printing()
- x = symbols('x')
- x
-
-#+END_SRC
diff --git a/Makefile b/Makefile
index bab2782..33c84d7 100644
--- a/Makefile
+++ b/Makefile
@@ -69,9 +69,9 @@ test-jupyterhub: test-compile
-cask exec ecukes --tags @jupyterhub --reporter magnars
.PHONY: test
-test: quick test-int test-poly
+test: quick test-int
-.PHONY: test-poly
+.PHONY: test-unpoly
test-poly:
cask exec ert-runner -L ./lisp -L ./test -l test/testfunc.el test/test-poly.el test/test-func.el
cp test/test-poly.el features/support/test-poly.el
@@ -79,12 +79,12 @@ test-poly:
.PHONY: test-int
test-int:
- cask exec ert-runner -L ./lisp -L ./test -l test/testfunc.el test/test-func.el
cask exec ecukes --reporter magnars
.PHONY: test-unit
test-unit:
cask exec ert-runner -L ./lisp -L ./test -l test/testein.el test/test-ein*.el
+ cask exec ert-runner -L ./lisp -L ./test test/test-uncompiled.el
.PHONY: test-ob-ein-recurse
test-ob-ein-recurse:
diff --git a/README.in.rst b/README.in.rst
index fd44d03..353a05b 100644
--- a/README.in.rst
+++ b/README.in.rst
@@ -62,7 +62,6 @@ Notebook server ``M-x ein:log-pop-to-request-buffer``.
Kernel messaging (must be run from notebook buffer) ``M-x ein:dev-pop-to-debug-channels``.
.. _spacemacs layer: https://github.com/syl20bnr/spacemacs/tree/master/layers/%2Blang/ipython-notebook
-.. _auto-complete: https://github.com/auto-complete/auto-complete
.. _company-mode: https://github.com/company-mode/company-mode
.. _jupyterhub: https://github.com/jupyterhub/jupyterhub
diff --git a/README.rst b/README.rst
index 5526542..1de59ba 100644
--- a/README.rst
+++ b/README.rst
@@ -121,7 +121,7 @@ Keymap (C-h m)
key binding
--- -------
-
+
C-c Prefix Command
C-x Prefix Command
ESC Prefix Command
@@ -131,16 +131,16 @@ Keymap (C-h m)
ein:worksheet-execute-cell-and-insert-below
ein:worksheet-move-cell-down
ein:worksheet-move-cell-up
-
+
C-x C-s ein:notebook-save-notebook-command
C-x C-w ein:notebook-rename-command
-
+
M-RET ein:worksheet-execute-cell-and-goto-next
M-, ein:pytools-jump-back-command
M-. ein:pytools-jump-to-source-command
M-n ein:worksheet-next-input-history
M-p ein:worksheet-previous-input-history
-
+
C-c C-a ein:worksheet-insert-cell-above
C-c C-b ein:worksheet-insert-cell-below
C-c C-c ein:worksheet-execute-cell
@@ -166,7 +166,6 @@ Keymap (C-h m)
C-c C-z ein:notebook-kernel-interrupt-command
C-c ESC Prefix Command
C-c ! ein:worksheet-rename-sheet
- C-c ' ein:edit-cell-contents
C-c + ein:notebook-worksheet-insert-next
C-c - ein:notebook-worksheet-delete
C-c 1 ein:notebook-worksheet-open-1th
@@ -179,7 +178,6 @@ Keymap (C-h m)
C-c 8 ein:notebook-worksheet-open-8th
C-c 9 ein:notebook-worksheet-open-last
C-c S ein:worksheet-toggle-slide-type
- C-c i ein:inspect-object
C-c { ein:notebook-worksheet-open-prev-or-last
C-c } ein:notebook-worksheet-open-next-or-first
C-c C-S-l ein:worksheet-clear-all-output
@@ -192,10 +190,10 @@ Keymap (C-h m)
C-c C-; ein:shared-output-show-code-cell-at-point
C-c ein:worksheet-move-cell-down
C-c ein:worksheet-move-cell-up
-
+
C-c C-x C-l ein:notebook-toggle-latex-fragment
C-c C-x C-r ein:notebook-restart-session-command
-
+
C-c M-+ ein:notebook-worksheet-insert-prev
C-c M-w ein:worksheet-copy-cell
C-c M-{ ein:notebook-worksheet-move-prev
diff --git a/The Emacs IPython Notebook.ipynb b/The Emacs IPython Notebook.ipynb
deleted file mode 100644
index bc53c3d..0000000
--- a/The Emacs IPython Notebook.ipynb
+++ /dev/null
@@ -1,1193 +0,0 @@
-{
- "cells": [
- {
- "cell_type": "markdown",
- "metadata": {
- "ein.tags": "worksheet-0",
- "slideshow": {
- "slide_type": "slide"
- }
- },
- "source": [
- "# The Emacs IPython Notebook\n",
- "### JupyterCon 2018\n",
- "\n",
- "John Miller ([email](millejoh@mac.com) / [github](https://github.com/millejoh/) / [linkedin](www.linkedin.com/in/john-miller-3720a811\n",
- ")) "
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {
- "ein.tags": "worksheet-0",
- "slideshow": {
- "slide_type": "slide"
- }
- },
- "source": [
- "# The Plan"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {
- "ein.tags": "worksheet-0",
- "slideshow": {
- "slide_type": "-"
- }
- },
- "source": [
- "- Thanks\n",
- "- About me\n",
- "- Introducing EIN\n",
- "- About Emacs\n",
- "- A Short History\n",
- "- Feature dive\n",
- "- What's next\n",
- "- Demo?"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {
- "ein.tags": "worksheet-0",
- "slideshow": {
- "slide_type": "slide"
- }
- },
- "source": [
- "# Disclaimer"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {
- "ein.tags": "worksheet-0",
- "slideshow": {
- "slide_type": "-"
- }
- },
- "source": [
- "- This work is not sponsored by my employer (Honeywell UOP)\n",
- "- I am not representing my employer (today)\n",
- "- UOP does some cools things, find me later if you want to learn more!"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {
- "ein.tags": "worksheet-0",
- "slideshow": {
- "slide_type": "slide"
- }
- },
- "source": [
- "# Thanks!"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {
- "ein.tags": "worksheet-0",
- "slideshow": {
- "slide_type": "fragment"
- }
- },
- "source": [
- "- Takafumi Arakami ([@tkf](https://github.com/tkf))\n",
- "\n",
- " - EIN does not exist without tkf"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {
- "ein.tags": "worksheet-0",
- "slideshow": {
- "slide_type": "fragment"
- }
- },
- "source": [
- "- Fernando and the rest at Jupyter\n",
- "- O'Reilly - Andre Morrow in particular!\n",
- "- D.E. Shaw - supporting some work back in 2016-2017.\n",
- "- My kind, patient crew of Github ein [stargazers](https://github.com/millejoh/emacs-ipython-notebook/stargazers) (all 660 of you!)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {
- "ein.tags": "worksheet-0",
- "slideshow": {
- "slide_type": "subslide"
- }
- },
- "source": [
- "# About John"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {
- "ein.tags": "worksheet-0",
- "slideshow": {
- "slide_type": "-"
- }
- },
- "source": [
- "- 1997: BS Chemical Engineering / Computer Science from CSU\n",
- "- Since then: [Honeywell UOP](https://www.uop.com)\n",
- "- Emacser since college (??)\n",
- "- Irregular Pythoner since 1998 (Zope to Pandas!)\n",
- "- EIN Maintainer since 2014/2015-ish (commit [20a7250](https://github.com/millejoh/emacs-ipython-notebook/commit/20a725012b6c8ffe9173fcfc8808dfb46fbb1824))"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {
- "ein.tags": "worksheet-0",
- "slideshow": {
- "slide_type": "slide"
- }
- },
- "source": [
- "# Introducing EIN"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {
- "ein.tags": "worksheet-0",
- "slideshow": {
- "slide_type": "-"
- }
- },
- "source": [
- "- A full-featured client for the Jupyter Notebook in the venerable Emacs editor\n",
- "- Tries to be a bit like [SLIME](https://common-lisp.net/project/slime/)\n",
- "- Work on emacs 24.5+ (but 25+ is best)\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {
- "ein.tags": "worksheet-0",
- "slideshow": {
- "slide_type": "subslide"
- }
- },
- "source": [
- "## Features\n",
- " - Written almost completely in elisp!\n",
- " - IDE features (syntax highlighting, jump to source, auto-completeion, popup help, help browser, etc.)\n",
- " - Integration with pdb via comint\n",
- " - Integration with [org-mode](https://orgmode.org/)\n",
- " - Works with non-python kernels!\n",
- " - Connect python buffers to running kernels."
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {
- "ein.tags": "worksheet-0",
- "slideshow": {
- "slide_type": "slide"
- }
- },
- "source": [
- "# About Emacs"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {
- "ein.tags": "worksheet-0",
- "slideshow": {
- "slide_type": "-"
- }
- },
- "source": [
- "The programmable programming editor.\n",
- "40 years of history.\n",
- ""
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {
- "ein.tags": "worksheet-0",
- "slideshow": {
- "slide_type": "slide"
- }
- },
- "source": [
- "## Why do I use Emacs?"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {
- "ein.tags": "worksheet-0",
- "slideshow": {
- "slide_type": "subslide"
- }
- },
- "source": [
- ""
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {
- "ein.tags": "worksheet-0",
- "slideshow": {
- "slide_type": "subslide"
- }
- },
- "source": [
- "- Lisp Machine's scrapier cousin from the wrong side of town\n",
- "- See Josh Stella's excellent blog posts ([#1](https://blog.fugue.co/2015-11-11-guide-to-emacs.html) and [#2](https://blog.fugue.co/2018-08-09-two-years-with-emacs-as-a-cto.html))\n",
- "- Focus without distraction\n",
- "- Not a black box with a shiny interface\n",
- "- Almost complete control over your editing environment\n",
- "- It's a tool building tool"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {
- "ein.tags": "worksheet-0",
- "slideshow": {
- "slide_type": "subslide"
- }
- },
- "source": [
- "# The Great Editor/IDE Wars"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {
- "ein.tags": "worksheet-0",
- "slideshow": {
- "slide_type": "-"
- }
- },
- "source": [
- "Let's not, actually. Brothers and sisters, read [More than Words](http://www.nhplace.com/kent/PS/Lambda.html).\n",
- "\n",
- "> In essence, I'll suggest that Lisp is a social phenomenon, akin to a\n",
- "> political party, and that what unifies Lisp are the people who are its\n",
- "> leaders, and the ways in which they respond (or fail to respond) to the needs\n",
- "> of that community. --- Kent Pitman"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {
- "ein.tags": "worksheet-0",
- "slideshow": {
- "slide_type": "notes"
- }
- },
- "source": [
- "More than one political party is good! Diverse ideas are good! Extremism - not\n",
- "so good.\n",
- "\n",
- "The secret to peace - holding opposing thoughts in our heads?"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {
- "ein.tags": "worksheet-0",
- "slideshow": {
- "slide_type": "slide"
- }
- },
- "source": [
- "# A Brief History of EIN"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {
- "ein.tags": "worksheet-0",
- "slideshow": {
- "slide_type": "fragment"
- }
- },
- "source": [
- ""
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {
- "ein.tags": "worksheet-0",
- "slideshow": {
- "slide_type": "subslide"
- }
- },
- "source": [
- "- Created by [tkf](https://github.com/tkf) in 2012\n",
- "- First alternate client for IPython\n",
- "- tkf's last commit is on 17 Mar 2014 (1,795 commits later!)\n",
- "- I fork and push IPython 2.0 support on 14 April 2014\n",
- "- Supporting transition from IPython/Jupyter 1.0 -> 4.0 rough sailing!"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {
- "ein.tags": "worksheet-0",
- "slideshow": {
- "slide_type": "subslide"
- }
- },
- "source": [
- "# The Challenges"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {
- "ein.tags": "worksheet-0",
- "slideshow": {
- "slide_type": "-"
- }
- },
- "source": [
- "- Changes to the Contents API\n",
- "- Changes to communication protocol\n",
- "- Changes to the security model (I hate you _xsrf)\n",
- "- Changes to the notebook format\n",
- "- Debugging connection issues for other users\n",
- "- Legacy support (Emacs 24 vs 25, 26, 27...)\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {
- "ein.tags": "worksheet-0",
- "slideshow": {
- "slide_type": "subslide"
- }
- },
- "source": [
- "- Why?\n",
- " - John is agoraphobic outside of Emacs\n",
- " - John is allergic to javascript\n",
- " - EIN’s internal data structures tuned to earlier versions of notebook format\n",
- " - Behold the eldritch horrors of `ein:cell-to-nb4-json`\n",
- " - Every Emacs installation is different (advantage and disadvantage!)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {
- "ein.tags": "worksheet-0",
- "slideshow": {
- "slide_type": "subslide"
- }
- },
- "source": [
- "# The Joys"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {
- "ein.tags": "worksheet-0",
- "slideshow": {
- "slide_type": "-"
- }
- },
- "source": [
- "- People (not just me) use it to do stuff!\n",
- "- Supportive community.\n",
- "- Solving the challenges.\n",
- "- I get to program in Lisp!"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {
- "ein.tags": "worksheet-0",
- "slideshow": {
- "slide_type": "slide"
- }
- },
- "source": [
- "# Feature Dive"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {
- "ein.tags": "worksheet-0",
- "slideshow": {
- "slide_type": "subslide"
- }
- },
- "source": [
- "## What is similar"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {
- "ein.tags": "worksheet-0",
- "slideshow": {
- "slide_type": "-"
- }
- },
- "source": [
- "- Visually alike, but more text-y\n",
- "- Cut, copy, past cells (even across notebooks!)\n",
- "- Inline images\n",
- "- Works with non-python kernels"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {
- "ein.tags": "worksheet-0",
- "slideshow": {
- "slide_type": "subslide"
- }
- },
- "source": [
- "## IDE-like Features"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {
- "ein.tags": "worksheet-0",
- "slideshow": {
- "slide_type": "-"
- }
- },
- "source": [
- "- Auto-completion\n",
- "- Jump to definition (local only!)\n",
- "- Popup (tooltip) help\n",
- "- Syntax highlighting (not perfect)\n",
- "- Help browser\n",
- "- Traceback view\n",
- "- Integration with ipdb"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {
- "ein.tags": "worksheet-0",
- "slideshow": {
- "slide_type": "subslide"
- }
- },
- "source": [
- "## Unique to Emacs?"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {
- "ein.tags": "worksheet-0",
- "slideshow": {
- "slide_type": "-"
- }
- },
- "source": [
- "- Run jupyter from inside Emacs!\n",
- "- Execute elisp from IPython\n",
- "- Integration with org-mode\n",
- "- Support for [hy](http://hylang.org)\n",
- "- Connect python buffer to a running notebook\n",
- "- Customizable using elisp (vs javascript)\n",
- "- %whos popup (`ein:pytools-whos`)\n",
- "- Run doctests for object at point"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {
- "ein.tags": "worksheet-0",
- "slideshow": {
- "slide_type": "slide"
- }
- },
- "source": [
- "## Needing some TLC"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {
- "ein.tags": "worksheet-0",
- "slideshow": {
- "slide_type": "-"
- }
- },
- "source": [
- "- Pandas to [SES](http://www.gnu.org/software/emacs/manual/html_node/ses/index.html)\n",
- "- Hierarchymagic (depends on [Hierarchymagic_ext](https://github.com/tkf/ipython-hierarchymagic))"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {
- "ein.tags": "worksheet-0",
- "slideshow": {
- "slide_type": "subslide"
- }
- },
- "source": [
- "## What EIN does not do"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {
- "ein.tags": "worksheet-0",
- "slideshow": {
- "slide_type": "-"
- }
- },
- "source": [
- "- Widgets\n",
- "- Extensions\n",
- " - Emacs doesn't quite understand javascript.\n",
- " - Possible with some effort (see [timestamp](https://github.com/millejoh/emacs-ipython-notebook/blob/master/lisp/ein-timestamp.el))\n",
- " - [Skewer](https://github.com/skeeto/skewer-mode) package allows limited execution of javascript\n",
- "- Jupyterhub support exists, but is wonky"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {
- "ein.tags": "worksheet-0",
- "slideshow": {
- "slide_type": "slide"
- }
- },
- "source": [
- "# What's Next for EIN?"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {
- "ein.tags": "worksheet-0",
- "slideshow": {
- "slide_type": "-"
- }
- },
- "source": [
- "- Don't fall behind (easier said than done)\n",
- "- More robust!\n",
- "- Better integration with external documentation\n",
- "- Seamless support for remote Jupyterhub and remote connections\n",
- "- Support widgets (this is going to be tough!)\n",
- "- Better integration with the Emacs Python ecosystem\n",
- "- A full inspector (ala SLIME)\n",
- "- And much (too much!) more...\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {
- "ein.tags": "worksheet-0",
- "slideshow": {
- "slide_type": "slide"
- }
- },
- "source": [
- "# A Demonstration"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "autoscroll": false,
- "collapsed": false,
- "ein.hycell": false,
- "ein.tags": "worksheet-0",
- "slideshow": {
- "slide_type": "-"
- }
- },
- "outputs": [],
- "source": [
- "%pwd"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "autoscroll": false,
- "collapsed": false,
- "ein.hycell": false,
- "ein.tags": "worksheet-0",
- "slideshow": {
- "slide_type": "-"
- }
- },
- "outputs": [],
- "source": [
- "import sys\n",
- "# Watch me autocomplete and show an informative popup!\n",
- "# Try this before executing import sys with `ein:completion-backend`\n",
- "# set to `ein:use-ac-jedi-backend`. Eat your heart out Joel Grus and\n",
- "# JupyterLab!\n",
- "sys"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "autoscroll": false,
- "collapsed": false,
- "ein.hycell": false,
- "ein.tags": "worksheet-0",
- "slideshow": {
- "slide_type": "-"
- }
- },
- "outputs": [],
- "source": [
- "print(\"Hello World!\")"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {
- "ein.tags": "worksheet-0",
- "slideshow": {
- "slide_type": "-"
- }
- },
- "source": [
- "## Behold the glory of Python and Emacs!"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {
- "ein.tags": "worksheet-0",
- "slideshow": {
- "slide_type": "-"
- }
- },
- "source": [
- "### Syntax highlighting and inline images."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 1,
- "metadata": {
- "autoscroll": false,
- "collapsed": false,
- "ein.hycell": false,
- "ein.tags": "worksheet-0",
- "slideshow": {
- "slide_type": "-"
- }
- },
- "outputs": [],
- "source": [
- "%matplotlib inline\n",
- "# Open via C-c ' and check out flycheck support\n",
- "import matplotlib.pyplot as plt\n",
- "import numpy as np"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "autoscroll": false,
- "collapsed": false,
- "ein.hycell": false,
- "ein.tags": "worksheet-0",
- "slideshow": {
- "slide_type": "slide"
- }
- },
- "outputs": [],
- "source": [
- "plt."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "autoscroll": false,
- "collapsed": false,
- "ein.hycell": false,
- "ein.tags": "worksheet-0",
- "slideshow": {
- "slide_type": "-"
- }
- },
- "outputs": [],
- "source": [
- "def plotnormal():\n",
- " return plt.plot(np.random.randn(1000), np.random.randn(1000), 'o', alpha=0.3)\n",
- "plotnormal()"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {
- "ein.tags": "worksheet-0",
- "slideshow": {
- "slide_type": "-"
- }
- },
- "source": [
- "### The help browser and jump to source"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "autoscroll": false,
- "collapsed": false,
- "ein.hycell": false,
- "ein.tags": "worksheet-0",
- "slideshow": {
- "slide_type": "-"
- }
- },
- "outputs": [],
- "source": [
- "plt.plot?"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {
- "ein.tags": "worksheet-0",
- "slideshow": {
- "slide_type": "-"
- }
- },
- "source": [
- "### EIN combines python and ipython error handling with Emacs debugger support."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "autoscroll": false,
- "collapsed": false,
- "ein.hycell": false,
- "ein.tags": "worksheet-0",
- "slideshow": {
- "slide_type": "-"
- }
- },
- "outputs": [],
- "source": [
- "%run non_existent_file"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "autoscroll": false,
- "collapsed": false,
- "ein.hycell": false,
- "ein.tags": "worksheet-0",
- "slideshow": {
- "slide_type": "-"
- }
- },
- "outputs": [],
- "source": [
- "x = 1\n",
- "y = 4\n",
- "z = y / (1 - x)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "autoscroll": false,
- "collapsed": false,
- "ein.hycell": false,
- "ein.tags": "worksheet-0",
- "slideshow": {
- "slide_type": "-"
- }
- },
- "outputs": [],
- "source": [
- "%run wiener_filtering.py"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "autoscroll": false,
- "collapsed": false,
- "ein.hycell": false,
- "ein.tags": "worksheet-0",
- "slideshow": {
- "slide_type": "-"
- }
- },
- "outputs": [],
- "source": [
- "%debug"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {
- "ein.tags": "worksheet-0",
- "slideshow": {
- "slide_type": "-"
- }
- },
- "source": [
- "### What about org files"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {
- "ein.tags": "worksheet-0",
- "slideshow": {
- "slide_type": "-"
- }
- },
- "source": [
- "Take a looksy at [this](./org_demo.org)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {
- "ein.tags": "worksheet-0",
- "slideshow": {
- "slide_type": "-"
- }
- },
- "source": [
- "### What was that about Hy?"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {
- "ein.tags": "worksheet-0",
- "slideshow": {
- "slide_type": "skip"
- }
- },
- "source": [
- "Note - due to a bug in ein hy cell types are not saved between sessions, so you\n",
- "will need to manually set the cell type of the following two cells to Hy by\n",
- "calling `ein:worksheet-change-cell-type` then typing `h`"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 14,
- "metadata": {
- "autoscroll": false,
- "collapsed": false,
- "ein.hycell": false,
- "ein.tags": "worksheet-0",
- "slideshow": {
- "slide_type": "-"
- }
- },
- "outputs": [
- {
- "data": {
- "text/plain": [
- "2"
- ]
- },
- "execution_count": 14,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "(+ 1 1)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 15,
- "metadata": {
- "autoscroll": false,
- "collapsed": false,
- "ein.hycell": false,
- "ein.tags": "worksheet-0",
- "slideshow": {
- "slide_type": "-"
- }
- },
- "outputs": [],
- "source": [
- "(setv hy-var 42)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "autoscroll": false,
- "collapsed": false,
- "ein.hycell": false,
- "ein.tags": "worksheet-0",
- "slideshow": {
- "slide_type": "-"
- }
- },
- "outputs": [],
- "source": [
- "hy_var"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {
- "ein.tags": "worksheet-0",
- "slideshow": {
- "slide_type": "-"
- }
- },
- "source": [
- "### What about Emacs Lisp?"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "autoscroll": false,
- "collapsed": false,
- "ein.hycell": false,
- "ein.tags": "worksheet-0",
- "slideshow": {
- "slide_type": "-"
- }
- },
- "outputs": [],
- "source": [
- "%run tools/emacslisp.py"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "autoscroll": false,
- "collapsed": false,
- "ein.hycell": false,
- "ein.tags": "worksheet-0",
- "slideshow": {
- "slide_type": "-"
- }
- },
- "outputs": [],
- "source": [
- "res = EmacsLisp('(ein:dev-sys-info)')\n",
- "res"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "autoscroll": false,
- "collapsed": false,
- "ein.hycell": false,
- "ein.tags": "worksheet-0",
- "slideshow": {
- "slide_type": "-"
- }
- },
- "outputs": [],
- "source": [
- "type(res)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "autoscroll": false,
- "collapsed": false,
- "ein.hycell": false,
- "ein.tags": "worksheet-0",
- "slideshow": {
- "slide_type": "-"
- }
- },
- "outputs": [],
- "source": [
- "dir(res)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {
- "ein.tags": "worksheet-0",
- "slideshow": {
- "slide_type": "-"
- }
- },
- "source": [
- "### We Support Magic!"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "autoscroll": false,
- "collapsed": false,
- "ein.hycell": false,
- "ein.tags": "worksheet-0",
- "slideshow": {
- "slide_type": "-"
- }
- },
- "outputs": [],
- "source": [
- "%load tools/emacslisp.py"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {
- "ein.tags": "worksheet-0",
- "slideshow": {
- "slide_type": "-"
- }
- },
- "source": [
- "## Check out test.py"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "autoscroll": false,
- "collapsed": false,
- "ein.hycell": false,
- "ein.tags": "worksheet-0",
- "slideshow": {
- "slide_type": "-"
- }
- },
- "outputs": [],
- "source": [
- "digits"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {
- "ein.tags": "worksheet-0",
- "slideshow": {
- "slide_type": "-"
- }
- },
- "source": [
- "# Don't look at me!"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 1,
- "metadata": {
- "autoscroll": false,
- "collapsed": false,
- "ein.hycell": false,
- "ein.tags": "worksheet-0",
- "execute-time": [
- "2018-10-15T02:00:45.633797Z",
- "2018-10-15T02:00:46.999049Z"
- ],
- "slideshow": {
- "slide_type": "-"
- }
- },
- "outputs": [],
- "source": [
- "import matplotlib.pyplot as plt\n",
- "import seaborn as sns\n",
- "sns.set(context='talk')\n",
- "plt.rcParams[\"figure.dpi\"] = 144\n",
- "plt.rcParams[\"figure.figsize\"] = 16, 10"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "autoscroll": false,
- "collapsed": false,
- "ein.hycell": false,
- "ein.tags": "worksheet-0",
- "execute-time": [
- "2018-10-15T03:20:48.024857Z",
- "2018-10-15T03:20:48.040723Z"
- ],
- "slideshow": {
- "slide_type": "-"
- }
- },
- "outputs": [],
- "source": [
- "digits"
- ]
- }
- ],
- "metadata": {
- "celltoolbar": "Slideshow",
- "kernelspec": {
- "display_name": "Data Science (py36)",
- "name": "datascience"
- },
- "language_info": {
- "codemirror_mode": {
- "name": "ipython",
- "version": 3
- },
- "file_extension": ".py",
- "mimetype": "text/x-python",
- "name": "python",
- "nbconvert_exporter": "python",
- "pygments_lexer": "ipython3",
- "version": "3.6.6"
- },
- "name": "The Emacs IPython Notebook.ipynb",
- "rise": {
- "controls": false,
- "theme": "serif"
- }
- },
- "nbformat": 4,
- "nbformat_minor": 2
-}
diff --git a/_images/ein_logo.jpg b/_images/ein_logo.jpg
deleted file mode 100644
index afa3491..0000000
Binary files a/_images/ein_logo.jpg and /dev/null differ
diff --git a/doc/source/index.rst b/doc/source/index.rst
index 69689ad..163402e 100644
--- a/doc/source/index.rst
+++ b/doc/source/index.rst
@@ -100,9 +100,6 @@ Requirements
* `request-deferred.el`_ >= 0.2
* `dash`_ >= 2.13
* `s`_ >= 1.11
-* `auto-complete.el`_ >= 1.4:
- You need to configure subpackage ``ein-ac`` to enable
- this feature.
* `skewer-mode`_ >= 1.6.2:
Skewer mode gives EIN the ability to execute dynamic javascript in the
note book.
diff --git a/features/connect.feature b/features/connect.feature
index efc37fc..6d4d456 100644
--- a/features/connect.feature
+++ b/features/connect.feature
@@ -1,29 +1,3 @@
-@connect
-Scenario: Company completion in a python buffer
- Given I set "ein:completion-backend" to eval "(quote ein:use-company-backend)"
- Given I kill all websocket buffers
- Given new python notebook
- When I open temp file "connect.py"
- And I switch to buffer like "connect.py"
- And I call "python-mode"
- And I connect to default notebook
- And I type "import itertools"
- And I press "RET"
- And I call "ein:connect-run-buffer"
- And I type "itertools."
- And I call "company-complete"
- And I wait for completions "itertools.chain"
- And I press "C-a"
- And I press "C-k"
- And I clear websocket log
- And I type "itertool"
- And I call "company-complete"
- Then I should see "itertools"
- And I type ".chai"
- And I call "company-complete"
- Then I should see "itertools.chain"
- Then no completion traffic
-
@connect
Scenario: Test shared eval
Given new python notebook
diff --git a/features/notebook.feature b/features/notebook.feature
index 6a1189a..caaf134 100644
--- a/features/notebook.feature
+++ b/features/notebook.feature
@@ -1,58 +1,3 @@
-@eldoc
-Scenario: remote eldoc (largely unused)
- Given I enable "ein:enable-eldoc-support"
- Given I clear log expr "ein:log-all-buffer-name"
- Given new python notebook
- And I type "import math"
- And I press "C-a"
- And I call eldoc-documentation-function
- And I switch to log expr "ein:log-all-buffer-name"
- Then I should not see "ein:completions--prepare-oinfo"
-
-@complete
-Scenario: auto completion
- Given I set "ein:ac-direct-matches" to eval "nil"
- Given I set "ein:completion-backend" to eval "(quote ein:use-ac-backend)"
- Given new python notebook
- And I type "import itertool"
- And I press "C-c C-i"
- And I wait for the smoke to clear
- Then "ein:ac-direct-matches" should include "itertools"
-
-@complete
-Scenario: no auto completion
- Given I set "ein:ac-direct-matches" to eval "nil"
- Given I set "ein:completion-backend" to eval "(quote ein:use-none-backend)"
- Given new python notebook
- And I type "import itertool"
- And I press "C-c C-i"
- And I wait for the smoke to clear
- Then "ein:ac-direct-matches" should not include "itertools"
-
-@complete
-Scenario: company completion
- Given I set "ein:completion-backend" to eval "(quote ein:use-company-backend)"
- Given I kill all websocket buffers
- Given new python notebook
- And I type "import itertools"
- And I press "M-RET"
- And I type "itertools."
- And I call "company-complete"
- And I wait for completions "itertools.chain"
- And I press "C-a"
- And I press "C-k"
- And I clear websocket log
- And I type "itertool"
- And I call "company-complete"
- Then I should see "itertools"
- And I type ".chai"
- And I call "company-complete"
- Then I should see "itertools.chain"
- Then no completion traffic
- Given I set "ein:completion-backend" to eval "(quote ein:use-ac-backend)"
- Given new python notebook
- Given I set "ein:completion-backend" to eval "(quote ein:use-none-backend)"
-
@rename
Scenario: rename notebook
Given new python notebook
diff --git a/features/support/env.el b/features/support/env.el
index 682528a..c3a412a 100644
--- a/features/support/env.el
+++ b/features/support/env.el
@@ -3,9 +3,10 @@
(require 'espuds)
(require 'ert)
(require 'undo-tree)
-
-(with-eval-after-load "python"
- (setq python-indent-guess-indent-offset-verbose nil))
+(require 'python)
+(require 'julia-mode)
+(require 'ess-r-mode)
+(require 'markdown-mode)
(let* ((support-path (f-dirname load-file-name))
(root-path (f-parent (f-parent support-path))))
@@ -73,7 +74,8 @@
(Setup
(ein:dev-start-debug)
(cl-assert (boundp 'company-frontends))
- (custom-set-variables '(company-frontends nil))
+ (custom-set-variables '(company-frontends nil)
+ '(python-indent-guess-indent-offset-verbose nil))
(setq ein:jupyter-default-kernel
(loop with cand = ""
for (k . spec) in
@@ -90,8 +92,6 @@
do (setq cand (symbol-name k))
end
finally return (intern cand)))
- (setq ein:notebook-autosave-frequency 0)
- (setq ein:notebook-create-checkpoint-on-save nil)
(setq ein:testing-dump-file-log (concat default-directory "log/ecukes.log"))
(setq ein:testing-dump-file-messages (concat default-directory "log/ecukes.messages"))
(setq ein:testing-dump-file-server (concat default-directory "log/ecukes.server"))
diff --git a/features/undo.feature b/features/undo.feature
index f98a400..62769f1 100644
--- a/features/undo.feature
+++ b/features/undo.feature
@@ -23,7 +23,7 @@ Scenario: Kill yank doesn't break undo
And I press "C-"
And I press "C-c C-y"
And I press "C-/"
- Then the cursor should be at point "74"
+ Then the cursor should be at point "75"
@undo
Scenario: Collapse doesn't break undo
@@ -52,7 +52,7 @@ Scenario: Collapse doesn't break undo
And I dump buffer
Then the cursor should be at point "77"
And I undo again
- Then the cursor should be at point "55"
+ Then the cursor should be at point "53"
@undo
Scenario: Test the conflagrative commands
@@ -108,7 +108,7 @@ Scenario: Clear output doesn't break undo
And I press "C-/"
Then the cursor should be at point "74"
And I undo again
- Then the cursor should be at point "55"
+ Then the cursor should be at point "53"
@undo
Scenario: Moving cells doesn't break undo
@@ -221,7 +221,7 @@ Scenario: Undo needs to at least work for reopened notebooks
And I undo again
And I undo again
And I undo again
- Then the cursor should be at point "125"
+ Then the cursor should be at point "124"
@undo
Scenario: Toggling between markdown and codecell does not break undo
@@ -291,7 +291,7 @@ Scenario: Undo (kind of) needs to work when someone explicitly requires ein-time
And I undo again
And I undo again
And I undo again
- Then the cursor should be at point "125"
+ Then the cursor should be at point "124"
@timestamp
Scenario: Kill yank doesn't break undo
diff --git a/features/undo.ipynb b/features/undo.ipynb
index d16579a..e884c0d 100644
--- a/features/undo.ipynb
+++ b/features/undo.ipynb
@@ -95,6 +95,21 @@
}
],
"metadata": {
+ "kernelspec": {
+ "argv": [
+ "python",
+ "-m",
+ "ipykernel_launcher",
+ "-f",
+ "{connection_file}"
+ ],
+ "display_name": "Python 3",
+ "env": null,
+ "interrupt_mode": "signal",
+ "language": "python",
+ "metadata": null,
+ "name": "python3"
+ },
"name": "undo.ipynb"
},
"nbformat": 4,
diff --git a/lisp/ein-ac.el b/lisp/ein-ac.el
deleted file mode 100644
index 6b62c5b..0000000
--- a/lisp/ein-ac.el
+++ /dev/null
@@ -1,253 +0,0 @@
-;;; ein-ac.el --- Auto-complete extension
-
-;; Copyright (C) 2012- Takafumi Arakaki
-
-;; Author: Takafumi Arakaki
-
-;; This file is NOT part of GNU Emacs.
-
-;; ein-ac.el is free software: you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation, either version 3 of the License, or
-;; (at your option) any later version.
-
-;; ein-ac.el is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with ein-ac.el. If not, see .
-
-;;; Commentary:
-
-;;
-
-;;; Code:
-
-(eval-when-compile (require 'cl))
-(require 'auto-complete)
-
-(require 'ein-core)
-(eval-when-compile (require 'ein-notebook)
- (defvar ein:mumamo-codecell-mode))
-
-
-;;; Configuration
-(defcustom ein:use-auto-complete-superpack nil
- "Set to `t' to use preset a little bit hacky auto-complete configuration.
-When this option is enabled, cached omni completion is available."
- :type 'boolean
- :group 'ein)
-
-(defvar ein:ac-sources (and (boundp 'ac-sources)
- (default-value 'ac-sources))
- "Extra `ac-sources' used in notebook.")
-
-
-;;; Chunk (adapted from auto-complete-chunk.el)
-
-(defvar ein:ac-chunk-regex
- (rx (group (| (syntax whitespace)
- (syntax open-parenthesis)
- (syntax close-parenthesis)
- (syntax string-quote) ; Complete files for `open("path/..`
- bol))
- (? (syntax punctuation)) ; to complete ``~/PATH/...``
- (* (+ (| (syntax word) (syntax symbol)))
- (syntax punctuation))
- (+ (| (syntax word) (syntax symbol)))
- (? (syntax punctuation))
- point)
- "A regexp that matches to a \"chunk\" containing words and dots.")
-
-(defun ein:ac-chunk-beginning ()
- "Return the position where the chunk begins."
- (ignore-errors
- (save-excursion
- (+ (re-search-backward ein:ac-chunk-regex) (length (match-string 1))))))
-
-(defun ein:ac-chunk-candidates-from-list (chunk-list)
- "Return matched candidates in CHUNK-LIST."
- (let* ((start (ein:ac-chunk-beginning)))
- (when start
- (loop with prefix = (buffer-substring start (point))
- for cc in chunk-list
- when (string-prefix-p prefix cc)
- collect cc))))
-
-
-;;; AC Source
-
-(defvar ein:ac-direct-matches nil
- "Variable to store completion candidates for `auto-completion'.")
-;; FIXME: Maybe this should be buffer-local?
-
-(defun ein:ac-direct-get-matches ()
- (ein:ac-chunk-candidates-from-list ein:ac-direct-matches))
-
-(ac-define-source ein-direct
- '((candidates . ein:ac-direct-get-matches)
- (requires . 0)
- (prefix . ein:ac-chunk-beginning)
- (symbol . "s")))
-
-(ac-define-source ein-async
- '((candidates . ein:ac-direct-get-matches)
- (requires . 0)
- (prefix . ein:ac-chunk-beginning)
- (init . ein:ac-request-in-background)
- (symbol . "c")))
-
-(define-obsolete-function-alias 'ac-complete-ein-cached 'ac-complete-ein-async
- "0.2.1")
-(define-obsolete-variable-alias 'ac-source-ein-cached 'ac-source-ein-async
- "0.2.1")
-
-(defun ein:ac-request-in-background ()
- (cl-ecase ein:completion-backend
- (ein:use-ac-backend (ein:aif (ein:get-kernel)
- (ein:completer-complete
- it
- (list :complete_reply
- (cons (lambda (_ content __)
- (ein:ac-prepare-completion (plist-get content :matches)))
- nil))
- #'ignore)))))
-
-
-;;; Completer interface
-
-(defun ein:ac-dot-complete (callback)
- "Insert a dot and request completion via CALLBACK of 0-arity"
- (interactive (list (lambda () (call-interactively #'ein:completer-complete))))
- (insert ".")
- (if (not (ac-cursor-on-diable-face-p))
- (funcall callback)))
-
-(defun ein:ac-prepare-completion (matches)
- "Prepare `ac-source-ein-direct' using MATCHES from kernel.
-Call this function before calling `auto-complete'."
- (when matches
- (setq ein:ac-direct-matches matches))) ; let-binding won't work
-
-(defun* ein:completer-finish-completing-ac
- (matched-text
- matches
- &key (expand ac-expand-on-auto-complete)
- &allow-other-keys)
- "Invoke completion using `auto-complete'.
-Only the argument MATCHES is used. MATCHED-TEXT is for
-compatibility with `ein:completer-finish-completing-default'."
- ;; I don't need to check if the point is at right position, as in
- ;; `ein:completer-finish-completing-default' because `auto-complete'
- ;; checks it anyway.
-
- (ein:log 'debug "COMPLETER-FINISH-COMPLETING-AC: matched-text=%S matches=%S"
- matched-text matches)
- (ein:ac-prepare-completion matches)
- (when matches ; No auto-complete drop-down list when no matches
- (let ((ac-expand-on-auto-complete expand))
- (ac-start))))
-
-
-;;; Async document request hack
-
-(defun ein:ac-request-document-for-selected-candidate ()
- "Request object information for the candidate at point.
-This is called via `ac-next'/`ac-previous'/`ac-update' and set
-`document' property of the current candidate string. If server
-replied within `ac-quick-help-delay' seconds, auto-complete will
-popup help string."
- (ein:aif (ein:get-kernel)
- (let* ((candidate (ac-selected-candidate))
- (kernel it)
- (api-version (ein:$kernel-api-version kernel))
- (callbacks (list (if (< api-version 3)
- :object_info_reply
- :inspect_request)
- (cons #'ein:ac-set-document candidate))))
- (when (and candidate
- (ein:kernel-live-p kernel)
- (not (get-text-property 0 'document candidate)))
- (ein:log 'debug "Requesting object info for AC candidate %S"
- candidate)
- (ein:kernel-object-info-request kernel candidate callbacks)))))
-
-(defun ein:ac-set-document (candidate content -metadata-not-used-)
- (ein:log 'debug "EIN:AC-SET-DOCUMENT candidate=%S content=%S"
- candidate content)
- (put-text-property 0 (length candidate)
- 'document (ein:kernel-construct-help-string content)
- candidate))
-
-(defadvice ac-next (after ein:ac-next-request)
- "Monkey patch `auto-complete' internal function to request
-help documentation asynchronously."
- (ein:ac-request-document-for-selected-candidate))
-
-(defadvice ac-previous (after ein:ac-previous-request)
- "Monkey patch `auto-complete' internal function to request
-help documentation asynchronously."
- (ein:ac-request-document-for-selected-candidate))
-
-(defadvice ac-update (after ein:ac-update-request)
- "Monkey patch `auto-complete' internal function to request help
-documentation asynchronously. This will request info for the
-first candidate when the `ac-menu' pops up."
- (ein:ac-request-document-for-selected-candidate))
-
-
-;;; Setup
-
-(defun ein:ac-superpack ()
- "Enable richer auto-completion.
-
-* Enable auto-completion help by monkey patching `ac-next'/`ac-previous'"
- (interactive)
- (ad-enable-advice 'ac-next 'after 'ein:ac-next-request)
- (ad-enable-advice 'ac-previous 'after 'ein:ac-previous-request)
- (ad-enable-advice 'ac-update 'after 'ein:ac-update-request)
- (ad-activate 'ac-next)
- (ad-activate 'ac-previous)
- (ad-activate 'ac-update))
-
-(defun ein:ac-setup ()
- "Call this function from mode hook (see `ein:ac-config')."
- (setq ac-sources (append '(ac-source-ein-async) ein:ac-sources)))
-
-(defun ein:ac-setup-maybe ()
- "Setup `ac-sources' for mumamo.
-
-.. note:: Setting `ein:notebook-mumamo-mode-hook' does not work
- because `ac-sources' in `ein:notebook-mumamo-mode'-enabled
- buffer is *chunk local*, rather than buffer local.
-
- Making `ac-sources' permanent-local also addresses issue of
- MuMaMo discarding `ac-sources'. However, it effects to entire
- Emacs setting. So this is not the right way to do it.
-
- Using `mumamo-make-variable-buffer-permanent' (i.e., adding
- `ac-sources' to `mumamo-per-buffer-local-vars' or
- `mumamo-per-main-major-local-vars') is also not appropriate.
- Adding `ac-sources' to them makes it impossible to different
- `ac-sources' between chunks, which is good for EIN but may not
- for other package."
- (and (ein:eval-if-bound 'ein:notebook-mode)
- (ein:eval-if-bound 'ein:notebook-mumamo-mode)
- (eql major-mode ein:mumamo-codecell-mode)
- (ein:ac-setup)))
-
-(defun ein:ac-config (&optional superpack)
- "Install auto-complete-mode for notebook modes.
-Specifying non-`nil' to SUPERPACK enables richer auto-completion
-\(see `ein:ac-superpack')."
- (add-hook 'after-change-major-mode-hook 'ein:ac-setup-maybe)
- (add-hook 'ein:notebook-mode-hook 'ein:ac-setup)
- (when superpack
- (ein:ac-superpack)))
-
-(ein:ac-config ein:use-auto-complete-superpack)
-(provide 'ein-ac)
-
-;;; ein-ac.el ends here
diff --git a/lisp/ein-cell-edit.el b/lisp/ein-cell-edit.el
deleted file mode 100644
index edf2340..0000000
--- a/lisp/ein-cell-edit.el
+++ /dev/null
@@ -1,273 +0,0 @@
-;;; ein-cell-edit.el --- Notebook cell editing
-
-;; Copyright (C) 2016 John M. Miller
-
-;; Author: John Miller
-
-;; This file is NOT part of GNU Emacs.
-
-;; ein-cell-edit.el is free software: you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation, either version 3 of the License, or
-;; (at your option) any later version.
-
-;; ein-cell-edit.el is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with ein-worksheet.el. If not, see .
-
-;;; Commentary:
-
-;; This code inspired by borrowing from org-src.el.
-
-;;; Code:
-(require 'ein-cell)
-
-(autoload 'julia-mode "julia-mode")
-(autoload 'markdown-mode "markdown-mode")
-(autoload 'R-mode "ess-r-mode")
-(autoload 'org-src--remove-overlay "org-src")
-(autoload 'org-src-switch-to-buffer "org-src")
-
-(defvar ein:src--cell nil)
-(defvar ein:src--ws nil)
-(defvar ein:src--allow-write-back t)
-(defvar ein:src--overlay nil)
-(defvar ein:src--saved-window-config nil)
-
-(defvar ein:edit-cell-mode-map
- (let ((map (make-sparse-keymap)))
- (define-key map "\C-c'" 'ein:edit-cell-exit)
- (define-key map "\C-c\C-k" 'ein:edit-cell-abort)
- (define-key map "\C-c\C-c" 'ein:edit-cell-save-and-execute)
- (define-key map "\C-x\C-s" 'ein:edit-cell-save)
- (define-key map "\C-c\C-x" 'ein:edit-cell-view-traceback)
- map))
-
-(define-minor-mode ein:edit-cell-mode
- "Minor mode for language major mode buffers generated by EIN.
-This minor mode is turned on when editing a source code snippet with \\[ein:edit-cell-contents]
-
-\\{ein:edit-cell-mode-map}
-
-."
- nil " EinCell" nil
- (set (make-local-variable 'header-line-format)
- (substitute-command-keys
- "Edit, execute with \\[ein:edit-cell-execute] then exit with \\[ein:edit-cell-exit] \
-or abort with \\[ein:edit-cell-abort]"))
- ;; Possibly activate various auto-save features (for the edit buffer
- ;; or the source buffer).
- ;; (when org-edit-src-turn-on-auto-save
- ;; (setq buffer-auto-save-file-name
- ;; (concat (make-temp-name "org-src-")
- ;; (format-time-string "-%Y-%d-%m")
- ;; ".txt")))
- ;; (unless (or org-src--auto-save-timer (zerop org-edit-src-auto-save-idle-delay))
- ;; (setq org-src--auto-save-timer
- ;; (run-with-idle-timer
- ;; org-edit-src-auto-save-idle-delay t
- ;; (lambda ()
- ;; (save-excursion
- ;; (let (edit-flag)
- ;; (dolist (b (buffer-list))
- ;; (with-current-buffer b
- ;; (when (org-src-edit-buffer-p)
- ;; (unless edit-flag (setq edit-flag t))
- ;; (when (buffer-modified-p) (org-edit-src-save)))))
- ;; (unless edit-flag
- ;; (cancel-timer org-src--auto-save-timer)
- ;; (setq org-src--auto-save-timer nil))))))))
- )
-
-(defun ein:cell-configure-edit-buffer ()
- (when (and (bound-and-true-p org-src--from-org-mode) (boundp 'org-src--beg-marker))
- (add-hook 'kill-buffer-hook #'org-src--remove-overlay nil 'local)
- (if (bound-and-true-p org-src--allow-write-back)
- (progn
- (setq buffer-offer-save t)
- (setq buffer-file-name
- (concat (buffer-file-name (marker-buffer org-src--beg-marker))
- "[" (buffer-name) "]"))
- (setq write-contents-functions '(ein:edit-cell-save)))
- (setq buffer-read-only t))))
-
-(defun ein:edit-cell-view-traceback ()
- "Jump to traceback, if there is one, for current edit."
- (interactive)
- (let ((buf (current-buffer))
- (cell ein:src--cell))
- (with-current-buffer (ein:worksheet--get-buffer ein:src--ws)
- (ein:cell-goto cell)
- (ein:tb-show))))
-
-(defun ein:edit-cell-save-and-execute ()
- "Save, then execute the countents of the EIN source edit buffer
-and place results (if any) in output of original notebook cell."
- (interactive)
- (ein:edit-cell-save)
- (when (and (slot-exists-p ein:src--cell 'kernel)
- (slot-boundp ein:src--cell 'kernel))
- (ein:cell-execute-internal ein:src--cell
- (slot-value ein:src--cell 'kernel)
- (buffer-string)
- :silent nil)))
-
-(defun ein:edit-cell-save ()
- "Save contents of EIN source edit buffer back to original notebook
-cell."
- (interactive)
- (set-buffer-modified-p nil)
- (let* ((edited-code (buffer-string))
- (cell ein:src--cell)
- (overlay ein:src--overlay)
- (read-only (overlay-get overlay 'modification-hooks)))
- (overlay-put overlay 'modification-hooks nil)
- (overlay-put overlay 'insert-in-front-hooks nil)
- (overlay-put overlay 'insert-behind-hooks nil)
- (with-current-buffer (ein:worksheet--get-buffer ein:src--ws)
- (ein:cell-set-text cell edited-code))
- ;;(setf (slot-value ein:src--cell 'input) edited-code)
- (overlay-put overlay 'modification-hooks read-only)
- (overlay-put overlay 'insert-in-front-hooks read-only)
- (overlay-put overlay 'insert-behind-hooks read-only)))
-
-
-(defun ein:edit-cell-exit ()
- "Close the EIN source edit buffer, saving contents back to the
-original notebook cell, unless being called via
-`ein:edit-cell-abort'."
- (interactive)
- (let ((edit-buffer (current-buffer))
- (ws ein:src--ws)
- (cell ein:src--cell))
- (ein:remove-overlay)
- (when ein:src--allow-write-back
- (ein:edit-cell-save))
- (kill-buffer edit-buffer)
- (switch-to-buffer-other-window (ein:worksheet--get-buffer ws))
- (ein:cell-goto cell)
- (when ein:src--saved-window-config
- (set-window-configuration ein:src--saved-window-config)
- (setq ein:src--saved-window-config nil))))
-
-(defun ein:edit-cell-abort ()
- "Abort editing the current cell, contents will revert to
-previous value."
- (interactive)
- (let (ein:src--allow-write-back) (ein:edit-cell-exit)))
-
-(defun ein:construct-cell-edit-buffer-name (bufname cid cell-type)
- (concat "*EIN Src " bufname "[ " cid "/" cell-type " ]*" ))
-
-(defun ein:get-mode-for-kernel (kernelspec)
- (if (null kernelspec)
- 'python ;; FIXME
- (ein:case-equal (ein:$kernelspec-language kernelspec)
- (("julia" "python" "R") (intern (ein:$kernelspec-language kernelspec)))
- (t 'python))))
-
-(defun ein:edit-src-continue (e)
- (interactive "e")
- (mouse-set-point e)
- (let ((buf (get-char-property (point) 'edit-buffer)))
- (if buf (org-src-switch-to-buffer buf 'continue)
- (user-error "No sub-editing buffer for area at point"))))
-
-(defun ein:make-source-overlay (beg end edit-buffer)
- "Create overlay between BEG and END positions and return it.
-EDIT-BUFFER is the buffer currently editing area between BEG and
-END."
- (let ((overlay (make-overlay beg end)))
- (overlay-put overlay 'face 'secondary-selection)
- (overlay-put overlay 'edit-buffer edit-buffer)
- (overlay-put overlay 'help-echo
- "Click with mouse-1 to switch to buffer editing this segment")
- (overlay-put overlay 'face 'secondary-selection)
- (overlay-put overlay 'keymap
- (let ((map (make-sparse-keymap)))
- (define-key map [mouse-1] 'ein:edit-src-continue)
- map))
- (let ((read-only
- (list
- (lambda (&rest _)
- (user-error
- "Cannot modify an area being edited in a dedicated buffer")))))
- (overlay-put overlay 'modification-hooks read-only)
- (overlay-put overlay 'insert-in-front-hooks read-only)
- (overlay-put overlay 'insert-behind-hooks read-only))
- overlay))
-
-(defun ein:remove-overlay ()
- "Remove overlay from current source buffer."
- (when (overlayp ein:src--overlay) (delete-overlay ein:src--overlay)))
-
-(defcustom ein:raw-cell-default-edit-mode 'LaTeX-mode
- "The major mode to use when editing a cell of type 'Raw' in the
- dedicated edit buffer. By default we use LaTeX-mode."
- :type 'symbol
- :group 'ein)
-
-(defun ein:edit-cell-contents ()
- "Edit the contents of the current cell in a buffer using an
-appropriate language major mode. Functionality is very similar to
-`org-edit-special'."
- (interactive)
- (setq ein:src--saved-window-config (current-window-configuration))
- (let* ((cell (or (ein:worksheet-get-current-cell)
- (error "Must be called from inside an EIN worksheet cell.")))
- (nb (ein:notebook--get-nb-or-error))
- (ws (ein:worksheet--get-ws-or-error))
- (type (slot-value cell 'cell-type))
- (name (ein:construct-cell-edit-buffer-name (buffer-name) (ein:cell-id cell) type)))
- (ein:aif (get-buffer name)
- (switch-to-buffer-other-window it)
- (ein:create-edit-cell-buffer name cell nb ws))))
-
-(defun ein:edit-cell-detect-type (contents notebook &optional raw-cell-p)
- (if (string-match "^%%\\(.*\\)" contents)
- (ein:case-equal (match-string 1 contents)
- (("html" "HTML") (html-mode))
- (("latex" "LATEX") (LaTeX-mode))
- (("ruby") (ruby-mode))
- (("sh" "bash") (sh-mode))
- (("javascript" "js") (javascript-mode))
- (t (funcall ein:raw-cell-default-edit-mode)))
- (if raw-cell-p
- (funcall ein:raw-cell-default-edit-mode)
- (case (ein:get-mode-for-kernel (ein:$notebook-kernelspec notebook))
- (julia (julia-mode))
- (python (python-mode))
- (R (R-mode))))))
-
-(defun ein:create-edit-cell-buffer (name cell notebook worksheet)
- (let* ((contents (ein:cell-get-text cell))
- (type (slot-value cell 'cell-type))
- (buffer (generate-new-buffer-name name))
- (overlay (ein:make-source-overlay (ein:cell-input-pos-min cell)
- (ein:cell-input-pos-max cell)
- buffer)))
- (switch-to-buffer-other-window buffer)
- (insert contents)
- (remove-text-properties (point-min) (point-max)
- '(display nil invisible nil intangible nil))
- (set-buffer-modified-p nil)
- (setq buffer-file-name buffer) ;; Breaks anaconda-mode without this special fix.
-
- (condition-case e
- (ein:case-equal type
- (("markdown") (markdown-mode))
- (("raw") (ein:edit-cell-detect-type contents notebook t))
- (("code") (ein:edit-cell-detect-type contents notebook)))
- (error (message "Language mode `%s' fails with: %S"
- type (nth 1 e))))
- (set (make-local-variable 'ein:src--overlay) overlay)
- (set (make-local-variable 'ein:src--cell) cell)
- (set (make-local-variable 'ein:src--ws) worksheet)
- (set (make-local-variable 'ein:src--allow-write-back) t)
- (ein:edit-cell-mode)))
-
-(provide 'ein-cell-edit)
diff --git a/lisp/ein-cell.el b/lisp/ein-cell.el
index 0f3cc0b..0fc22ec 100644
--- a/lisp/ein-cell.el
+++ b/lisp/ein-cell.el
@@ -42,8 +42,6 @@
(require 'ein-node)
(require 'ein-kernel)
(require 'ein-output-area)
-(require 'ein-skewer)
-(require 'ein-hy)
;;; Faces
@@ -122,12 +120,7 @@
;;; Customization
-(defcustom ein:enable-dynamic-javascript nil
- "[EXPERIMENTAL] When non-nil enable support in ein for
-executing dynamic javascript. This feature requires installation
-of the skewer package."
- :type 'boolean
- :group 'ein)
+(make-obsolete-variable 'ein:enable-dynamic-javascript nil "0.17.0")
(defcustom ein:cell-traceback-level 1
"Number of traceback stack to show.
@@ -210,7 +203,6 @@ a number will limit the number of lines in a cell output."
(defun ein:cell-class-from-type (type)
(ein:case-equal type
(("code") 'ein:codecell)
- (("hy-code") 'ein:hy-codecell)
(("text") 'ein:textcell)
(("html") 'ein:htmlcell)
(("markdown") 'ein:markdowncell)
@@ -229,13 +221,7 @@ a number will limit the number of lines in a cell output."
(apply (ein:cell-class-from-type type) args))
(defun ein:cell--determine-cell-type (json-data)
- (let ((base-type (plist-get json-data :cell_type))
- (metadata (plist-get json-data :metadata)))
- (if (and (string-equal base-type "code")
- (plist-get :metadata :ein.hycell)
- (not (eql (plist-get metadata :ein.hycell) :json-false)))
- "hy-code"
- base-type)))
+ (plist-get json-data :cell_type))
(defun ein:cell-from-json (data &rest args)
(let ((cell (ein:cell-init (apply #'ein:cell-from-type
@@ -921,13 +907,8 @@ Called from ewoc pretty printer via `ein:cell-insert-output'."
(cl-defmethod ein:cell-append-display-data ((cell ein:codecell) json)
"Insert display-data type output in the buffer.
Called from ewoc pretty printer via `ein:cell-insert-output'."
- (if (and (or (plist-get json :javascript)
- (plist-get json :html))
- (slot-value cell 'dynamic) ein:enable-dynamic-javascript)
- (ein:execute-javascript cell json)
- (progn
- (ein:cell-append-mime-type json (slot-value cell 'dynamic))
- (ein:insert-read-only "\n"))))
+ (ein:cell-append-mime-type json (slot-value cell 'dynamic))
+ (ein:insert-read-only "\n"))
(defcustom ein:output-type-preference
(if (and (fboundp 'shr-insert-document)
@@ -1052,9 +1033,6 @@ prettified text thus be used instead of HTML type."
(setq metadata (plist-put metadata :collapsed (if (slot-value cell 'collapsed) t json-false)))
(setq metadata (plist-put metadata :autoscroll json-false))
(setq metadata (plist-put metadata :ein.tags (format "worksheet-%s" wsidx)))
- (setq metadata (plist-put metadata :ein.hycell (if (ein:hy-codecell-p cell)
- t
- json-false)))
(setq metadata (plist-put metadata :slideshow ss-table))
(unless discard-output
(dolist (output outputs)
diff --git a/lisp/ein-classes.el b/lisp/ein-classes.el
index 2006cf7..9e5786e 100644
--- a/lisp/ein-classes.el
+++ b/lisp/ein-classes.el
@@ -63,9 +63,6 @@
:file : Either :text or :base64
:notebook : :json.
-`ein:$content-checkpoints'
- Names auto-saved checkpoints for content. Stored as a list
- of ( . ) pairs.
"
url-or-port
notebook-version
@@ -78,11 +75,7 @@
mimetype
raw-content
format
- session-p
- checkpoints)
-
-
-
+ session-p)
;;; Websockets
(defstruct ein:$websocket
@@ -148,13 +141,6 @@
`ein:$notebook-api-version' : integer
Major version of the IPython notebook server we are talking to.
-
-`ein:$notebook-checkpoints'
- Names auto-saved checkpoints for content. Stored as a list
- of ( . ) pairs.
-
-`ein:$notebook-q-checkpoints'
- Whether to checkpoint on save. Overrides ein:notebook-create-checkpoint-on-save
"
url-or-port
notebook-id ;; In IPython-2.0 this is "[:path]/[:name].ipynb"
@@ -171,10 +157,7 @@
events
worksheets
scratchsheets
- api-version
- autosave-timer
- checkpoints
- q-checkpoints)
+ api-version)
@@ -306,11 +289,6 @@ This cell is executed when the connected buffer is saved,
provided that (1) this flag is `t' and (2) corresponding
auto-execution mode flag in the connected buffer is `t'.")))
-;; Use this cell to execute hy code in notebook running a Python kernel.
-(defclass ein:hy-codecell (ein:codecell)
- ((cell-type :initarg :cell-type :initform "hy-code"))
- "Codecell that supports executing hy code from within a Python kernel.")
-
(defclass ein:textcell (ein:basecell)
((cell-type :initarg :cell-type :initform "text")
(element-names :initform (:prompt :input :footer :slidetype))))
@@ -366,9 +344,7 @@ auto-execution mode flag in the connected buffer is `t'.")))
"NotebookStatus"
:s2m
'((notebook_saving.Notebook . "Saving Notebook...")
- (notebook_create_checkpoint.Notebook . "Creating Checkpoint...")
(notebook_saved.Notebook . "Notebook is saved")
- (notebook_checkpoint_created.Notebook . "Checkpoint created.")
(notebook_save_failed.Notebook . "Failed to save Notebook!")))
:type ein:notification-status)
(kernel
diff --git a/lisp/ein-company.el b/lisp/ein-company.el
deleted file mode 100644
index 4bef496..0000000
--- a/lisp/ein-company.el
+++ /dev/null
@@ -1,124 +0,0 @@
-;;; -*- mode: emacs-lisp; lexical-binding: t; -*-
-;;; ein-company.el --- Support for completion using company back-end.
-
-;; Copyright (C) 2017 - John Miller
-
-;; Author: John Miller
-
-;; This file is NOT part of GNU Emacs.
-
-;; ein-company.el is free software: you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation, either version 3 of the License, or
-;; (at your option) any later version.
-
-;; ein-company.el is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with ein-company.el. If not, see .
-
-;;; Commentary:
-
-;;
-
-;;; Code:
-
-(eval-when-compile (require 'cl))
-(require 'deferred)
-(require 'ein-completer)
-(require 'company nil t)
-
-(autoload 'company-begin-backend "company")
-(autoload 'company-doc-buffer "company")
-
-(defun ein:company--deferred-complete ()
- (let ((d (deferred:new #'identity)))
- (ein:completer-complete
- (ein:get-kernel)
- (list :complete_reply
- (cons (lambda (d* &rest args) (deferred:callback-post d* args))
- d))
- (apply-partially (lambda (d* err) (deferred:callback-post d* err)) d))
- d))
-
-(defun ein:company--complete (prefix fetcher)
- (deferred:$
- (deferred:next
- (lambda ()
- (ein:company--deferred-complete)))
- (deferred:nextc it
- (lambda (replies)
- (unless (stringp replies) ;; if not an error
- (ein:completions--prepare-matches prefix fetcher replies))))))
-
-(defun ein:completions--prepare-matches (prefix fetcher replies)
- (destructuring-bind
- ((&key matches cursor_start cursor_end &allow-other-keys) ; :complete_reply
- _metadata)
- replies
- (let ((nix (- cursor_end cursor_start))
- prefixed-matches)
- (dolist (match matches)
- (setq prefixed-matches
- (nconc prefixed-matches (list (concat prefix (substring match nix))))))
- (ein:completions--build-oinfo-cache prefixed-matches)
- (funcall fetcher prefixed-matches))))
-
-;;;###autoload
-(defun ein:company-backend (command &optional arg &rest _)
- (interactive (list 'interactive))
- (cl-case command
- (interactive (company-begin-backend 'ein:company-backend))
- (prefix (and (eq ein:completion-backend 'ein:use-company-backend)
- (or (ein:worksheet-at-codecell-p) ein:connect-mode)
- (ein:get-kernel)
- (ein:object-prefix-at-point)))
- (annotation (let ((kernel (ein:get-kernel)))
- (ein:aif (gethash arg (ein:$kernel-oinfo-cache kernel))
- (plist-get it :definition))))
- (doc-buffer (cons :async
- (lambda (cb)
- (ein:company-handle-doc-buffer arg cb))))
- (location (cons :async
- (lambda (cb)
- (ein:pytools-find-source (ein:get-kernel-or-error)
- arg
- cb))))
- (candidates
- (let* ((kernel (ein:get-kernel-or-error))
- (cached (ein:completions-get-cached arg (ein:$kernel-oinfo-cache kernel))))
- (ein:aif cached it
- (unless (ein:company--punctuation-check (thing-at-point 'line)
- (current-column))
- (case ein:completion-backend
- (t
- (cons :async
- (lambda (cb)
- (ein:company--complete arg cb)))))))))))
-
-(defun ein:company--punctuation-check (thing col)
- (or (string-match "[[:nonascii:]]" thing)
- (let ((query (ein:trim-right (subseq thing 0 col) "[\n]")))
- (string-match "[]()\",[{}'=: ]$" query (- col 2)))))
-
-
-(defun ein:company-handle-doc-buffer-finish (packed content _metadata-not-used_)
- (when (plist-get content :found)
- (funcall (plist-get packed :callback) (company-doc-buffer
- (ansi-color-apply (cadr (plist-get content :data)))))))
-
-(defun ein:company-handle-doc-buffer (object cb)
- (ein:kernel-object-info-request (ein:get-kernel-or-error)
- object
- (list :inspect_reply
- (cons #'ein:company-handle-doc-buffer-finish
- (list :object object
- :callback cb)))))
-
-(when (boundp 'company-backends)
- (add-to-list 'company-backends 'ein:company-backend))
-
-(provide 'ein-company)
diff --git a/lisp/ein-completer.el b/lisp/ein-completer.el
index 61b223d..b0a1ca5 100644
--- a/lisp/ein-completer.el
+++ b/lisp/ein-completer.el
@@ -26,8 +26,6 @@
;;; Code:
-(declare-function ac-cursor-on-diable-face-p "auto-complete")
-
(eval-when-compile (require 'cl))
(require 'ein-core)
@@ -35,7 +33,6 @@
(require 'ein-subpackages)
(require 'ein-kernel)
(require 'ein-pytools)
-(require 'ein-ac)
(require 'dash)
(make-obsolete-variable 'ein:complete-on-dot nil "0.15.0")
@@ -43,7 +40,6 @@
(defun ein:completer-choose ()
(cond
((eq ein:completion-backend 'ein:use-none-backend) #'ignore)
- ((ein:eval-if-bound 'auto-complete-mode) #'ein:completer-finish-completing-ac)
(t #'ein:completer-finish-completing-default)))
(defun ein:completer-beginning (matched-text)
@@ -73,12 +69,7 @@
(insert word))))
(defun ein:completer-complete (kernel callbacks errback)
- "Start completion for the code at point.
-
- EXPAND keyword argument is supported by
- `ein:completer-finish-completing-ac'. When it is specified,
- it overrides `ac-expand-on-auto-complete' when calling
- `auto-complete'."
+ "Start completion for the code at point."
(interactive (list (ein:get-kernel)
(list :complete_reply
(cons #'ein:completer-finish-completing '(:expand nil)))
@@ -97,16 +88,9 @@
when (string-prefix-p partial candidate)
collect candidate))
-(defun ein:completions--get-oinfo (obj)
+(defun ein:completions--get-oinfo (_obj)
(let ((d (deferred:new #'identity))
- (kernel (ein:get-kernel)))
- (if (ein:kernel-live-p kernel)
- (ein:kernel-execute
- kernel
- (format "__ein_print_object_info_for(__ein_maybe_undefined_object(r\"%s\", locals()))" obj)
- (list
- :output `(,(lambda (d* &rest args) (deferred:callback-post d* args)) . ,d)))
- (deferred:callback-post d "kernel not live"))
+ (_kernel (ein:get-kernel)))
d))
(defun ein:completions--build-oinfo-cache (objs)
@@ -142,16 +126,6 @@
(prin1 output #'external-debugging-output))
(setf (gethash obj (ein:$kernel-oinfo-cache kernel)) :json-false))))
-;;; Support for Eldoc
-
-(defun ein:completer--get-eldoc-signature ()
- (ein:and-let* ((func (ein:function-at-point))
- (kernel (ein:get-kernel)))
- (ein:aif (gethash func (ein:$kernel-oinfo-cache kernel))
- (ein:kernel-construct-defstring it)
- (ein:completions--build-oinfo-cache (list func))
- nil)))
-
(provide 'ein-completer)
;;; ein-completer.el ends here
diff --git a/lisp/ein-connect.el b/lisp/ein-connect.el
index ec5667b..aac6753 100644
--- a/lisp/ein-connect.el
+++ b/lisp/ein-connect.el
@@ -33,7 +33,6 @@
(require 'eieio)
(require 'company nil t)
(require 'ein-notebook)
-(eval-when-compile (require 'auto-complete))
(autoload 'company-mode "company")
@@ -199,8 +198,6 @@ notebooks."
(if (or (not no-reconnection)
(not ein:%connect%))
(let ((connection (ein:connect-setup notebook buffer)))
- (when (ein:eval-if-bound 'ac-sources)
- (push 'ac-source-ein-async ac-sources))
(ein:connect-mode)
(ein:log 'info "Connected to %s"
(ein:$notebook-notebook-name notebook))
@@ -398,15 +395,7 @@ notebook."
:lighter (:eval (ein:connect-mode-get-lighter))
:keymap ein:connect-mode-map
:group 'ein
- (case ein:completion-backend
- (ein:use-ac-backend
- (define-key ein:connect-mode-map "." 'ein:ac-dot-complete)
- (auto-complete-mode))
- (ein:use-company-backend
- (if (not (boundp 'company-backends))
- (error "ein:connect-mode: company unsupported")
- (cl-assert (member 'ein:company-backend company-backends))
- (company-mode)))))
+ )
(put 'ein:connect-mode 'permanent-local t)
diff --git a/lisp/ein-contents-api.el b/lisp/ein-contents-api.el
index 47f7546..3ba064d 100644
--- a/lisp/ein-contents-api.el
+++ b/lisp/ein-contents-api.el
@@ -427,71 +427,6 @@ global setting. For global setting and more information, see
&aux (resp-string (format "STATUS: %s DATA: %s" (request-response-status-code response) data)))
(ein:log 'debug "ein:query-sessions--complete %s" resp-string))
-
-;;; Checkpoints
-
-
-(defun ein:content-query-checkpoints (content &optional callback cbargs)
- (let* ((url (ein:content-url content "checkpoints")))
- (ein:query-singleton-ajax
- (list 'content-query-checkpoints url)
- url
- :type "GET"
- :timeout ein:content-query-timeout
- :parser #'ein:json-read
- :sync ein:force-sync
- :success (apply-partially #'ein:content-query-checkpoints-success content callback cbargs)
- :error (apply-partially #'ein:content-query-checkpoints-error content))))
-
-(defun ein:content-create-checkpoint (content &optional callback cbargs)
- (let* ((url (ein:content-url content "checkpoints")))
- (ein:query-singleton-ajax
- (list 'content-query-checkpoints url)
- url
- :type "POST"
- :timeout ein:content-query-timeout
- :parser #'ein:json-read
- :sync ein:force-sync
- :success (apply-partially #'ein:content-query-checkpoints-success content callback cbargs)
- :error (apply-partially #'ein:content-query-checkpoints-error content))))
-
-(defun ein:content-restore-checkpoint (content checkpoint-id &optional callback cbargs)
- (let* ((url (ein:content-url content "checkpoints" checkpoint-id)))
- (ein:query-singleton-ajax
- (list 'content-query-checkpoints url)
- url
- :type "POST"
- :timeout ein:content-query-timeout
- :parser #'ein:json-read
- :sync ein:force-sync
- :success (when callback
- (apply callback cbargs))
- :error (apply-partially #'ein:content-query-checkpoints-error content))))
-
-(defun ein:content-delete-checkpoint (content checkpoint-id &optional callback cbargs)
- (let* ((url (ein:content-url content "checkpoints" checkpoint-id)))
- (ein:query-singleton-ajax
- (list 'content-query-checkpoints url)
- url
- :type "DELETE"
- :timeout ein:content-query-timeout
- :parser #'ein:json-read
- :sync ein:force-sync
- :success (when callback
- (apply callback cbargs))
- :error (apply-partially #'ein:content-query-checkpoints-error content))))
-
-(defun* ein:content-query-checkpoints-success (content cb cbargs &key data status response &allow-other-keys)
- (unless (listp (car data))
- (setq data (list data)))
- (setf (ein:$content-checkpoints content) data)
- (when cb
- (apply cb content cbargs)))
-
-(defun* ein:content-query-checkpoints-error (content &key symbol-status response &allow-other-keys)
- (ein:log 'error "Content checkpoint operation failed with status %s (%s)." symbol-status response))
-
-
;;; Uploads
diff --git a/lisp/ein-core.el b/lisp/ein-core.el
index 9bca8b5..7511dfb 100644
--- a/lisp/ein-core.el
+++ b/lisp/ein-core.el
@@ -346,8 +346,7 @@ but can operate in different contexts."
(ein:generic-getter '(ein:get-kernel--notebook
ein:get-kernel--worksheet
ein:get-kernel--shared-output
- ein:get-kernel--connect
- ein:get-kernel--worksheet-in-edit-cell)))
+ ein:get-kernel--connect)))
(defun ein:get-kernel-or-error ()
(or (ein:get-kernel)
diff --git a/lisp/ein-dev.el b/lisp/ein-dev.el
index a94e6ba..53309b6 100644
--- a/lisp/ein-dev.el
+++ b/lisp/ein-dev.el
@@ -27,6 +27,7 @@
(eval-when-compile (require 'cl))
(declare-function rst-shift-region "rst")
+(declare-function markdown-mode "markdown-mode")
(require 'ein-notebook)
(require 'ein-subpackages)
@@ -49,8 +50,7 @@
(let* ((dir (or dir ein:source-dir))
(regex (or regex ".+"))
(files (-remove #'(lambda (x)
- (or (string-match-p "ein-pkg\\.el" x)
- (string-match-p "ein-smartrep\\.el" x)))
+ (string-match-p "ein-pkg\\.el" x))
(and
(file-accessible-directory-p dir)
(directory-files dir 'full regex)))))
@@ -69,7 +69,6 @@
(loop for f in (directory-files ein:source-dir nil "^ein-.*\\.el$")
unless (or (equal f "ein-pkg.el")
(equal f "ein-autoloads.el")
- (equal f "ein-smartrep.el")
(funcall ignore-p f))
do (require (intern (file-name-sans-extension f)) nil t))
;; For `widget-button-press':
@@ -125,7 +124,7 @@ callback (`websocket-callback-debug-on-error') is enabled."
(setq request-log-level (quote debug))
(lexical-let ((curl-trace (concat temporary-file-directory "curl-trace")))
(nconc request-curl-options `("--trace-ascii" ,curl-trace))
- (add-function :after
+ (add-function :after
(symbol-function 'request--curl-callback)
(lambda (&rest args)
(if (file-readable-p curl-trace)
diff --git a/lisp/ein-hy.el b/lisp/ein-hy.el
deleted file mode 100644
index a08ceb0..0000000
--- a/lisp/ein-hy.el
+++ /dev/null
@@ -1,52 +0,0 @@
-;;; ein-hy.el --- Hylang Support -*- lexical-binding: t; -*-
-
-;; (C) 2018 - John M. Miller
-
-;; Author: John Miller
-
-;; This file is NOT part of GNU Emacs.
-
-;; ein-hy.el is free software: you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation, either version 3 of the License, or
-;; (at your option) any later version.
-
-;; ein-hy.el is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with ein-hy.el. If not, see .
-
-;;; Commentary:
-
-;;; Code:
-
-(require 'cl)
-(require 'ein-classes)
-
-(cl-defmethod ein:cell-insert-prompt ((cell ein:hy-codecell))
- "Insert prompt of the CELL in the buffer.
-Called from ewoc pretty printer via `ein:cell-pp'."
- ;; Newline is inserted in `ein:cell-insert-input'.
- (ein:insert-read-only
- (concat
- (format "In (hy) [%s]" (or (ein:oref-safe cell 'input-prompt-number) " "))
- (ein:maybe-show-slideshow-data cell)
- (when (slot-value cell 'autoexec) " %s" ein:cell-autoexec-prompt))
- 'font-lock-face 'ein:cell-input-prompt))
-
-(cl-defmethod ein:cell-execute-internal ((cell ein:hy-codecell)
- kernel code &rest args)
- (ein:cell-clear-output cell t t t)
- (ein:cell-set-input-prompt cell "*")
- (ein:cell-running-set cell t)
- (setf (slot-value cell 'dynamic) t)
- (apply #'ein:kernel-execute kernel (ein:pytools-wrap-hy-code code) (ein:cell-make-callbacks cell) args))
-
-(cl-defmethod ein:cell-to-nb4-json :before ((cell ein:hy-codecell) _ &optional _ignore)
- (let ((metadata (slot-value cell 'metadata)))
- (setf metadata (plist-put metadata :ein.hycell t))))
-
-(provide 'ein-hy)
diff --git a/lisp/ein-inspector.el b/lisp/ein-inspector.el
deleted file mode 100644
index ad24fe5..0000000
--- a/lisp/ein-inspector.el
+++ /dev/null
@@ -1,125 +0,0 @@
-;;; -*- mode: emacs-lisp; lexical-binding: t -*-
-;;; ein-inspector.el --- An inspector, in emacs, for Python
-
-;; Copyright (C) 2017 - John Miller
-
-;; Authors: Takafumi Arakaki
-;; John M. Miller
-
-;; This file is NOT part of GNU Emacs.
-
-;; ein-inspector.el is free software: you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation, either version 3 of the License, or
-;; (at your option) any later version.
-
-;; ein-inspector.el is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with ein-inspector.el. If not, see .
-
-;;; Commentary:
-
-;;; Code:
-
-(require 'ein-pytools)
-
-;;;###autoload
-(defun ein:inspect-object (kernel object)
- (interactive (list (ein:get-kernel-or-error)
- (ein:object-at-point-or-error)))
- (ein:kernel-execute kernel
- (format "__import__('ein_inspector').generate_inspector_data('%s', globals(), locals())"
- object)
- (list
- :output
- (cons #'ein:prepare-inspector
- (list kernel object)))))
-
-(defun ein:prepare-inspector (packed _msg-type content _metadata)
- (destructuring-bind (_kernel oname)
- packed
- (ein:aif (or (plist-get content :text) (plist-get content :data))
- (let ((oinfo (ein:json-read-from-string it)))
- (if (not (plist-get oinfo :type))
- (ein:log 'warn "[EIN:INSPECTOR]: %s" (plist-get oinfo :error))
- (ein:render-inspector oinfo)))
- (ein:log 'warn "[EIN:INSPECTOR]: Could not find inspect data for object %s." oname))))
-
-(defclass ein:iobject ()
- ((name :accessor ein:iobject-name :documentation "String representation can be evaluated in python to generate the object being inspected.")
- (type :accessor ein:iobject-type :documentation "Python type of object, as returned by `type()`.")
- (repr :accessor ein:iobject-repr :documentation "Value of object, as returned by its `__str__` method.")
- (source-file :accessor ein:iobject-sfile :documentation "If availabe, the filename where the source for this object is to be found.")
- (source-lines :accessor ein:iobject-slines :documentation "If available, the line in the file where the source for this object is found.")
- (doc :accessor ein:iobject-doc :documentation "If available, the documentation string for this object."))
- :documentation "Class to hold information returned by Python `inspect` module for a Python object identified in the `name` slot.")
-
-(defun ein:new-inspector-object (object-info)
- (make-instance 'ein:iobject
- :name (plist-get object-info :name)
- :type (plist-get object-info :type)
- :repr (plist-get object-info :repr)
- :source-file (plist-get object-info :source_file)
- :source-lines (plist-get object-info :source_lines)
- :doc (plist-get object-info :doc)))
-
-(defvar ein:inspector-visit-source-map (make-sparse-keymap))
-
-(defvar ein:inspector-mode-map
- (let ((map (make-sparse-keymap)))
- (set-keymap-parent map (make-composed-keymap widget-keymap
- special-mode-map))
- map)
- "Keymap for ein:inspector-mode.")
-
-(define-derived-mode ein:inspector-mode special-mode "EIN:INSPECTOR-MODE"
- "Major mode for inspector Python objects from the emacs-ipython-notebook."
- )
-
-
-
-(defun ein:render-inspector (oinfo)
- (let ((name (plist-get oinfo :name)))
- (switch-to-buffer (format "*EIN Inspector: %s*" name))
- (kill-all-local-variables)
- (let ((inhibit-read-only t))
- (erase-buffer))
- (remove-overlays)
- (lexical-let* ((type (plist-get oinfo :type))
- (repr (plist-get oinfo :repr))
- (sfile (plist-get oinfo :source_file))
- (slines (last (plist-get oinfo :source_lines)))
- (info-str (format "%s = {%s} %s" name type repr)))
- (if sfile
- (widget-create 'link
- :notify
- (lambda (&rest _ignore)
- (ein:goto-file sfile (car slines)))
- info-str)
- (widget-insert (propertize info-str 'face 'bold)))
- (widget-insert (format "\n\n%s\n\n" (make-string 80 ?\u2501)))
- (widget-insert (format "%s\n\n%s\n\n" (plist-get oinfo :doc) (make-string 80 ?\u2501)))
- (widget-insert (propertize (format "%s: %s\n" type name)
- 'face 'bold))))
- (ein:inspector-mode)
- (widget-setup))
-
-
-
-(defun ein:inspector-visit-source ()
- (message "Visit source!"))
-
-(defun ein:inspector-visit-thing ())
-
-(defun ein:inspector-section-toggle (_section))
-
-(defun ein:inspector-section-show (_section))
-
-(defun ein:inspector-section-hide (_section)
- )
-
-(provide 'ein-inspector)
diff --git a/lisp/ein-jupyter.el b/lisp/ein-jupyter.el
index 29cafc9..baa1acd 100644
--- a/lisp/ein-jupyter.el
+++ b/lisp/ein-jupyter.el
@@ -213,8 +213,6 @@ the log of the running jupyter server."
(if (numberp port)
`("--port" ,(format "%s" port)
"--port-retries" "0")))))
- (when (eql system-type 'windows-nt)
- (accept-process-output proc (/ ein:jupyter-server-run-timeout 1000)))
(loop repeat 30
until (car (ein:jupyter-server-conn-info ein:jupyter-server-buffer-name))
do (sleep-for 0 500)
@@ -255,19 +253,14 @@ the log of the running jupyter server."
do (ein:query-running-process-table)
until (zerop (hash-table-count ein:query-running-process-table))
do (sleep-for 0 500))
- (if (eq system-type 'windows-nt)
- (progn
- (ein:undocumented-shutdown url-or-port)
- (ein:aif (ein:jupyter-server-process)
- (delete-process it)))
- (lexical-let* ((proc (ein:jupyter-server-process))
- (pid (process-id proc)))
- (ein:log 'info "Signaled %s with pid %s" proc pid)
- (signal-process pid 15)
- (run-at-time 2 nil
- (lambda ()
- (ein:log 'info "Resignaled %s with pid %s" proc pid)
- (signal-process pid 15)))))
+ (lexical-let* ((proc (ein:jupyter-server-process))
+ (pid (process-id proc)))
+ (ein:log 'info "Signaled %s with pid %s" proc pid)
+ (signal-process pid 15)
+ (run-at-time 2 nil
+ (lambda ()
+ (ein:log 'info "Resignaled %s with pid %s" proc pid)
+ (signal-process pid 15))))
;; `ein:notebooklist-sentinel' frequently does not trigger
(ein:notebooklist-list-remove url-or-port)
diff --git a/lisp/ein-kernelinfo.el b/lisp/ein-kernelinfo.el
index bb87e46..c2f904e 100644
--- a/lisp/ein-kernelinfo.el
+++ b/lisp/ein-kernelinfo.el
@@ -41,76 +41,17 @@ in these buffer will be synced with the kernel's cwd.")
(hostname
:initarg :hostname :type string
:documentation "Host name of the machine where the kernel is running on.")
- (language
- :initarg :language :type string
- :accessor ein:kernelinfo-language
- :documentation "Language for the running kernel.")
(ccwd
:initarg :ccwd :type string
:documentation "cached CWD (last time checked CWD)."))
:documentation "Info related (but unimportant) to kernel")
-(defun ein:kernelinfo-new (kernel get-buffers kernel-language)
+(defun ein:kernelinfo-new (kernel get-buffers)
"Make a new `ein:kernelinfo' instance based on KERNEL and GET-BUFFERS."
(let ((kerinfo (make-instance 'ein:kernelinfo)))
(setf (slot-value kerinfo 'kernel) kernel)
(setf (slot-value kerinfo 'get-buffers) get-buffers)
- (setf (slot-value kerinfo 'language) kernel-language)
- (ein:case-equal kernel-language
- ("python" (ein:kernelinfo-setup-hooks kerinfo)))
kerinfo))
-
-(defun ein:kernelinfo-setup-hooks (kerinfo)
- "Add `ein:kernelinfo-update-*' to `ein:$kernel-after-*-hook'."
- (with-slots (kernel) kerinfo
- (push (cons #'ein:kernelinfo-update-all kerinfo)
- (ein:$kernel-after-start-hook kernel))
- (push (cons #'ein:kernelinfo-update-ccwd kerinfo)
- (ein:$kernel-after-execute-hook kernel))))
-
-(defun ein:kernelinfo-update-all (kerinfo)
- "Update KERINFO slots by triggering all update functions."
- (ein:log 'debug "(ein:kernel-live-p kernel) = %S"
- (ein:kernel-live-p (slot-value kerinfo 'kernel)))
- (ein:kernelinfo-update-ccwd kerinfo)
- (ein:kernelinfo-update-hostname kerinfo))
-
-(defun ein:kernelinfo-update-ccwd (kerinfo)
- "Update cached current working directory (CCWD) and change
-`default-directory' of kernel related buffers."
- (let ((ccwd-string (ein:case-equal (ein:kernelinfo-language kerinfo)
- (("python") "__import__('sys').stdout.write(__import__('os').getcwd())")
- ((t) nil))))
- (when ccwd-string
- (ein:kernel-request-stream
- (slot-value kerinfo 'kernel)
- ccwd-string
- (lambda (cwd kerinfo)
- (with-slots (kernel get-buffers) kerinfo
- (setq cwd (ein:kernel-filename-from-python kernel cwd))
- (oset kerinfo :ccwd cwd)
- ;; sync buffer's `default-directory' with CWD
- (when (file-accessible-directory-p cwd)
- (dolist (buffer (ein:funcall-packed get-buffers))
- (when (buffer-live-p buffer)
- (with-current-buffer buffer
- (setq default-directory (file-name-as-directory cwd))))))))
- (list kerinfo)))))
-
-(defun ein:kernelinfo-update-hostname (kerinfo)
- "Get hostname in which kernel is running and store it in KERINFO."
- (let ((hostname-string (ein:case-equal (ein:kernelinfo-language kerinfo)
- (("python") "__import__('sys').stdout.write(__import__('socket').gethostname())")
- ((t) nil))))
- (when hostname-string
- (ein:kernel-request-stream
- (slot-value kerinfo 'kernel)
- hostname-string ; "__import__('sys').stdout.write(__import__('socket').gethostname())" ; uname() not available in windows
- (lambda (hostname kerinfo)
- (oset kerinfo :hostname hostname))
- (list kerinfo)))))
-
-
(provide 'ein-kernelinfo)
;;; ein-kernelinfo.el ends here
diff --git a/lisp/ein-multilang.el b/lisp/ein-multilang.el
index 6954466..92b399e 100644
--- a/lisp/ein-multilang.el
+++ b/lisp/ein-multilang.el
@@ -102,10 +102,6 @@ This function may raise an error."
'ein:worksheet-end-of-cell-input)
(ein:ml-set-font-lock-defaults))
-(eval-after-load "auto-complete"
- '(add-to-list 'ac-modes 'ein:notebook-multilang-mode))
-
-
;;; Language setup functions
(defun ein:ml-narrow-to-cell ()
diff --git a/lisp/ein-notebook.el b/lisp/ein-notebook.el
index 9cf89c2..5f076a0 100644
--- a/lisp/ein-notebook.el
+++ b/lisp/ein-notebook.el
@@ -34,7 +34,6 @@
(eval-when-compile (require 'cl))
-(eval-when-compile (require 'auto-complete))
(require 'ewoc)
(require 'mumamo nil t)
@@ -50,7 +49,6 @@
(require 'ein-kernel)
(require 'ein-kernelinfo)
(require 'ein-cell)
-(require 'ein-cell-edit)
(require 'ein-cell-output)
(require 'ein-worksheet)
(require 'ein-iexec)
@@ -65,7 +63,6 @@
(require 'ein-query)
(require 'ein-pytools)
(require 'ein-traceback)
-(require 'ein-inspector)
(require 'ein-shared-output)
(require 'ein-notebooklist)
(require 'ein-multilang)
@@ -74,51 +71,6 @@
;;; Configuration
-(make-obsolete-variable 'ein:notebook-discard-output-on-save nil "0.2.0")
-
-(declare-function ein:smartrep-config "ein-smartrep")
-
-(defcustom ein:use-smartrep nil
- "Set to `t' to use preset smartrep configuration.
-
-.. warning:: When used with MuMaMo (see `ein:notebook-modes'),
- keyboard macro which manipulates cell (add, remove, move,
- etc.) may start infinite loop (you need to stop it with
- ``C-g``). Please be careful using this option if you are a
- heavy keyboard macro user. Using keyboard macro for other
- commands is fine.
-
-.. (Comment) I guess this infinite loop happens because the three
- modules (kmacro.el, mumamo.el and smartrep.el) touches to
- `unread-command-events' in somehow inconsistent ways."
- :type 'boolean
- :group 'ein)
-
-(defvar *ein:notebook--pending-query* (make-hash-table :test 'equal)
- "A map: (URL-OR-PORT . PATH) => t/nil")
-
-(defcustom ein:notebook-autosave-frequency 300
- "Sets the frequency (in seconds) at which the notebook is
-automatically saved, per IPEP15. Set to 0 to disable this feature.
-
-Autosaves are automatically enabled when a notebook is opened,
-but can be controlled manually via `ein:notebook-enable-autosave'
-and `ein:notebook-disable-autosave'.
-
-If you wish to change the autosave frequency for the current
-notebook call `ein:notebook-update-autosave-freqency'.
-
-"
- :type 'number
- :group 'ein)
-
-(defcustom ein:notebook-create-checkpoint-on-save t
- "If non-nil a checkpoint will be created every time the
-notebook is saved. Otherwise checkpoints must be created manually
-via `ein:notebook-create-checkpoint'."
- :type 'boolean
- :group 'ein)
-
(defcustom ein:notebook-discard-output-on-save 'no
"Configure if the output part of the cell should be saved or not.
@@ -140,6 +92,16 @@ a function
(const :tag "Yes" 'yes)
)
:group 'ein)
+(make-obsolete-variable 'ein:use-smartrep nil "0.17.0")
+
+(defvar *ein:notebook--pending-query* (make-hash-table :test 'equal)
+ "A map: (URL-OR-PORT . PATH) => t/nil")
+
+(make-obsolete-variable 'ein:notebook-autosave-frequency nil "0.17.0")
+
+(make-obsolete-variable 'ein:notebook-create-checkpoint-on-save nil "0.17.0")
+
+(make-obsolete-variable 'ein:notebook-discard-output-on-save nil "0.17.0")
(defun ein:notebook-cell-has-image-output-p (-ignore- cell)
(ein:cell-has-image-ouput-p cell))
@@ -405,11 +367,11 @@ where `created' indicates a new notebook or an existing one.
(add-function :before errback pending-clear)
(ein:content-query-contents url-or-port path
(apply-partially #'ein:notebook-open--callback
- notebook callback0 (not no-pop))
+ notebook callback0)
errback))))
notebook))
-(defun ein:notebook-open--callback (notebook callback0 q-checkpoints content)
+(defun ein:notebook-open--callback (notebook callback0 content)
(ein:log 'verbose "Opened notebook %s" (ein:$notebook-notebook-path notebook))
(let ((notebook-path (ein:$notebook-notebook-path notebook)))
(ein:gc-prepare-operation)
@@ -433,12 +395,9 @@ where `created' indicates a new notebook or an existing one.
(ein:$notebook-notebook-name notebook)))
(setf (ein:$notebook-kernelinfo notebook)
(ein:kernelinfo-new (ein:$notebook-kernel notebook)
- (cons #'ein:notebook-buffer-list notebook)
- (symbol-name (ein:get-mode-for-kernel (ein:$notebook-kernelspec notebook)))))
+ (cons #'ein:notebook-buffer-list notebook)))
(ein:notebook-put-opened-notebook notebook)
(ein:notebook--check-nbformat (ein:$content-raw-content content))
- (setf (ein:$notebook-q-checkpoints notebook) q-checkpoints)
- (ein:notebook-enable-autosaves notebook)
(ein:gc-complete-operation))))
(defun ein:notebook-maybe-set-kernelspec (notebook content-metadata)
@@ -478,56 +437,6 @@ of minor mode."
;;; Initialization.
-(defun ein:notebook-enable-autosaves (notebook)
- "Enable automatic, periodic saving for notebook."
- (interactive
- (list (or (ein:get-notebook)
- (ein:aand (ein:notebook-opened-buffer-names)
- (with-current-buffer (ein:completing-read
- "Notebook: " it nil t)
- (ein:get-notebook))))))
- (when (and (ein:$notebook-q-checkpoints notebook)
- (> ein:notebook-autosave-frequency 0))
- (setf (ein:$notebook-autosave-timer notebook)
- (run-at-time ein:notebook-autosave-frequency
- ein:notebook-autosave-frequency
- #'ein:notebook-maybe-save-notebook
- notebook))
- (ein:log 'verbose "Enabling autosaves for %s with frequency %s seconds."
- (ein:$notebook-notebook-name notebook)
- ein:notebook-autosave-frequency)))
-
-(defun ein:notebook-disable-autosaves (notebook)
- "Disable automatic, periodic saving for current notebook."
- (interactive
- (list (or (ein:get-notebook)
- (ein:aand (ein:notebook-opened-buffer-names)
- (with-current-buffer (ein:completing-read
- "Notebook: " it nil t)
- (ein:get-notebook))))))
- (if (and notebook (ein:$notebook-autosave-timer notebook))
- (progn
- (ein:log 'verbose "Disabling auto checkpoints for notebook %s" (ein:$notebook-notebook-name notebook))
- (cancel-timer (ein:$notebook-autosave-timer notebook)))))
-
-(defun ein:notebook-update-autosave-frequency (new-frequency notebook)
- "Change the autosaves frequency for the current notebook, or
-for a notebook selected by the user if not currently inside a
-notebook buffer."
- (interactive
- (list (read-number "New autosaves frequency (0 to disable): ")
- (or (ein:get-notebook)
- (ein:aand (ein:notebook-opened-buffer-names)
- (with-current-buffer (ein:completing-read
- "Notebook: " it nil t)
- (ein:get-notebook))))))
- (if notebook
- (progn
- (setq ein:notebook-autosave-frequency new-frequency)
- (ein:notebook-disable-autosaves notebook)
- (ein:notebook-enable-autosaves notebook))
- (message "Open notebook first")))
-
(defun ein:notebook-bind-events (notebook events)
"Bind events related to PAGER to the event handler EVENTS."
(setf (ein:$notebook-events notebook) events)
@@ -607,9 +516,7 @@ notebook buffer then the user will be prompted to select an opened notebook."
base-url
(ein:$notebook-events notebook)
(ein:$notebook-api-version notebook))))
- (setf (ein:$notebook-kernel notebook) kernel)
- (when (eq (ein:get-mode-for-kernel (ein:$notebook-kernelspec notebook)) 'python)
- (ein:pytools-setup-hooks kernel notebook))))
+ (setf (ein:$notebook-kernel notebook) kernel)))
(defun ein:notebook-reconnect-session-command ()
"It seems convenient but undisciplined to blithely create a new session if the original one no longer exists."
@@ -628,14 +535,6 @@ notebook buffer then the user will be prompted to select an opened notebook."
'ein:notebook-request-tool-tip-or-help-command
'ein:pytools-request-tooltip-or-help "0.1.2")
-(defun ein:notebook-ac-dot-complete ()
- "Insert dot and request completion."
- (interactive)
- (if (and (ein:get-notebook)
- (ein:codecell-p (ein:get-cell-at-point)))
- (call-interactively #'ein:ac-dot-complete)
- (insert ".")))
-
(defun ein:notebook-kernel-interrupt-command ()
"Interrupt the kernel.
This is equivalent to do ``C-c`` in the console program."
@@ -888,8 +787,6 @@ This is equivalent to do ``C-c`` in the console program."
(ein:$notebook-worksheets notebook))
(ein:events-trigger (ein:$notebook-events notebook)
'notebook_saved.Notebook)
- (when ein:notebook-create-checkpoint-on-save
- (ein:notebook-create-checkpoint notebook))
(when callback
(apply callback cbargs)))
@@ -1041,48 +938,6 @@ notebook worksheets."
:type "notebook"
:notebook-version (ein:$notebook-api-version notebook)))
-(defun ein:notebook-create-checkpoint (notebook)
- "Create checkpoint for current notebook based on most recent save."
- (interactive (list (ein:get-notebook)))
- (if (ein:$notebook-q-checkpoints notebook)
- (ein:content-create-checkpoint
- (ein:fast-content-from-notebook notebook)
- (lexical-let ((notebook notebook))
- #'(lambda (content)
- (ein:log 'verbose "Checkpoint %s for %s generated."
- (plist-get (first (ein:$content-checkpoints content)) :id)
- (ein:$notebook-notebook-name notebook))
- (setf (ein:$notebook-checkpoints notebook)
- (ein:$content-checkpoints content)))))))
-
-(defun ein:notebook-list-checkpoint-ids (notebook)
- (unless (ein:$notebook-checkpoints notebook)
- (ein:content-query-checkpoints (ein:fast-content-from-notebook notebook)
- (lexical-let ((notebook notebook))
- #'(lambda (content)
- (setf (ein:$notebook-checkpoints notebook)
- (ein:$content-checkpoints content)))))
- (sleep-for 0.5))
- (loop for cp in (ein:$notebook-checkpoints notebook)
- collecting (plist-get cp :last_modified)))
-
-(defun ein:notebook-restore-to-checkpoint (notebook checkpoint)
- "Restore notebook to previous checkpoint saved on the Jupyter
-server. Note that if there are multiple checkpoints the user will
-be prompted on which one to use."
- (interactive
- (let* ((notebook (ein:get-notebook))
- (checkpoint (ein:completing-read
- "Select checkpoint: "
- (ein:notebook-list-checkpoint-ids notebook))))
- (list notebook checkpoint)))
- (ein:content-restore-checkpoint (ein:fast-content-from-notebook notebook)
- checkpoint)
- (ein:notebook-close notebook)
- (ein:notebook-open (ein:$notebook-url-or-port notebook)
- (ein:$notebook-notebook-path notebook)))
-
-
;;; Worksheet
(defmacro ein:notebook--worksheet-render-new (notebook type)
@@ -1466,10 +1321,6 @@ Use simple `python-mode' based notebook mode when MuMaMo is not installed::
(defvar ein:notebook-mode-map (make-sparse-keymap))
-(with-eval-after-load "ein-smartrep"
- (ein:smartrep-config ein:notebook-mode-map))
-
-
(defmacro ein:notebook--define-key (keymap key defn)
"Ideally we could override just the keymap binding with a (string . wrapped) cons pair (as opposed to messing with the DEFN itself), but then describe-minor-mode unhelpfully shows ?? for the keymap commands."
`(progn
@@ -1480,8 +1331,6 @@ Use simple `python-mode' based notebook mode when MuMaMo is not installed::
(define-key ,keymap ,key ,defn)))
(let ((map ein:notebook-mode-map))
- (ein:notebook--define-key map "\C-ci" 'ein:inspect-object)
- (ein:notebook--define-key map "\C-c'" 'ein:edit-cell-contents)
(ein:notebook--define-key map "\C-c\C-c" 'ein:worksheet-execute-cell)
(ein:notebook--define-key map (kbd "M-RET") 'ein:worksheet-execute-cell-and-goto-next)
(ein:notebook--define-key map (kbd "")
@@ -1582,8 +1431,7 @@ Use simple `python-mode' based notebook mode when MuMaMo is not installed::
)))
("Cell/Code"
,@(ein:generate-menu
- '(("Edit cell contents in dedicated buffer" ein:edit-cell-contents)
- ("Execute cell" ein:worksheet-execute-cell
+ '(("Execute cell" ein:worksheet-execute-cell
:active (ein:worksheet-at-codecell-p))
("Execute cell and go to next"
ein:worksheet-execute-cell-and-goto-next
@@ -1694,28 +1542,12 @@ watch the fireworks!"
;; It is executed after toggling the mode, and before running MODE-hook.
(when ein:notebook-mode
- (case ein:completion-backend
- (ein:use-ac-backend
- (ein:notebook--define-key ein:notebook-mode-map "." 'ein:notebook-ac-dot-complete)
- (auto-complete-mode))
- (ein:use-company-backend
- (if (not (boundp 'company-backends))
- (error "ein:connect-mode: company unsupported")
- (cl-assert (member 'ein:company-backend company-backends))
- (ein:notebook--define-key ein:notebook-mode-map "." nil)
- (company-mode))))
(ein:aif ein:helm-kernel-history-search-key
(ein:notebook--define-key ein:notebook-mode-map it 'helm-ein-kernel-history))
(ein:aif ein:anything-kernel-history-search-key
(ein:notebook--define-key ein:notebook-mode-map it 'anything-ein-kernel-history))
(setq indent-tabs-mode nil) ;; Being T causes problems with Python code.
- (when (and (featurep 'eldoc) ein:enable-eldoc-support)
- (add-function :before-until (local 'eldoc-documentation-function)
- #'ein:completer--get-eldoc-signature)
- (eldoc-mode))
- (ein:worksheet-imenu-setup)
- (when ein:use-smartrep
- (require 'ein-smartrep))))
+ (ein:worksheet-imenu-setup)))
;; To avoid MuMaMo to discard `ein:notebook-mode', make it
;; permanent local.
@@ -1790,7 +1622,6 @@ the first argument and CBARGS as the rest of arguments."
;; nor `ein:notebook-close' updates ein:notebook--opened-map
(ein:log 'debug "ein:notebook-kill-buffer-callback called")
(when (ein:$notebook-p ein:%notebook%)
- (ein:notebook-disable-autosaves ein:%notebook%)
(ein:notebook-close-worksheet ein:%notebook% ein:%worksheet%)))
(defun ein:notebook-setup-kill-buffer-hook ()
diff --git a/lisp/ein-notebooklist.el b/lisp/ein-notebooklist.el
index 185aaec..02a842b 100644
--- a/lisp/ein-notebooklist.el
+++ b/lisp/ein-notebooklist.el
@@ -35,8 +35,6 @@
(require 'ein-file)
(require 'ein-contents-api)
(require 'ein-subpackages)
-(require 'ein-ac)
-(require 'ein-company)
(require 'deferred)
(require 'dash)
(require 'ido)
@@ -51,10 +49,9 @@
(defcustom ein:notebooklist-render-order
'(render-header
- render-opened-notebooks
render-directory)
"Order of notebook list sections.
-Must contain render-header, render-opened-notebooks, and render-directory."
+Must contain render-header, and render-directory."
:group 'ein
:type 'list
)
@@ -623,33 +620,6 @@ This function is called via `ein:notebook-after-rename-hook'."
(symbol-name ein:jupyter-default-kernel))))
(widget-insert "\n"))))))
-(defun render-opened-notebooks (url-or-port &rest args)
- "Render the opened notebooks section (for ipython>=3)."
- ;; Opened Notebooks Section
- (with-current-buffer (ein:notebooklist-get-buffer url-or-port)
- (widget-insert "\n---------- All Opened Notebooks ----------\n\n")
- (loop for buffer in (ein:notebook-opened-buffers)
- do (progn (widget-create
- 'link
- :notify (lexical-let ((buffer buffer))
- (lambda (&rest ignore)
- (condition-case err
- (switch-to-buffer buffer)
- (error
- (message "%S" err)
- (ein:notebooklist-reload)))))
- "Open")
- (widget-create
- 'link
- :notify (lexical-let ((buffer buffer))
- (lambda (&rest ignore)
- (if (buffer-live-p buffer)
- (kill-buffer buffer))
- (run-at-time 1 nil #'ein:notebooklist-reload)))
- "Close")
- (widget-insert " : " (buffer-name buffer))
- (widget-insert "\n")))))
-
(defun ein:format-nbitem-data (name last-modified)
(let ((dt (date-to-time last-modified)))
(format "%-40s%+20s" name
@@ -935,62 +905,6 @@ and the url-or-port argument of ein:notebooklist-open*."
(ein:notebooklist-login--success-1 url-or-port callback errback))
(t (ein:notebooklist-login--error-1 url-or-port error-thrown response errback))))
-;;;###autoload
-
-(defun ein:notebooklist-change-url-port (new-url-or-port)
- "Update the ipython/jupyter notebook server URL for all the
-notebooks currently opened from the current notebooklist buffer.
-
-This function works by calling `ein:notebook-update-url-or-port'
-on all the notebooks opened from the current notebooklist."
- (interactive (list (ein:notebooklist-ask-url-or-port)))
- (unless (eql major-mode 'ein:notebooklist-mode)
- (error "This command needs to be called from within a notebooklist buffer."))
- (let* ((current-nblist ein:%notebooklist%)
- (old-url (ein:$notebooklist-url-or-port current-nblist))
- (new-url-or-port new-url-or-port)
- (open-nb (ein:notebook-opened-notebooks #'(lambda (nb)
- (equal (ein:$notebook-url-or-port nb)
- (ein:$notebooklist-url-or-port current-nblist))))))
- (ein:notebooklist-open* new-url-or-port)
- (loop for x upfrom 0 by 1
- until (or (get-buffer (format ein:notebooklist-buffer-name-template new-url-or-port))
- (= x 100))
- do (sit-for 0.1))
- (dolist (nb open-nb)
- (ein:notebook-update-url-or-port new-url-or-port nb))
- (kill-buffer (ein:notebooklist-get-buffer old-url))
- (ein:notebooklist-open* new-url-or-port nil nil nil (lambda (buffer url-or-port)
- (pop-to-buffer buffer)))))
-
-(defun ein:notebooklist-change-url-port--deferred (new-url-or-port)
- (lexical-let* ((current-nblist ein:%notebooklist%)
- (old-url (ein:$notebooklist-url-or-port current-nblist))
- (new-url-or-port new-url-or-port)
- (open-nb (ein:notebook-opened-notebooks
- (lambda (nb)
- (equal (ein:$notebook-url-or-port nb)
- (ein:$notebooklist-url-or-port current-nblist))))))
- (deferred:$
- (deferred:next
- (lambda ()
- (ein:notebooklist-open* new-url-or-port)
- (loop until (get-buffer (format ein:notebooklist-buffer-name-template new-url-or-port))
- do (sit-for 0.1))))
- (deferred:nextc it
- (lambda ()
- (dolist (nb open-nb)
- (ein:notebook-update-url-or-port new-url-or-port nb))))
- (deferred:nextc it
- (lambda ()
- (kill-buffer (ein:notebooklist-get-buffer old-url))
- (ein:notebooklist-open* new-url-or-port nil nil nil (lambda (buffer url-or-port)
- (pop-to-buffer buffer))))))))
-
-;;; Generic getter
-
-
-
(defun ein:get-url-or-port--notebooklist ()
(when (ein:$notebooklist-p ein:%notebooklist%)
(ein:$notebooklist-url-or-port ein:%notebooklist%)))
diff --git a/lisp/ein-notification.el b/lisp/ein-notification.el
index 56f6686..c65617b 100644
--- a/lisp/ein-notification.el
+++ b/lisp/ein-notification.el
@@ -74,13 +74,6 @@ where NS is `:kernel' or `:notebook' slot of NOTIFICATION."
st ; = event-type
#'ein:notification--callback
(cons ns st))))
- (ein:events-on events
- 'notebook_checkpoint_created.Notebook
- #'ein:notification--fadeout-callback
- (list (slot-value notification 'notebook)
- "Checkpoint created."
- 'notebook_checkpoint_created.Notebook
- nil))
(ein:events-on events
'notebook_saved.Notebook
#'ein:notification--fadeout-callback
@@ -320,16 +313,6 @@ Generated by `ein:header-line-define-mouse-commands'" slot)
(ein:notification-tab-create-line
(slot-value ein:%notification% 'tab)))))))
-(defun ein:header-line-setup-maybe ()
- "Setup `header-line-format' for mumamo.
-As `header-line-format' is buffer local variable, it must be set
-for each chunk when in
-See also `ein:ac-setup-maybe'."
- (and (ein:eval-if-bound 'ein:notebook-mode)
- (ein:eval-if-bound 'mumamo-multi-major-mode)
- (setq header-line-format ein:header-line-format)))
-(add-hook 'after-change-major-mode-hook 'ein:header-line-setup-maybe)
-
(provide 'ein-notification)
;;; ein-notification.el ends here
diff --git a/lisp/ein-pkg.el b/lisp/ein-pkg.el
index 4668742..baae978 100644
--- a/lisp/ein-pkg.el
+++ b/lisp/ein-pkg.el
@@ -3,11 +3,9 @@
"Emacs IPython Notebook"
'((emacs "25")
(websocket "20190620.338")
- (auto-complete "1.4.0")
(request "20190621.1622")
(deferred "0.5")
(polymode "20190426.1729")
(markdown-mode "20171116.756")
(dash "2.13.0")
- (s "1.11.0")
- (skewer-mode "1.6.2")))
+ (s "1.11.0")))
diff --git a/lisp/ein-python.el b/lisp/ein-python.el
deleted file mode 100644
index 454b029..0000000
--- a/lisp/ein-python.el
+++ /dev/null
@@ -1,82 +0,0 @@
-;;; ein-python.el --- Workarounds for python.el
-
-;; Copyright (C) 2012 Takafumi Arakaki
-
-;; Author: Takafumi Arakaki
-
-;; This file is NOT part of GNU Emacs.
-
-;; ein-python.el is free software: you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation, either version 3 of the License, or
-;; (at your option) any later version.
-
-;; ein-python.el is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with ein-python.el.
-;; If not, see .
-
-;;; Commentary:
-
-;;
-
-;;; Code:
-
-(require 'python)
-
-(require 'ein-worksheet)
-
-(defvar ein:python-block-start
- (rx line-start
- symbol-start
- (or "def" "class" "if" "elif" "else" "try"
- "except" "finally" "for" "while" "with")
- symbol-end))
-
-(defun ein:python-indent-calculate-indentation--around (orig &rest args)
- "False if there is no python block yet in this cell."
- (condition-case _
- (ein:and-let* ((cell (ein:worksheet-get-current-cell))
- (beg (ein:cell-input-pos-min cell))
- (p (point))
- ((< beg (point))))
- (if (not (search-backward-regexp ein:python-block-start beg t))
- 0
- (goto-char p)
- (apply orig args)))
- (error (apply orig args))))
-
-(advice-add 'python-indent--calculate-indentation :around #'ein:python-indent-calculate-indentation--around)
-
-;; (defadvice python-indent-calculate-indentation
-;; (around ein:python-indent-calculate-levels activate)
-;; "Hack `python-indent-calculate-levels' to reset indent per cell.
-
-;; Let's say you have a notebook something like this::
-
-;; In [1]:
-;; def func():
-;; pass
-
-;; In [2]:
-;; something[]
-
-;; Here, ``[]`` is the cursor position. When you hit the tab here,
-;; you don't expect it to indent. However, python.el tries to follow
-;; the indent of ``func()`` then you get indentation. This advice
-;; workaround this problem.
-
-;; Note that this workaround does not work with the MuMaMo based
-;; notebook mode."
-;; (if (ein:ein-block-start-p)
-;; ad-do-it
-;; 0))
-
-
-(provide 'ein-python)
-
-;;; ein-python.el ends here
diff --git a/lisp/ein-pytools.el b/lisp/ein-pytools.el
index 9607f2b..f9ab0b1 100644
--- a/lisp/ein-pytools.el
+++ b/lisp/ein-pytools.el
@@ -56,9 +56,6 @@ If OTHER-WINDOW is non-`nil', open the file in the other window."
(push (cons #'ein:pytools-load-safely kernel)
(ein:$kernel-after-start-hook kernel)))
-(defun ein:pytools-wrap-hy-code (code)
- (format "__import__('hy').eval(__import__('hy').read_str('''%s'''))" code))
-
(defun ein:pytools-load-safely (kernel)
(with-temp-buffer
(let ((pytools-file (format "%s/%s" ein:source-dir "ein_remote_safe.py")))
diff --git a/lisp/ein-skewer.el b/lisp/ein-skewer.el
deleted file mode 100644
index 52cd0dd..0000000
--- a/lisp/ein-skewer.el
+++ /dev/null
@@ -1,98 +0,0 @@
-;;; -*- mode: emacs-lisp; lexical-binding: t; -*-
-;;; ein-skewer.el --- Cell module
-
-;; (C) 2016 - John M Miller
-
-;; Author: John M Miller
-
-;; This file is NOT part of GNU Emacs.
-
-;; ein-skewer.el is free software: you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation, either version 3 of the License, or
-;; (at your option) any later version.
-
-;; ein-skewre.el is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with ein-cell.el. If not, see .
-
-;;; Commentary:
-
-;; This depends on the skewer package, so likely will get split into
-;; its own package at some point.
-
-;;; Code:
-
-(require 'skewer-mode)
-(require 'skewer-html)
-(require 'simple-httpd)
-
-(defvar *ein:skewer-running-p* nil "True if the emacs httpd server has been started.")
-
-(defun ein:js-prepare-result (result type)
- (list :output_type type :text result))
-
-(defun ein:update-javascript-output (cell json result)
- (let ((val (ein:js-prepare-result
- (or (cdr (assoc 'value result)) "See browser for result.")
- (plist-get json :output_type))))
- (setf (slot-value cell 'outputs) (list val))
- (ein:cell-append-output cell val (slot-value cell 'dynamic))))
-
-(defservlet current-jupyter-cell-output text/html (path)
- (let ((cell-id (file-name-nondirectory path)))
- (insert (gethash cell-id *ein:skewer-cell-output-cache*))))
-
-(defvar *ein:skewer-html-template*
- "
-
- Emacs IPython Notebook
-
-
-
- %s
-
- ")
-
-(defvar *ein:skewer-cell-output-cache* (make-hash-table :test #'equal))
-
-(defun ein:skewer--handle-html (cell string)
- (setf (gethash (slot-value cell 'cell-id) *ein:skewer-cell-output-cache*)
- (format *ein:skewer-html-template* string) ))
-
-;; Format of result is ((id . STR) (type . STR) (status . STR) (value . STR) (time . FLOAT))
-(defun ein:execute-javascript (cell json)
- (unless (httpd-running-p) ;; *ein:skewer-running-p*
- (run-skewer))
- (deferred:$
- (deferred:next
- (lambda ()
- (let ((result nil))
- (ein:aif (plist-get json :html)
- (progn
- (let ((cell-id (slot-value cell 'cell-id)))
- (ein:skewer--handle-html cell it)
- (setq result (list '(id . nil)
- '(type . str)
- '(stats . nil)
- (cons 'value (format "Open http://localhost:8080/current-jupyter-cell-output/%s" cell-id))
- '(time . nil)))
- (browse-url (format "http://localhost:8080/current-jupyter-cell-output/%s" cell-id))))
- (skewer-eval (plist-get json :javascript)
- (lambda (v)
- (setq result v))
- :type (if (plist-get json :html)
- "html"
- "eval")))
- (cl-loop until result
- do (accept-process-output nil 0.01)
- finally (return result)))))
- (deferred:nextc it
- (lambda (result)
- (ein:update-javascript-output cell json result)))))
-
-(provide 'ein-skewer)
diff --git a/lisp/ein-smartrep.el b/lisp/ein-smartrep.el
deleted file mode 100644
index 977afca..0000000
--- a/lisp/ein-smartrep.el
+++ /dev/null
@@ -1,55 +0,0 @@
-;;; ein-smartrep.el --- smartrep integration
-
-;; Copyright (C) 2012- Takafumi Arakaki
-
-;; Author: Takafumi Arakaki
-
-;; This file is NOT part of GNU Emacs.
-
-;; ein-smartrep.el is free software: you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation, either version 3 of the License, or
-;; (at your option) any later version.
-
-;; ein-smartrep.el is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with ein-smartrep.el. If not, see .
-
-;;; Commentary:
-
-;;
-
-;;; Code:
-
-(require 'smartrep nil t)
-
-(defcustom ein:smartrep-notebook-mode-alist
- '(("C-t" . ein:worksheet-toggle-cell-type)
- ("C-l" . ein:worksheet-clear-output)
- ("C-k" . ein:worksheet-kill-cell)
- ("C-y" . ein:worksheet-yank-cell)
- ("C-a" . ein:worksheet-insert-cell-above)
- ("C-b" . ein:worksheet-insert-cell-below)
- ("C-n" . ein:worksheet-goto-next-input)
- ("C-p" . ein:worksheet-goto-prev-input)
- ("C-m" . ein:worksheet-merge-cell)
- ("" . ein:worksheet-move-cell-up)
- ("" . ein:worksheet-move-cell-down))
- "alist passed to `smartrep-define-key'."
- :type '(repeat (cons string function))
- :group 'ein)
-
-(when (fboundp 'smartrep-define-key)
- (defmacro ein:smartrep-config (map)
- `(smartrep-define-key
- ,map
- "C-c"
- ein:smartrep-notebook-mode-alist)))
-
-(provide 'ein-smartrep)
-
-;;; ein-smartrep.el ends here
diff --git a/lisp/ein-subpackages.el b/lisp/ein-subpackages.el
index c718714..05169f0 100644
--- a/lisp/ein-subpackages.el
+++ b/lisp/ein-subpackages.el
@@ -31,13 +31,9 @@
"EIN defaults to your individual company-mode or auto-complete-mode configuration. Change this setting to gather completions from the jupyter server::
* ein:use-none-backend: local completions only (configured outside EIN)
- * ein:use-company-backend: company-style remote completions (elpy takes precedence)
- * ein:use-ac-backend: deprecated auto-complete remote completions
"
:type '(choice
- (const ein:use-none-backend)
- (const ein:use-company-backend)
- (const ein:use-ac-backend))
+ (const ein:use-none-backend))
:group 'ein)
(provide 'ein-subpackages)
diff --git a/lisp/ein-utils.el b/lisp/ein-utils.el
index c373aa1..8a25a2d 100644
--- a/lisp/ein-utils.el
+++ b/lisp/ein-utils.el
@@ -666,7 +666,6 @@ Use `ein:log' for debugging and logging."
(defun ein:get-docstring (function)
"Return docstring of FUNCTION."
- ;; Borrowed from `ac-symbol-documentation'.
(with-temp-buffer
;; import help-xref-following
(require 'help-mode)
diff --git a/lisp/ein-worksheet.el b/lisp/ein-worksheet.el
index 36bd292..b7c3569 100644
--- a/lisp/ein-worksheet.el
+++ b/lisp/ein-worksheet.el
@@ -795,7 +795,7 @@ directly."
Prompt will appear in the minibuffer.
When used in as a Lisp function, TYPE (string) should be chose
-from \"code\", \"hy-code\", \"markdown\", \"raw\" and \"heading\". LEVEL is
+from \"code\", \"markdown\", \"raw\" and \"heading\". LEVEL is
an integer used only when the TYPE is \"heading\"."
(interactive
(let* ((ws (ein:worksheet--get-ws-or-error))
@@ -808,7 +808,6 @@ an integer used only when the TYPE is \"heading\"."
(format "Cell type [%s]: " choices) choices))
(type (case key
(?c "code")
- (?h "hy-code")
(?m "markdown")
(?r "raw")
(t "heading")))
@@ -1173,13 +1172,6 @@ in the history."
(defun ein:get-kernel--worksheet ()
(when (ein:worksheet-p ein:%worksheet%) (slot-value ein:%worksheet% 'kernel)))
-;; in edit-cell-mode, worksheet is bound as src--ws
-;; used by ein:get-kernel as a last option so completion, tooltips
-;; work in edit-cell-mode
-(defun ein:get-kernel--worksheet-in-edit-cell ()
- "Get kernel when in edit-cell-mode."
- (when (ein:worksheet-p ein:src--ws) (slot-value ein:src--ws 'kernel)))
-
(defun ein:get-cell-at-point--worksheet ()
(ein:worksheet-get-current-cell :noerror t))
diff --git a/lisp/ein_inspector.py b/lisp/ein_inspector.py
deleted file mode 100644
index e4eb4c3..0000000
--- a/lisp/ein_inspector.py
+++ /dev/null
@@ -1,46 +0,0 @@
-"""
-Python utilities for the ein inspector.
-
-Copyright (C) 2017- John M. Miller
-
-Author: John Miller
-
-ein_inspector.py is free software: you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 3 of the License, or
-(at your option) any later version.
-
-ein_inspector.py is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with ein_inspector.py. If not, see .
-
-"""
-
-import json
-import inspect
-
-
-def generate_inspector_data(obj_str, globals, locals):
- odata = {'name': obj_str}
- try:
- obj = eval(obj_str, globals, locals)
- except NameError:
- odata['error'] = 'Object {} not found.'.format(obj_str)
- else:
- odata['doc'] = inspect.getdoc(obj)
- odata['type'] = str(type(obj))
- odata['repr'] = str(obj)
- try:
- odata['source_file'] = inspect.getsourcefile(obj)
- odata['source_lines'] = inspect.getsourcelines(obj)
- except:
- odata['source_file'] = None
- odata['source_lines'] = None
- print(json.dumps(odata))
- return odata
-
-
diff --git a/lisp/ein_remote_safe.py b/lisp/ein_remote_safe.py
deleted file mode 100644
index ba148f1..0000000
--- a/lisp/ein_remote_safe.py
+++ /dev/null
@@ -1,120 +0,0 @@
-"""
-Python utilities to use it from ein.el
-
-Copyright (C) 2012- Takafumi Arakaki
-
-Author: Takafumi Arakaki
-
-ein.py is free software: you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 3 of the License, or
-(at your option) any later version.
-
-ein.py is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with ein.py. If not, see .
-
-"""
-
-
-def __ein_export_nb(nb_json, format):
- import IPython.nbconvert as nbconvert
- import IPython.nbformat as nbformat
- nb = nbformat.reads(nb_json, nbformat.NO_CONVERT)
- output = nbconvert.export_by_name(format, nb)
- print(output[0])
-
-
-def __ein_find_edit_target_012(*args, **kwds):
- from IPython.core.interactiveshell import InteractiveShell
- inst = InteractiveShell.instance()
- return inst._find_edit_target(*args, **kwds)
-
-
-def __ein_find_edit_target_013(*args, **kwds):
- from IPython.core.interactiveshell import InteractiveShell
- inst = InteractiveShell.instance()
- return CodeMagics._find_edit_target(inst, *args, **kwds)
-
-
-def __ein_find_edit_target_python(name):
- from inspect import getsourcefile, getsourcelines
- try:
- obj = eval(name)
- except NameError:
- return False
- else:
- sfile = getsourcefile(obj)
- sline = getsourcelines(obj)[-1]
- if sfile and sline:
- return(sfile, sline, False)
- else:
- return False
-
-try:
- from IPython.core.magics import CodeMagics
- __ein_find_edit_target = __ein_find_edit_target_013
-except ImportError:
- __ein_find_edit_target = __ein_find_edit_target_012
-
-def __ein_set_figure_size(*dim):
- try:
- from matplotlib.pyplot import rcParams
- rcParams['figure.figsize'] = dim
- except:
- raise RuntimeError("Matplotlib not installed in this instance of python!")
-
-def __ein_find_source(name):
- """Given an object as string, `name`, print its place in source code."""
- # FIXME: use JSON display object instead of stdout
- ret = __ein_find_edit_target_python(name) or __ein_find_edit_target(name, {}, [])
- if ret:
- (filename, lineno, use_temp) = ret
- if not use_temp:
- print(filename)
- print(lineno)
- return
- raise RuntimeError("Source code for {0} cannot be found".format(name))
-
-
-def __ein_run_docstring_examples(obj, verbose=True):
- from IPython.core.interactiveshell import InteractiveShell
- import doctest
- inst = InteractiveShell.instance()
- globs = inst.user_ns
- return doctest.run_docstring_examples(obj, globs, verbose=verbose)
-
-
-def __ein_maybe_undefined_object(obj, locals=None):
- try:
- return eval(obj, None, locals)
- except Exception:
- return None
- except SyntaxError:
- return None
-
-def __ein_print_object_info_for(obj):
- import IPython.core.oinspect
- import json
-
- inspector = IPython.core.oinspect.Inspector()
-
- try:
- print(json.dumps(inspector.info(obj)))
- except Exception:
- print(json.dumps(inspector.info(None)))
-
-def __ein_eval_hy_string(obj):
- try:
- import hy
- except ImportError:
- print("Hy not supported in this kernel. Execute `pip install hy` if you want this support.")
-
- expr = hy.read_str(obj)
- ret = hy.eval(expr)
-
- return ret
diff --git a/lisp/ob-ein.el b/lisp/ob-ein.el
index 4e29033..d294acb 100644
--- a/lisp/ob-ein.el
+++ b/lisp/ob-ein.el
@@ -70,8 +70,7 @@
("ein-python" . python)
("ein-R" . R)
("ein-r" . R)
- ("ein-julia" . julia)
- ("ein-hy" . hy))
+ ("ein-julia" . julia))
"ob-ein has knowledge of these (ein-LANG . LANG-MODE) pairs."
:type '(repeat (cons string symbol))
:group 'ein)
@@ -162,8 +161,7 @@ Based on ob-ipython--configure-kernel."
(fset (intern (concat "org-babel-execute:" lang-name))
`(lambda (body params)
(require (quote ,(intern (format "ob-%s" lang-mode))) nil t)
- (if (boundp 'python-indent-guess-indent-offset-verbose)
- (setq python-indent-guess-indent-offset-verbose nil))
+ (custom-set-variables '(python-indent-guess-indent-offset-verbose nil))
(let* ((parser
(quote
,(intern
@@ -366,53 +364,6 @@ if necessary. Install CALLBACK (i.e., cell execution) upon notebook retrieval."
(t (url-port parsed-url)))))))
(t (ein:notebooklist-login url-or-port callback-login)))))
-(defun ob-ein--edit-ctrl-c-ctrl-c ()
- "C-c C-c mapping in ein:connect-mode-map."
- (interactive)
- (if (not (org-src-edit-buffer-p))
- (ein:connect-run-buffer)
- (org-edit-src-save)
- (when (boundp 'org-src--beg-marker)
- (let* ((beg org-src--beg-marker)
- (buf (marker-buffer beg)))
- (with-current-buffer buf
- (save-excursion
- (goto-char beg)
- (org-ctrl-c-ctrl-c)))))))
-
-(defcustom ob-ein-babel-edit-polymode-ignore nil
- "When false override default python mode key mapping for `\C-c\C-c' while inside a babel edit buffer.
-Instead the binding will be to `ob-ein--edit-ctrl-c-ctrl-c', which will execute the code block being edited."
- :group 'ein
- :type '(boolean))
-
-(defun org-babel-edit-prep:ein (babel-info)
- (if (and ein:polymode (not ob-ein-babel-edit-polymode-ignore))
- (progn
- (use-local-map (copy-keymap python-mode-map))
- (local-set-key "\C-c\C-c" 'ob-ein--edit-ctrl-c-ctrl-c))
- (let* ((buffer (current-buffer))
- (processed-parameters (nth 2 babel-info))
- (session (or (ein:aand (cdr (assoc :session processed-parameters))
- (unless (string= "none" it)
- (format "%s" it)))
- ein:url-localhost))
- (lang "ein-python")
- (kernelspec (or (cdr (assoc :kernelspec processed-parameters))
- (ein:aif (cdr (assoc lang org-src-lang-modes))
- (cons 'language (format "%s" it))
- (error "ob-ein--execute-body: %s not among %s"
- lang (mapcar #'car org-src-lang-modes))))))
- (ob-ein--initiate-session
- session
- kernelspec
- (lambda (notebook)
- (ein:connect-buffer-to-notebook notebook buffer t)
- (define-key ein:connect-mode-map "\C-c\C-c" 'ob-ein--edit-ctrl-c-ctrl-c))))))
-
-(defun org-babel-edit-prep:ein-python (babel-info)
- (org-babel-edit-prep:ein babel-info))
-
(loop for (lang . mode) in ob-ein-languages
do (ob-ein--babelize-lang lang mode))
diff --git a/lisp/poly-ein.el b/lisp/poly-ein.el
index 9674722..ee5a7e9 100644
--- a/lisp/poly-ein.el
+++ b/lisp/poly-ein.el
@@ -4,7 +4,7 @@
(declare-function polymode-inhibit-during-initialization "polymode-core")
-(defcustom ein:polymode nil
+(defcustom ein:polymode t
"When enabled ein will use polymode to provide multi-major mode
support in a notebook buffer, otherwise ein's custom and outdated
multi-major mode support will be used. Emacs must be restarted
@@ -181,15 +181,14 @@ TYPE can be 'body, nil."
(error (message "%s: defaulting language to python"
(error-message-string err))
"python")))
- (mode
- (pm-get-mode-symbol-from-name
- (cond ((ein:codecell-p cell) lang)
- ((ein:markdowncell-p cell) "markdown")
- (t "fundamental"))))
+ (what (cond ((ein:codecell-p cell) lang)
+ ((ein:markdowncell-p cell) "markdown")
+ (t "fundamental")))
+ (mode (pm-get-mode-symbol-from-name what))
((not (equal mode (ein:oref-safe cm :mode)))))
(when (eq mode 'poly-fallback-mode)
(ein:display-warning
- (format "pm:get-span: no major mode for kernelspec language '%s'" lang)))
+ (format "pm:get-span: no major mode for kernelspec language '%s'" what)))
(setq result-cm
(loop for ocm in (eieio-oref pm/polymode '-auto-innermodes)
when (equal mode (ein:oref-safe ocm :mode))
diff --git a/ltxpng/Enhancements_99e9bae2984f33a8dd1b990b80b91ab1a662cf49.png b/ltxpng/Enhancements_99e9bae2984f33a8dd1b990b80b91ab1a662cf49.png
deleted file mode 100644
index 576a488..0000000
Binary files a/ltxpng/Enhancements_99e9bae2984f33a8dd1b990b80b91ab1a662cf49.png and /dev/null differ
diff --git a/ltxpng/Enhancements_a52848837248c7931a943cbbd4b70188a0935854.png b/ltxpng/Enhancements_a52848837248c7931a943cbbd4b70188a0935854.png
deleted file mode 100644
index 0bb33ed..0000000
Binary files a/ltxpng/Enhancements_a52848837248c7931a943cbbd4b70188a0935854.png and /dev/null differ
diff --git a/org_demo.org b/org_demo.org
deleted file mode 100644
index d48b05e..0000000
--- a/org_demo.org
+++ /dev/null
@@ -1,132 +0,0 @@
-* Tests
-
-This is a [[ipynb:(:url-or-port%20"http://localhost:8888"%20:name%20"emacs-ipython-notebook/The%20Emacs%20IPython%20Notebook.ipynb")][link]] to an ein notebook. It might not work if your setup is not the same as mine!
-
-
-Note that code is executed asynchronously, so executing the following won't
-block Emacs. You can even queue up a number of source code blocks and they will
-execute sequentially as the previous finishes execution!
-
-#+NAME: 6d0ec9b7-249c-46e9-bdf1-c48b7bcf7fbd
-#+BEGIN_SRC ein :session http://localhost:8888/The Emacs IPython Notebook.ipynb
- import sys
- import time
-
- time.sleep(10)
- print("Hello dood!")
-#+END_SRC
-
-#+RESULTS: 6d0ec9b7-249c-46e9-bdf1-c48b7bcf7fbd
-: Hello dood!
-
-
-
-
-
-
-
-#+NAME: 744c7889-aec1-495f-9d07-6efc17329e94
-#+BEGIN_SRC ein :session http://localhost:8888/The Emacs IPython Notebook.ipynb
- 1+4
-#+END_SRC
-
-#+RESULTS: 744c7889-aec1-495f-9d07-6efc17329e94
-: 5
-
-Tracebacks will be printed out, but if you want to use ein's traceback and
-debugging support you have to jump to the ~*ein:shared-output*~ buffer for
-traceback support or the notebook running the session and execute ~%debug~ in a
-cell there.
-
-#+NAME: 47c36fa5-1b53-413b-8f5b-814f1ae66a3b
-#+BEGIN_SRC ein :session http://localhost:8888/The Emacs IPython Notebook.ipynb :results output drawer
- 1/0
-#+END_SRC
-
-#+RESULTS: 47c36fa5-1b53-413b-8f5b-814f1ae66a3b
-:results:
-
-ZeroDivisionErrorTraceback (most recent call last)
- in
-----> 1 1/0
-
-ZeroDivisionError: division by zero
-:end:
-
-#+NAME: 00052904-6ca5-46e0-9797-c6039d0daf5e
-#+BEGIN_SRC ein :session http://localhost:8888/The Emacs IPython Notebook.ipynb :results output drawer
- import matplotlib.pyplot as plt
- import numpy as np
-
- %matplotlib inline
- x = np.linspace(0, 1, 100)
- y = np.random.rand(100,1)
- plt.plot(x,y)
- x
-
-#+END_SRC
-
-#+RESULTS: 00052904-6ca5-46e0-9797-c6039d0daf5e
-:results:
-array([0. , 0.01010101, 0.02020202, 0.03030303, 0.04040404,
- 0.05050505, 0.06060606, 0.07070707, 0.08080808, 0.09090909,
- 0.1010101 , 0.11111111, 0.12121212, 0.13131313, 0.14141414,
- 0.15151515, 0.16161616, 0.17171717, 0.18181818, 0.19191919,
- 0.2020202 , 0.21212121, 0.22222222, 0.23232323, 0.24242424,
- 0.25252525, 0.26262626, 0.27272727, 0.28282828, 0.29292929,
- 0.3030303 , 0.31313131, 0.32323232, 0.33333333, 0.34343434,
- 0.35353535, 0.36363636, 0.37373737, 0.38383838, 0.39393939,
- 0.4040404 , 0.41414141, 0.42424242, 0.43434343, 0.44444444,
- 0.45454545, 0.46464646, 0.47474747, 0.48484848, 0.49494949,
- 0.50505051, 0.51515152, 0.52525253, 0.53535354, 0.54545455,
- 0.55555556, 0.56565657, 0.57575758, 0.58585859, 0.5959596 ,
- 0.60606061, 0.61616162, 0.62626263, 0.63636364, 0.64646465,
- 0.65656566, 0.66666667, 0.67676768, 0.68686869, 0.6969697 ,
- 0.70707071, 0.71717172, 0.72727273, 0.73737374, 0.74747475,
- 0.75757576, 0.76767677, 0.77777778, 0.78787879, 0.7979798 ,
- 0.80808081, 0.81818182, 0.82828283, 0.83838384, 0.84848485,
- 0.85858586, 0.86868687, 0.87878788, 0.88888889, 0.8989899 ,
- 0.90909091, 0.91919192, 0.92929293, 0.93939394, 0.94949495,
- 0.95959596, 0.96969697, 0.97979798, 0.98989899, 1. ])
-[[file:ein-images/ob-ein-958ea9b193e7657e6b8b77069728be7a.png]]
-:end:
-
-
-#+NAME: 84b146f2-0b8d-46ca-9fb9-96759657927c
-#+BEGIN_SRC ein :session http://localhost:8888/The Emacs IPython Notebook.ipynb :results output
- from sympy import *
-
- init_printing()
- x = symbols('x')
- x
-
-#+END_SRC
-
-#+RESULTS: 84b146f2-0b8d-46ca-9fb9-96759657927c
-#+begin_example
-
-ModuleNotFoundErrorTraceback (most recent call last)
- in
-----> 1 from sympy import *
- 2
- 3 init_printing()
- 4 x = symbols('x')
- 5 x
-
-ModuleNotFoundError: No module named 'sympy'
-#+end_example
-
-
-* SVG Images
-* Issue #468: Results in org mode
-
-#+NAME: ffbf0b19-515a-4966-9220-70063cf2948d
-#+BEGIN_SRC ein :session http://localhost:8888/The Emacs IPython Notebook.ipynb :results value
- import numpy as np
- np.zeros(18)
-#+END_SRC
-
-#+RESULTS: ffbf0b19-515a-4966-9220-70063cf2948d
-: array([0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
-: 0.])
-
diff --git a/test/ein-testing-notebook.el b/test/ein-testing-notebook.el
index 3346659..b158a89 100644
--- a/test/ein-testing-notebook.el
+++ b/test/ein-testing-notebook.el
@@ -49,10 +49,10 @@
(ein:kernel-new 8888 "" nil "/kernels" (ein:$notebook-events notebook) (ein:need-notebook-version (ein:$notebook-url-or-port notebook))))
(setf (ein:$kernel-events (ein:$notebook-kernel notebook))
(ein:events-new))
- ; matryoshka: new-content makes a ein:$content using CONTENT as template
+ ; matryoshka: new-content makes a ein:$content using CONTENT as template
; populating its raw_content field with DATA's content field
(ein:notebook-open--callback
- notebook nil nil
+ notebook nil
(ein:new-content (ein:$notebook-url-or-port notebook)
(ein:$notebook-notebook-path notebook) data))
(ein:notebook-buffer notebook)))))
@@ -85,8 +85,8 @@
"Make new notebook. One empty cell will be inserted
automatically if CELLS is nil."
(ein:testing-notebook-from-json
- (json-encode (ein:testing-notebook-make-data
- (or name ein:testing-notebook-dummy-name)
+ (json-encode (ein:testing-notebook-make-data
+ (or name ein:testing-notebook-dummy-name)
(or path name ein:testing-notebook-dummy-name)
cells))))
@@ -112,7 +112,7 @@ The new cell is bound to a variable `cell'."
LIST-OUTPUTS is a list of list of strings (pyout text). Number
of LIST-OUTPUTS equals to the number cells to be contained in the
notebook."
- (ein:testing-notebook-make-new
+ (ein:testing-notebook-make-new
ein:testing-notebook-dummy-name nil
(mapcar (lambda (outputs)
(ein:testing-codecell-data
diff --git a/test/test-ein-ac.el b/test/test-ein-ac.el
deleted file mode 100644
index c69236b..0000000
--- a/test/test-ein-ac.el
+++ /dev/null
@@ -1,17 +0,0 @@
-(eval-when-compile (require 'cl))
-(require 'ert)
-
-(require 'ein-ac)
-(require 'ein-testing-kernel)
-
-
-(ert-deftest ein:ac-set-document ()
- (let ((string "candidate string"))
- (should-not (get-text-property 0 'document string))
- (ein:testing-kernel-construct-help-string-loop
- (lambda (content result)
- (ein:ac-set-document string content '-not-used-)
- (let ((props (text-properties-at 0 string)))
- ;; document property may be nil, but must be set.
- (should (member 'document props))
- (should (equal (plist-get props 'document) result)))))))
diff --git a/test/test-ein-kernel.el b/test/test-ein-kernel.el
index 59338b2..f21e173 100644
--- a/test/test-ein-kernel.el
+++ b/test/test-ein-kernel.el
@@ -17,7 +17,7 @@
(dummy-response (make-request-response))
got-url)
(setf (ein:$notebook-kernel notebook) kernel)
- (cl-letf (((symbol-function 'request)
+ (cl-letf (((symbol-function 'request)
(lambda (url &rest ignore) (setq got-url url) dummy-response))
((symbol-function 'set-process-query-on-exit-flag) #'ignore)
((symbol-function 'ein:kernel-stop-channels) #'ignore)
@@ -30,31 +30,35 @@
(should (equal got-url desired-url)))))
(ert-deftest ein:kernel-interrupt-check-url ()
- (let* ((kernel (eintest:kernel-new 8888))
- (kernel-id "KERNEL-ID")
- (desired-url "http://127.0.0.1:8888/api/kernels/KERNEL-ID/interrupt")
- (dummy-response (make-request-response))
- got-url)
- (flet ((request (url &rest ignore) (setq got-url url) dummy-response)
- (set-process-query-on-exit-flag (process flag))
- (ein:kernel-stop-channels (&rest ignore))
- (ein:websocket (url kernel on-message on-close on-open) (make-ein:$websocket :ws nil :kernel kernel :closed-by-client nil))
- (ein:websocket-open-p (websocket) t))
+ (lexical-let* ((kernel (eintest:kernel-new 8888))
+ (kernel-id "KERNEL-ID")
+ (desired-url "http://127.0.0.1:8888/api/kernels/KERNEL-ID/interrupt")
+ (dummy-response (make-request-response))
+ got-url)
+
+ (cl-letf (((symbol-function 'request)
+ (lambda (url &rest ignore) (setq got-url url) dummy-response))
+ ((symbol-function 'set-process-query-on-exit-flag) #'ignore)
+ ((symbol-function 'ein:kernel-stop-channels) #'ignore)
+ ((symbol-function 'ein:websocket) (lambda (&rest ignore) (make-ein:$websocket :ws nil :kernel kernel :closed-by-client nil)))
+ ((symbol-function 'ein:websocket-open-p) (lambda (&rest ignore) t)))
(ein:kernel-retrieve-session--success
kernel nil :data (list :ws_url "ws://127.0.0.1:8888" :id kernel-id))
(ein:kernel-interrupt kernel)
(should (equal got-url desired-url)))))
(ert-deftest ein:kernel-kill-check-url ()
- (let* ((kernel (eintest:kernel-new 8888))
- (kernel-id "KERNEL-ID")
- (desired-url "http://127.0.0.1:8888/api/sessions/KERNEL-ID")
- (dummy-response (make-request-response))
- got-url)
- (flet ((request (url &rest ignore) (setq got-url url) dummy-response)
- (set-process-query-on-exit-flag (process flag))
- (ein:kernel-stop-channels (&rest ignore))
- (ein:websocket (url kernel on-message on-close on-open) (make-ein:$websocket :ws nil :kernel kernel :closed-by-client nil)))
+ (lexical-let* ((kernel (eintest:kernel-new 8888))
+ (kernel-id "KERNEL-ID")
+ (desired-url "http://127.0.0.1:8888/api/sessions/KERNEL-ID")
+ (dummy-response (make-request-response))
+ got-url)
+ (cl-letf (((symbol-function 'request)
+ (lambda (url &rest ignore) (setq got-url url) dummy-response))
+ ((symbol-function 'set-process-query-on-exit-flag) #'ignore)
+ ((symbol-function 'ein:kernel-stop-channels) #'ignore)
+ ((symbol-function 'ein:websocket) (lambda (&rest ignore) (make-ein:$websocket :ws nil :kernel kernel :closed-by-client nil)))
+ ((symbol-function 'ein:websocket-open-p) (lambda (&rest ignore) t)))
(ein:kernel-retrieve-session--success
kernel nil :data (list :ws_url "ws://127.0.0.1:8888" :id kernel-id))
(ein:kernel-delete-session kernel))
diff --git a/test/test-ein-notification.el b/test/test-ein-notification.el
index 01f6584..0312ab0 100644
--- a/test/test-ein-notification.el
+++ b/test/test-ein-notification.el
@@ -57,8 +57,6 @@
'(notebook_saved.Notebook
notebook_saving.Notebook
notebook_save_failed.Notebook
- notebook_create_checkpoint.Notebook
- notebook_checkpoint_created.Notebook
execution_count.Kernel
status_idle.Kernel
status_busy.Kernel
diff --git a/test/test-ein-smartrep.el b/test/test-ein-smartrep.el
deleted file mode 100644
index 2c1b2e7..0000000
--- a/test/test-ein-smartrep.el
+++ /dev/null
@@ -1,8 +0,0 @@
-(eval-when-compile (require 'cl))
-(require 'ert)
-
-(require 'ein-smartrep)
-
-(ert-deftest ein:smartrep-notebook-mode-alist-fboundp ()
- (loop for (k . f) in ein:smartrep-notebook-mode-alist
- do (should (fboundp f))))
diff --git a/test/test-func.el b/test/test-func.el
deleted file mode 100644
index 5c19e6b..0000000
--- a/test/test-func.el
+++ /dev/null
@@ -1,239 +0,0 @@
-(eval-when-compile (require 'cl))
-(require 'ert)
-
-(require 'ein-notebooklist)
-(require 'ein-jupyter)
-(require 'wid-edit)
-(require 'ein-testing)
-(require 'ein-testing-cell)
-
-(let ((backend (getenv "EL_REQUEST_BACKEND")))
- (when (and backend (not (equal backend "")))
- (setq request-backend (intern backend))
- (message "Using request-backend = %S" request-backend)))
-
-(defvar *ein:testing-notebook-name* nil
- "This is the name of the notebook the server creates for this test. It could be Untitled.ipynb or if that was already there, Untitled1.ipynb, etc.")
-
-(setq message-log-max t)
-
-(defun ein:testing-get-notebook (url-or-port &rest paths)
- (ein:log 'debug "TESTING-GET-NOTEBOOK start")
- (ein:notebooklist-open* url-or-port)
- (ein:testing-wait-until (lambda () (and (bufferp (get-buffer (format ein:notebooklist-buffer-name-template url-or-port)))
- (ein:notebooklist-get-buffer url-or-port))))
- (with-current-buffer (ein:notebooklist-get-buffer url-or-port)
- (prog1 (ein:notebook-get-opened-notebook url-or-port (apply #'ein:glom-paths paths))
- (ein:log 'debug "TESTING-GET-NOTEBOOK end"))))
-
-(defun ein:testing-get-untitled0-or-create (url-or-port &optional path)
- (ein:log 'debug "TESTING-GET-UNTITLED0-OR-CREATE start")
- (let ((notebook (ein:testing-get-notebook url-or-port path *ein:testing-notebook-name*)))
- (if notebook
- (progn (ein:log 'debug
- "TESTING-GET-UNTITLED0-OR-CREATE notebook already exists")
- notebook)
- (ein:log 'debug
- "TESTING-GET-UNTITLED0-OR-CREATE creating notebook")
- (lexical-let (done-p
- (kernelspec (ein:get-kernelspec url-or-port "default")))
- (ein:notebooklist-new-notebook url-or-port kernelspec
- (lambda (notebook created)
- (setq *ein:testing-notebook-name*
- (ein:$notebook-notebook-name notebook))
- (setq done-p t)))
- (ein:testing-wait-until (lambda () done-p) nil 10000 2000)
- (prog1
- (ein:testing-get-notebook url-or-port path *ein:testing-notebook-name*)
- (with-current-buffer (ein:notebooklist-get-buffer url-or-port)
- (lexical-let (done-p)
- (ein:notebooklist-reload nil t (lambda (&rest args) (setq done-p t)))
- (ein:testing-wait-until (lambda () done-p) nil 10000 1000)))
- (ein:log 'debug "TESTING-GET-UNTITLED0-OR-CREATE end"))))))
-
-(defvar ein:notebooklist-after-open-hook nil)
-
-(defadvice ein:notebooklist-open--finish
- (after ein:testing-notebooklist-open--finish activate)
- "Advice to add `ein:notebooklist-after-open-hook'."
- (run-hooks 'ein:notebooklist-after-open-hook))
-
-;; (ert-deftest 00-jupyter-start-server ()
-;; (ein:log 'verbose "ERT TESTING-JUPYTER-START-SERVER start")
-;; (condition-case err
-;; (ein:testing-start-server)
-;; (error (ein:log 'verbose "ERT TESTING-JUPYTER-START-SERVER error when launching: %s" err)
-;; (sit-for 10)
-;; (ein:jupyter-server-login-and-open)))
-;; (should (processp %ein:jupyter-server-session%))
-;; (ein:log 'verbose "ERT TESTING-JUPYTER-START-SERVER end"))
-
-(ert-deftest 01-open-notebooklist ()
- (ein:log 'verbose "ERT OPEN-NOTEBOOKLIST start")
- (ein:notebooklist-open* *ein:testing-port*)
- (ein:testing-wait-until
- (lambda () (ein:aand
- (ein:notebooklist-get-buffer *ein:testing-port*)
- (with-current-buffer it (eq major-mode 'ein:notebooklist-mode))))))
-
-
-(ert-deftest 00-query-kernelspecs ()
- (ein:log 'info "ERT QUERY-KERNELSPECS")
- (ein:log 'info (format "ERT QUERY-KERNELSPECS: Pre-query kernelspec count %s." (hash-table-count *ein:kernelspecs*)))
- (should (>= (hash-table-count *ein:kernelspecs*) 1))
- (ein:log 'info (format "ERT QUERY-KERNELSPECS: Post-query kernelspec %S." (ein:need-kernelspecs *ein:testing-port*))))
-
-(ert-deftest 10-get-untitled0-or-create ()
- (ein:log 'verbose "ERT TESTING-GET-UNTITLED0-OR-CREATE start")
- (let ((notebook (ein:testing-get-untitled0-or-create *ein:testing-port*)))
- (ein:testing-wait-until
- (lambda () (ein:aand (ein:$notebook-kernel notebook)
- (ein:kernel-live-p it))))
- (with-current-buffer (ein:notebook-buffer notebook)
- (should (equal (ein:$notebook-notebook-name ein:%notebook%)
- *ein:testing-notebook-name*))))
- (ein:log 'verbose "ERT TESTING-GET-UNTITLED0-OR-CREATE end"))
-
-(ert-deftest 20-delete-untitled0 ()
- (ein:log 'verbose "----------------------------------")
- (ein:log 'verbose "ERT TESTING-DELETE-UNTITLED0 start")
- (with-current-buffer (ein:notebooklist-get-buffer *ein:testing-port*)
- (let* ((notebook (ein:testing-get-untitled0-or-create *ein:testing-port*))
- (the-url (ein:url *ein:testing-port* (ein:$notebook-notebook-path notebook))))
- (should (member the-url (ein:notebooklist-list-paths "notebook")))
- (ein:log 'verbose "ERT TESTING-DELETE-UNTITLED0 deleting notebook")
- (lexical-let (done-p)
- (ein:notebooklist-delete-notebook
- (ein:$notebook-notebook-path notebook)
- (lambda (&rest args) (setq done-p t)))
- (ein:testing-wait-until (lambda () done-p) nil 10000 1000))
- (lexical-let (done-p)
- (ein:content-query-hierarchy
- (ein:url *ein:testing-port*)
- (lambda (&rest args) (setq done-p t)))
- (ein:testing-wait-until (lambda () done-p) nil 10000 1000))
- (should-not (member the-url (ein:notebooklist-list-paths "notebook")))))
- (ein:log 'verbose "ERT TESTING-DELETE-UNTITLED0 end"))
-
-(ert-deftest 11-notebook-execute-current-cell-simple ()
- (let ((notebook (ein:testing-get-untitled0-or-create *ein:testing-port*)))
- (ein:testing-wait-until
- (lambda () (ein:aand (ein:$notebook-kernel notebook)
- (ein:kernel-live-p it))))
- (with-current-buffer (ein:notebook-buffer notebook)
- (call-interactively #'ein:worksheet-insert-cell-below)
- (insert "a = 100\na")
- (let ((cell (call-interactively #'ein:worksheet-execute-cell)))
- (ein:testing-wait-until (lambda () (not (slot-value cell 'running)))))
- ;; (message "%s" (buffer-string))
- (save-excursion
- (should (search-forward-regexp "Out \\[[0-9]+\\]" nil t))
- (should (search-forward "100" nil t))))))
-
-(defun ein:testing-image-type (image)
- "Return the type of IMAGE.
-See the definition of `create-image' for how it works."
- (assert (and (listp image) (eq (car image) 'image)) nil
- "%S is not an image." image)
- (plist-get (cdr image) :type))
-
-(ert-deftest 12-notebook-execute-current-cell-pyout-image ()
- (let ((notebook (ein:testing-get-untitled0-or-create *ein:testing-port*)))
- (ein:testing-wait-until
- (lambda () (ein:aand (ein:$notebook-kernel notebook)
- (ein:kernel-live-p it))))
- (if (image-type-available-p 'svg)
- (with-current-buffer (ein:notebook-buffer notebook)
- (call-interactively #'ein:worksheet-insert-cell-below)
- ;; Use IPython.core.display rather than IPython.display to
- ;; test it with older (< 0.13) IPython.
- (insert (concat "from IPython.core.display import SVG\n"
- (format "SVG(data=\"\"\"%s\"\"\")"
- ein:testing-example-svg)))
- (let ((cell (call-interactively #'ein:worksheet-execute-cell)))
- ;; It seems in this case, watching `:running' does not work
- ;; well sometimes. Probably "output reply" (iopub) comes
- ;; before "execute reply" in this case.
- (ein:testing-wait-until (lambda () (slot-value cell 'outputs)))
- ;; This cell has only one input
- (should (= (length (oref cell :outputs)) 1))
- ;; This output is a SVG image
- (let ((out (nth 0 (oref cell :outputs))))
- (should (equal (plist-get out :output_type) "execute_result"))
- (should (plist-get out :svg))))
- ;; Check the actual output in the buffer:
- (save-excursion
- (should (search-forward-regexp "Out \\[[0-9]+\\]" nil t))
- (should (= (forward-line) 0))
- (let ((image (get-text-property (point) 'display)))
- (should (eq (ein:testing-image-type image) 'svg)))))
- (ein:log 'info
- "Skipping image check as SVG image type is not available."))))
-
-(ert-deftest 13-notebook-execute-current-cell-stream ()
- (let ((notebook (ein:testing-get-untitled0-or-create *ein:testing-port*)))
- (ein:testing-wait-until
- (lambda () (ein:aand (ein:$notebook-kernel notebook)
- (ein:kernel-live-p it))))
- (with-current-buffer (ein:notebook-buffer notebook)
- (call-interactively #'ein:worksheet-insert-cell-below)
- (insert "print('Hello')")
- (let ((cell (call-interactively #'ein:worksheet-execute-cell)))
- (ein:testing-wait-until (lambda () (not (oref cell :running)))
- ))
- (save-excursion
- (should-not (search-forward-regexp "Out \\[[0-9]+\\]" nil t))
- (should (search-forward-regexp "^Hello$" nil t))))))
-
-(ert-deftest 14-notebook-execute-current-cell-question ()
- (lexical-let ((notebook (ein:testing-get-untitled0-or-create *ein:testing-port*)))
- (ein:testing-wait-until
- (lambda () (ein:aand (ein:$notebook-kernel notebook)
- (ein:kernel-live-p it))))
- (with-current-buffer (ein:notebook-buffer notebook)
- (call-interactively #'ein:worksheet-insert-cell-below)
- (insert "range?")
- (lexical-let ((cell (call-interactively #'ein:worksheet-execute-cell)))
- (ein:testing-wait-until
- (lambda ()
- (and (not (oref cell :running))
- (ein:$notebook-pager notebook)
- (get-buffer (ein:$notebook-pager notebook))))))
- (with-current-buffer (get-buffer (ein:$notebook-pager notebook))
- (should (search-forward "Docstring:"))))))
-
-(ert-deftest 15-notebook-request-help ()
- (let ((notebook (ein:testing-get-untitled0-or-create *ein:testing-port*)))
- (ein:testing-wait-until
- (lambda () (ein:aand (ein:$notebook-kernel notebook)
- (ein:kernel-live-p it))))
- (with-current-buffer (ein:notebook-buffer notebook)
- (call-interactively #'ein:worksheet-insert-cell-below)
- (let ((pager-name (ein:$notebook-pager ein:%notebook%)))
- (ein:aif (get-buffer pager-name)
- (kill-buffer it))
- (insert "file")
- (call-interactively #'ein:pytools-request-help)
- ;; Pager buffer will be created when got the response
- (ein:testing-wait-until
- (lambda () (get-buffer pager-name)))
- (with-current-buffer (get-buffer pager-name)
- (should (search-forward "Docstring:")))))))
-
-(ert-deftest 30-testing-jupyter-stop-server ()
- (ein:log 'verbose "ERT TESTING-JUPYTER-STOP-SERVER start")
-
- (let ((notebook (ein:testing-get-untitled0-or-create *ein:testing-port*)))
- (ein:testing-wait-until
- (lambda () (ein:aand (ein:$notebook-kernel notebook)
- (ein:kernel-live-p it))))
- (ein:jupyter-server-stop t ein:testing-dump-file-server)
- (cl-flet ((orphans-find (pid) (search (ein:$kernel-kernel-id (ein:$notebook-kernel notebook)) (alist-get 'args (process-attributes pid)))))
- (should-not (loop repeat 10
- with orphans = (seq-filter #'orphans-find
- (list-system-processes))
- until (and (null orphans) (ein:jupyter-server-process))
- do (sleep-for 0 1000)
- (setq orphans (seq-filter #'orphans-find (list-system-processes)))
- finally return orphans))))
- (ein:log 'verbose "ERT TESTING-JUPYTER-STOP-SERVER end"))
diff --git a/test/test-poly.el b/test/test-poly.el
index c9e6a70..8595f45 100644
--- a/test/test-poly.el
+++ b/test/test-poly.el
@@ -1,2 +1,2 @@
(custom-set-variables
- '(ein:polymode t))
+ '(ein:polymode nil))
diff --git a/test/test-ein-poly.el b/test/test-uncompiled.el
similarity index 62%
rename from test/test-ein-poly.el
rename to test/test-uncompiled.el
index 393f4b7..57d208e 100644
--- a/test/test-ein-poly.el
+++ b/test/test-uncompiled.el
@@ -1,5 +1,10 @@
+(custom-set-variables '(company-frontends nil)
+ '(python-indent-guess-indent-offset-verbose nil)
+ '(ein:polymode nil))
+
+(require 'ein-dev)
+(require 'ein-testing)
(require 'ert)
-(require 'poly-ein)
(require 'byte-compile)
(ert-deftest ein:should-not-compile-advised ()
diff --git a/test/testein.el b/test/testein.el
index 30f92af..ccb1c00 100644
--- a/test/testein.el
+++ b/test/testein.el
@@ -1,3 +1,7 @@
+(custom-set-variables '(company-frontends nil)
+ '(python-indent-guess-indent-offset-verbose nil))
+
+(require 'python)
(require 'ein-dev)
(require 'ein-testing)
diff --git a/test/testfunc.el b/test/testfunc.el
deleted file mode 100644
index c537b08..0000000
--- a/test/testfunc.el
+++ /dev/null
@@ -1,29 +0,0 @@
-(prefer-coding-system 'utf-8)
-
-(require 'ein-dev)
-(require 'ein-testing)
-(require 'ein-jupyter)
-(require 'ein-notebooklist)
-(require 'deferred)
-
-(ein:log 'info "Starting jupyter notebook server.")
-
-(defvar *ein:testing-jupyter-server-command* (or (getenv "JUPYTER_TESTING_COMMAND")
- (executable-find "jupyter"))
- "Path to command that starts the jupyter notebook server.")
-
-(defvar *ein:testing-jupyter-server-directory* (or (getenv "JUPYTER_TESTING_DIR") (concat default-directory "test"))
- "Location where to start the jupyter notebook server.")
-
-(setq ein:testing-dump-file-log (concat default-directory "log/testfunc.log"))
-(setq ein:testing-dump-file-messages (concat default-directory "log/testfunc.messages"))
-(setq ein:testing-dump-file-server (concat default-directory "log/testfunc.server"))
-(setq ein:testing-dump-file-websocket (concat default-directory "log/testfunc.websocket"))
-(setq ein:testing-dump-file-request (concat default-directory "log/testfunc.request"))
-(with-eval-after-load "python"
- (setq python-indent-guess-indent-offset-verbose nil))
-(ein:dev-start-debug)
-(ein:jupyter-server-start *ein:testing-jupyter-server-command* *ein:testing-jupyter-server-directory*)
-(ein:testing-wait-until (lambda () (ein:notebooklist-list)) nil 15000 1000)
-(defvar *ein:testing-port* (car (ein:jupyter-server-conn-info)))
-(fset 'y-or-n-p (lambda (prompt) nil))
diff --git a/test_requirements.txt b/test_requirements.txt
deleted file mode 100644
index 919e0a8..0000000
--- a/test_requirements.txt
+++ /dev/null
@@ -1,6 +0,0 @@
-jedi <= 0.13.3
-jupyter
-ipython
-numpy
-matplotlib
-invoke