├── .github └── ISSUE_TEMPLATE │ └── bug_report.md ├── .gitignore ├── LICENSE ├── README.md ├── assets ├── debug-python.gif ├── repl.gif ├── usage-1.gif ├── usage-3.gif ├── usage2.gif ├── usage4.gif └── wechat.JPG ├── autoload ├── async.vim ├── formatpythoncode.vim ├── formatvimscript.vim └── repl.vim ├── ftplugin ├── perl │ └── psh └── python │ └── python-repl.vim ├── plugin ├── default.vim └── vim-repl.vim ├── pythonx ├── filemanager.py ├── formatpythoncode.py ├── replpython.py └── testpythonx.py └── test ├── UUUU.log ├── comment.py ├── function1.py ├── gcd.py ├── ipython_log.py ├── long_sentence.py ├── perl └── test.pl ├── python.db ├── pythonpdb.py ├── test.py ├── test_Chinese.py ├── test_asyncdef.py ├── test_automerge.py ├── test_autopaste.py ├── test_autosend.py ├── test_autosend_unfinished_line.py ├── test_class.py ├── test_decoration.py ├── test_dill.py ├── test_error.py ├── test_for.py ├── test_gcn.py ├── test_git107.py ├── test_github127.py ├── test_magic_command.py ├── test_multi_lines.py ├── test_multisends.py ├── test_rhs.py ├── test_session.py ├── test_space.py ├── test_tab.py ├── test_try.py ├── test_virtualenv.py ├── test_with.py ├── testforsleep.py ├── testgcd.py ├── testif.py ├── testlongsentence.py └── testnumpy.py /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Describe the bug** 11 | A clear and concise description of what the bug is. 12 | 13 | **Screenshots** 14 | If applicable, add screenshots to help explain your problem. 15 | 16 | **Desktop (please complete the following information):** 17 | 18 | - result of `:REPLDebugInfo` 19 | 20 | **Additional context** 21 | Add any other context about the problem here. 22 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Git 2 | *.orig 3 | *.BACKUP.* 4 | *.BASE.* 5 | *.LOCAL.* 6 | *.REMOTE.* 7 | *_BACKUP_*.txt 8 | *_BASE_*.txt 9 | *_LOCAL_*.txt 10 | *_REMOTE_*.txt 11 | 12 | # macOS 13 | .DS_Store 14 | .AppleDouble 15 | .LSOverride 16 | Icon 17 | ._* 18 | .VolumeIcon.icns 19 | .com.apple.timemachine.donotpresent 20 | 21 | # Python 22 | __pycache__/ 23 | *.mypy_cache 24 | *.py[cod] 25 | *.old.py 26 | *$py.class 27 | 28 | build/ 29 | .pytest_cache/ 30 | .python-version 31 | 32 | # Misc 33 | *.out 34 | *.files 35 | *.lprof 36 | *.swp 37 | *~ 38 | deprecated 39 | autoload/testspeedrawcode.txt 40 | gh-md-toc 41 | 42 | :w 43 | :q 44 | 45 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 2, June 1991 3 | 4 | Copyright (C) 1989, 1991 Free Software Foundation, Inc., 5 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 6 | Everyone is permitted to copy and distribute verbatim copies 7 | of this license document, but changing it is not allowed. 8 | 9 | Preamble 10 | 11 | The licenses for most software are designed to take away your 12 | freedom to share and change it. By contrast, the GNU General Public 13 | License is intended to guarantee your freedom to share and change free 14 | software--to make sure the software is free for all its users. This 15 | General Public License applies to most of the Free Software 16 | Foundation's software and to any other program whose authors commit to 17 | using it. (Some other Free Software Foundation software is covered by 18 | the GNU Lesser General Public License instead.) You can apply it to 19 | your programs, too. 20 | 21 | When we speak of free software, we are referring to freedom, not 22 | price. Our General Public Licenses are designed to make sure that you 23 | have the freedom to distribute copies of free software (and charge for 24 | this service if you wish), that you receive source code or can get it 25 | if you want it, that you can change the software or use pieces of it 26 | in new free programs; and that you know you can do these things. 27 | 28 | To protect your rights, we need to make restrictions that forbid 29 | anyone to deny you these rights or to ask you to surrender the rights. 30 | These restrictions translate to certain responsibilities for you if you 31 | distribute copies of the software, or if you modify it. 32 | 33 | For example, if you distribute copies of such a program, whether 34 | gratis or for a fee, you must give the recipients all the rights that 35 | you have. You must make sure that they, too, receive or can get the 36 | source code. And you must show them these terms so they know their 37 | rights. 38 | 39 | We protect your rights with two steps: (1) copyright the software, and 40 | (2) offer you this license which gives you legal permission to copy, 41 | distribute and/or modify the software. 42 | 43 | Also, for each author's protection and ours, we want to make certain 44 | that everyone understands that there is no warranty for this free 45 | software. If the software is modified by someone else and passed on, we 46 | want its recipients to know that what they have is not the original, so 47 | that any problems introduced by others will not reflect on the original 48 | authors' reputations. 49 | 50 | Finally, any free program is threatened constantly by software 51 | patents. We wish to avoid the danger that redistributors of a free 52 | program will individually obtain patent licenses, in effect making the 53 | program proprietary. To prevent this, we have made it clear that any 54 | patent must be licensed for everyone's free use or not licensed at all. 55 | 56 | The precise terms and conditions for copying, distribution and 57 | modification follow. 58 | 59 | GNU GENERAL PUBLIC LICENSE 60 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 61 | 62 | 0. This License applies to any program or other work which contains 63 | a notice placed by the copyright holder saying it may be distributed 64 | under the terms of this General Public License. The "Program", below, 65 | refers to any such program or work, and a "work based on the Program" 66 | means either the Program or any derivative work under copyright law: 67 | that is to say, a work containing the Program or a portion of it, 68 | either verbatim or with modifications and/or translated into another 69 | language. (Hereinafter, translation is included without limitation in 70 | the term "modification".) Each licensee is addressed as "you". 71 | 72 | Activities other than copying, distribution and modification are not 73 | covered by this License; they are outside its scope. The act of 74 | running the Program is not restricted, and the output from the Program 75 | is covered only if its contents constitute a work based on the 76 | Program (independent of having been made by running the Program). 77 | Whether that is true depends on what the Program does. 78 | 79 | 1. You may copy and distribute verbatim copies of the Program's 80 | source code as you receive it, in any medium, provided that you 81 | conspicuously and appropriately publish on each copy an appropriate 82 | copyright notice and disclaimer of warranty; keep intact all the 83 | notices that refer to this License and to the absence of any warranty; 84 | and give any other recipients of the Program a copy of this License 85 | along with the Program. 86 | 87 | You may charge a fee for the physical act of transferring a copy, and 88 | you may at your option offer warranty protection in exchange for a fee. 89 | 90 | 2. You may modify your copy or copies of the Program or any portion 91 | of it, thus forming a work based on the Program, and copy and 92 | distribute such modifications or work under the terms of Section 1 93 | above, provided that you also meet all of these conditions: 94 | 95 | a) You must cause the modified files to carry prominent notices 96 | stating that you changed the files and the date of any change. 97 | 98 | b) You must cause any work that you distribute or publish, that in 99 | whole or in part contains or is derived from the Program or any 100 | part thereof, to be licensed as a whole at no charge to all third 101 | parties under the terms of this License. 102 | 103 | c) If the modified program normally reads commands interactively 104 | when run, you must cause it, when started running for such 105 | interactive use in the most ordinary way, to print or display an 106 | announcement including an appropriate copyright notice and a 107 | notice that there is no warranty (or else, saying that you provide 108 | a warranty) and that users may redistribute the program under 109 | these conditions, and telling the user how to view a copy of this 110 | License. (Exception: if the Program itself is interactive but 111 | does not normally print such an announcement, your work based on 112 | the Program is not required to print an announcement.) 113 | 114 | These requirements apply to the modified work as a whole. If 115 | identifiable sections of that work are not derived from the Program, 116 | and can be reasonably considered independent and separate works in 117 | themselves, then this License, and its terms, do not apply to those 118 | sections when you distribute them as separate works. But when you 119 | distribute the same sections as part of a whole which is a work based 120 | on the Program, the distribution of the whole must be on the terms of 121 | this License, whose permissions for other licensees extend to the 122 | entire whole, and thus to each and every part regardless of who wrote it. 123 | 124 | Thus, it is not the intent of this section to claim rights or contest 125 | your rights to work written entirely by you; rather, the intent is to 126 | exercise the right to control the distribution of derivative or 127 | collective works based on the Program. 128 | 129 | In addition, mere aggregation of another work not based on the Program 130 | with the Program (or with a work based on the Program) on a volume of 131 | a storage or distribution medium does not bring the other work under 132 | the scope of this License. 133 | 134 | 3. You may copy and distribute the Program (or a work based on it, 135 | under Section 2) in object code or executable form under the terms of 136 | Sections 1 and 2 above provided that you also do one of the following: 137 | 138 | a) Accompany it with the complete corresponding machine-readable 139 | source code, which must be distributed under the terms of Sections 140 | 1 and 2 above on a medium customarily used for software interchange; or, 141 | 142 | b) Accompany it with a written offer, valid for at least three 143 | years, to give any third party, for a charge no more than your 144 | cost of physically performing source distribution, a complete 145 | machine-readable copy of the corresponding source code, to be 146 | distributed under the terms of Sections 1 and 2 above on a medium 147 | customarily used for software interchange; or, 148 | 149 | c) Accompany it with the information you received as to the offer 150 | to distribute corresponding source code. (This alternative is 151 | allowed only for noncommercial distribution and only if you 152 | received the program in object code or executable form with such 153 | an offer, in accord with Subsection b above.) 154 | 155 | The source code for a work means the preferred form of the work for 156 | making modifications to it. For an executable work, complete source 157 | code means all the source code for all modules it contains, plus any 158 | associated interface definition files, plus the scripts used to 159 | control compilation and installation of the executable. However, as a 160 | special exception, the source code distributed need not include 161 | anything that is normally distributed (in either source or binary 162 | form) with the major components (compiler, kernel, and so on) of the 163 | operating system on which the executable runs, unless that component 164 | itself accompanies the executable. 165 | 166 | If distribution of executable or object code is made by offering 167 | access to copy from a designated place, then offering equivalent 168 | access to copy the source code from the same place counts as 169 | distribution of the source code, even though third parties are not 170 | compelled to copy the source along with the object code. 171 | 172 | 4. You may not copy, modify, sublicense, or distribute the Program 173 | except as expressly provided under this License. Any attempt 174 | otherwise to copy, modify, sublicense or distribute the Program is 175 | void, and will automatically terminate your rights under this License. 176 | However, parties who have received copies, or rights, from you under 177 | this License will not have their licenses terminated so long as such 178 | parties remain in full compliance. 179 | 180 | 5. You are not required to accept this License, since you have not 181 | signed it. However, nothing else grants you permission to modify or 182 | distribute the Program or its derivative works. These actions are 183 | prohibited by law if you do not accept this License. Therefore, by 184 | modifying or distributing the Program (or any work based on the 185 | Program), you indicate your acceptance of this License to do so, and 186 | all its terms and conditions for copying, distributing or modifying 187 | the Program or works based on it. 188 | 189 | 6. Each time you redistribute the Program (or any work based on the 190 | Program), the recipient automatically receives a license from the 191 | original licensor to copy, distribute or modify the Program subject to 192 | these terms and conditions. You may not impose any further 193 | restrictions on the recipients' exercise of the rights granted herein. 194 | You are not responsible for enforcing compliance by third parties to 195 | this License. 196 | 197 | 7. If, as a consequence of a court judgment or allegation of patent 198 | infringement or for any other reason (not limited to patent issues), 199 | conditions are imposed on you (whether by court order, agreement or 200 | otherwise) that contradict the conditions of this License, they do not 201 | excuse you from the conditions of this License. If you cannot 202 | distribute so as to satisfy simultaneously your obligations under this 203 | License and any other pertinent obligations, then as a consequence you 204 | may not distribute the Program at all. For example, if a patent 205 | license would not permit royalty-free redistribution of the Program by 206 | all those who receive copies directly or indirectly through you, then 207 | the only way you could satisfy both it and this License would be to 208 | refrain entirely from distribution of the Program. 209 | 210 | If any portion of this section is held invalid or unenforceable under 211 | any particular circumstance, the balance of the section is intended to 212 | apply and the section as a whole is intended to apply in other 213 | circumstances. 214 | 215 | It is not the purpose of this section to induce you to infringe any 216 | patents or other property right claims or to contest validity of any 217 | such claims; this section has the sole purpose of protecting the 218 | integrity of the free software distribution system, which is 219 | implemented by public license practices. Many people have made 220 | generous contributions to the wide range of software distributed 221 | through that system in reliance on consistent application of that 222 | system; it is up to the author/donor to decide if he or she is willing 223 | to distribute software through any other system and a licensee cannot 224 | impose that choice. 225 | 226 | This section is intended to make thoroughly clear what is believed to 227 | be a consequence of the rest of this License. 228 | 229 | 8. If the distribution and/or use of the Program is restricted in 230 | certain countries either by patents or by copyrighted interfaces, the 231 | original copyright holder who places the Program under this License 232 | may add an explicit geographical distribution limitation excluding 233 | those countries, so that distribution is permitted only in or among 234 | countries not thus excluded. In such case, this License incorporates 235 | the limitation as if written in the body of this License. 236 | 237 | 9. The Free Software Foundation may publish revised and/or new versions 238 | of the General Public License from time to time. Such new versions will 239 | be similar in spirit to the present version, but may differ in detail to 240 | address new problems or concerns. 241 | 242 | Each version is given a distinguishing version number. If the Program 243 | specifies a version number of this License which applies to it and "any 244 | later version", you have the option of following the terms and conditions 245 | either of that version or of any later version published by the Free 246 | Software Foundation. If the Program does not specify a version number of 247 | this License, you may choose any version ever published by the Free Software 248 | Foundation. 249 | 250 | 10. If you wish to incorporate parts of the Program into other free 251 | programs whose distribution conditions are different, write to the author 252 | to ask for permission. For software which is copyrighted by the Free 253 | Software Foundation, write to the Free Software Foundation; we sometimes 254 | make exceptions for this. Our decision will be guided by the two goals 255 | of preserving the free status of all derivatives of our free software and 256 | of promoting the sharing and reuse of software generally. 257 | 258 | NO WARRANTY 259 | 260 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY 261 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN 262 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES 263 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED 264 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 265 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS 266 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE 267 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, 268 | REPAIR OR CORRECTION. 269 | 270 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 271 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR 272 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, 273 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING 274 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED 275 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY 276 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER 277 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE 278 | POSSIBILITY OF SUCH DAMAGES. 279 | 280 | END OF TERMS AND CONDITIONS 281 | 282 | How to Apply These Terms to Your New Programs 283 | 284 | If you develop a new program, and you want it to be of the greatest 285 | possible use to the public, the best way to achieve this is to make it 286 | free software which everyone can redistribute and change under these terms. 287 | 288 | To do so, attach the following notices to the program. It is safest 289 | to attach them to the start of each source file to most effectively 290 | convey the exclusion of warranty; and each file should have at least 291 | the "copyright" line and a pointer to where the full notice is found. 292 | 293 | 294 | Copyright (C) 295 | 296 | This program is free software; you can redistribute it and/or modify 297 | it under the terms of the GNU General Public License as published by 298 | the Free Software Foundation; either version 2 of the License, or 299 | (at your option) any later version. 300 | 301 | This program is distributed in the hope that it will be useful, 302 | but WITHOUT ANY WARRANTY; without even the implied warranty of 303 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 304 | GNU General Public License for more details. 305 | 306 | You should have received a copy of the GNU General Public License along 307 | with this program; if not, write to the Free Software Foundation, Inc., 308 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 309 | 310 | Also add information on how to contact you by electronic and paper mail. 311 | 312 | If the program is interactive, make it output a short notice like this 313 | when it starts in an interactive mode: 314 | 315 | Gnomovision version 69, Copyright (C) year name of author 316 | Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 317 | This is free software, and you are welcome to redistribute it 318 | under certain conditions; type `show c' for details. 319 | 320 | The hypothetical commands `show w' and `show c' should show the appropriate 321 | parts of the General Public License. Of course, the commands you use may 322 | be called something other than `show w' and `show c'; they could even be 323 | mouse-clicks or menu items--whatever suits your program. 324 | 325 | You should also get your employer (if you work as a programmer) or your 326 | school, if any, to sign a "copyright disclaimer" for the program, if 327 | necessary. Here is a sample; alter the names: 328 | 329 | Yoyodyne, Inc., hereby disclaims all copyright interest in the program 330 | `Gnomovision' (which makes passes at compilers) written by James Hacker. 331 | 332 | , 1 April 1989 333 | Ty Coon, President of Vice 334 | 335 | This General Public License does not permit incorporating your program into 336 | proprietary programs. If your program is a subroutine library, you may 337 | consider it more useful to permit linking proprietary applications with the 338 | library. If this is what you want to do, use the GNU Lesser General 339 | Public License instead of this License. 340 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # vim-repl 2 | 3 | * [vim-repl](#vim-repl) 4 | * [Introduction](#introduction) 5 | * [Details](#details) 6 | * [Installation](#installation) 7 | * [Usage](#usage) 8 | * [How to open REPL](#how-to-open-repl) 9 | * [How to exit REPL](#how-to-exit-repl) 10 | * [How to send code to REPL](#how-to-send-code-to-repl) 11 | * [How to switch to REPL environment](#how-to-switch-to-repl-environment) 12 | * [How to hide the REPL environment](#how-to-hide-the-repl-environment) 13 | * [How to debug python script?](#how-to-debug-python-script) 14 | * [How to open python with virtual environment?](#how-to-open-python-with-virtual-environment) 15 | * [How to send python code block seperated by # %% or other tag](#how-to-send-python-code-block-seperated-by---or-other-tag) 16 | * [How to just send right hand side of current line to REPL environment?](#how-to-just-send-right-hand-side-of-current-line-to-repl-environment) 17 | * [Setting](#setting) 18 | * [My Configuration for Vim-Repl](#my-configuration-for-vim-repl) 19 | * [Updates](#updates) 20 | * [2021.3.23](#2021323) 21 | * [2020.10.22](#20201022) 22 | * [2020.4.29](#2020429) 23 | * [2019.10.14](#20191014) 24 | * [2019.8.27](#2019827) 25 | * [2019.8.16](#2019816) 26 | * [2019.8.11](#2019811) 27 | * [2019.8.10](#2019810) 28 | * [2019.8.9](#201989) 29 | * [2019.8.7](#201987) 30 | * [2019.8.6](#201986) 31 | * [2019.8.3](#201983) 32 | * [2019.5.28](#2019528) 33 | * [2019.5.14](#2019514) 34 | * [2019.4.27](#2019427) 35 | * [2018.7.7](#201877) 36 | * [2018.7.26](#2018726) 37 | * [Troubleshooting](#troubleshooting) 38 | 39 | ## Introduction 40 | 41 | Open the interactive environment with the code you are writing. 42 | 43 | Read–Eval–Print Loop (REPL), also known as an interactive toplevel or language shell, is extremely useful in python coding. However, it's difficult to interact with REPL when writing python with vim. Therefore, I write this plugin to provide a better repl environment for coding python or other file in vim. It use the terminal feature for vim8. So your vim version must be no less than 8.0 and support termianl function to use this plugin. 44 | 45 | 46 | 如果您想阅读中文文档,请移步:[知乎-vim-repl](https://zhuanlan.zhihu.com/p/37231865) 47 | 48 | 49 | ## Details 50 | 51 | ![usage](https://github.com/sillybun/vim-repl/blob/master/assets/repl.gif) 52 | 53 | Use vim to open a file, run `:REPLToggle` to open the REPL environment. If the REPL is already open. `:REPLToggle` will close REPL. 54 | 55 | By default, Python Perl and Vimscript are supported. If you run `:REPLToggle` in a `python` file, you will get `python` in the terminal buffer. In a `perl` file, vim-repl will try to use `perlconsole`, `reply` and `re.pl` (in that order); so one of them should be installed. In a `vim` file, `vim-repl` will try to open `vim -e`. 56 | In order to support more languages, you will have to specify which program to run for each specific filetype. 57 | 58 | There are three ways to send codes to REPL environment: 59 | 60 | - the first way: stay in normal mode and press `w` and the whole line of the cursor will be sent to REPL. 61 | 62 | ![usage](https://github.com/sillybun/vim-repl/blob/master/assets/usage-1.gif) 63 | 64 | - The second way is that in normal mode, move the cursor to the first line of one block (start of a function: `def functionname(argv):`, start of a for/while loop, start of a if-else statement) and press `w`, the whole block will be sent to REPL automatically. 65 | 66 | ![usage](https://github.com/sillybun/vim-repl/blob/master/assets/usage2.gif) 67 | 68 | - The third way is to select some lines in visual mode and press `w`, the seleted code will be sent to REPL. 69 | 70 | ![usage](https://github.com/sillybun/vim-repl/blob/master/assets/usage-3.gif) 71 | 72 | - The last way is to select some word in visual mode and press `w` and the selected word will be sent to REPL. 73 | 74 | ![usage](https://github.com/sillybun/vim-repl/blob/master/assets/usage4.gif) 75 | 76 | Note: currently this plugin doesn't support NeoVim. 77 | 78 | ## Installation 79 | 80 | This plugin support all platforms (Windows, MacOS, Linux). Use your plugin manager of choice. 81 | 82 | For MacOS, Windows and Linux Users (vim should have `+terminal` and `+timers` support): 83 | 84 | - [vim-plug](https://github.com/junegunn/vim-plug) (**recommended**) 85 | - Add `Plug 'sillybun/vim-repl'` to .vimrc 86 | - Run `:PlugInstall` 87 | 88 | ## Usage 89 | 90 | ### How to open REPL 91 | 92 | ``` 93 | :REPLToggle 94 | ``` 95 | 96 | 97 | ### How to exit REPL 98 | 99 | ``` 100 | :REPLToggle 101 | ``` 102 | 103 | > If you bind `r` to `:REPLToggle` by `nnoremap r :REPLToggle`, you only need to press `r` to open or close REPL. 104 | 105 | > leader key is set by `let g:mapleader=' '` 106 | 107 | ### How to send code to REPL 108 | 109 | - In Normal Mode, press `w`, code in the current line (including leading space and the end center) will be transmitted to REPL 110 | - In Normal Mode, move the cursor to the begin of a block and press `w` and the whole block will be sent to REPL (By default, code block start with `def`, `class`, `while`, `for`, `if` will be automatically sent. You can control the definition of start of code block by setting `g:repl_auto_sends`) 111 | - In Visual Mode, press `w`, selected code (whole line includeing leading space and the last center) will be trasmitted to REPL 112 | - In Visual Mode, selected a word and press `w`, and the selected word will be sent to REPL according to certain rules defined by `g:repl_sendvariable_template`. 113 | 114 | Currently, asynchronous transmission is completed and it is supported for all language if you correctly set the input symbols of the corresponding language. 115 | Setting for python is already done by author. Supported command shell for python include `python`, `ipython` and `ptpython`. 116 | 117 | Take a typical python REPL environment as an example 118 | 119 | ``` 120 | >>> 1+1 121 | 2 122 | >>> for i in range(3): 123 | ... print(i) 124 | ... 125 | >>> 126 | ``` 127 | 128 | Therefore, the input symbols for python includes `'>>>'` and `'...'`. They tell the plugin that it can continue send another line to the REPL environment if the current line of the REPL environment is either `'>>>'` or `'...'`. If you want async support for other language aside from python, you have to add entry for this language to `g:repl_input_symbols` 129 | 130 | The default value of `g:repl_input_symbols` is, the value of the dictionary can be either a list of string or a string: 131 | 132 | ``` 133 | let g:repl_input_symbols = { 134 | \ 'python': ['>>>', '>>>>', 'ipdb>', 'pdb', '...'], 135 | \ } 136 | ``` 137 | 138 | 139 | ### How to switch to REPL environment 140 | 141 | You can switch buffer between file and REPL environment the same as change between two vim buffer. press `` will change between file and REPL environment. `` also work the way it should be 142 | 143 | ### How to hide the REPL environment 144 | 145 | ``` 146 | :REPLHide 147 | ``` 148 | 149 | use `REPLUnhide` or `REPLToggle` to reveal the hidden terminal. 150 | 151 | ### How to debug python script? 152 | 153 | Note: You should have to install `ipdb` to debug python script! check it via: 154 | 155 | ``` 156 | python -m ipdb 157 | ``` 158 | 159 | if not installed, install it via: 160 | 161 | ``` 162 | python -m pip install ipdb 163 | ``` 164 | 165 | The default debugger is `python3 -m pip`, you can specify it through adding `'python-debug' : ''` to `g:repl_program` 166 | 167 | I suggest the following key binding: 168 | 169 | ``` 170 | autocmd Filetype python nnoremap :REPLDebugStopAtCurrentLine 171 | autocmd Filetype python nnoremap :REPLPDBN 172 | autocmd Filetype python nnoremap :REPLPDBS 173 | ``` 174 | 175 | To debug python code, (don't open python REPL environment via `:REPLToggle`), move the cursor to certain line and press ``, and ipdb will be run and the program will be stopped at that line. Press `` will run a single line and Press `` will also run a single line but will jump into functions. 176 | 177 | ![usage](https://github.com/sillybun/vim-repl/blob/master/assets/debug-python.gif) 178 | 179 | ### How to open python with virtual environment? 180 | 181 | There are two ways to open python with virtual environment. 182 | 183 | The first method (global) is that put: 184 | ``` 185 | g:repl_python_pre_launch_command = 'source /path_to_new_venv/bin/activate' 186 | ``` 187 | in `.vimrc`. And once you toggle python, the following command will be run: 188 | ``` 189 | :terminal [g:repl_program['default'][0]/bash/cmd.exe] 190 | source /path_to_new_venv/bin/activate 191 | python/ipython/ptpython 192 | ``` 193 | 194 | The second method (specific virtual environment) is that put: 195 | ``` 196 | #REPLENV: /path_to_new_venv/bin/activate 197 | ``` 198 | in python script. If you open this python file with vim and toggle vim-repl, python will be run in specific virtual environment. 199 | 200 | ### How to send python code block seperated by # %% or other tag 201 | 202 | If you have the following code seperated into two blocks: 203 | 204 | ``` 205 | # %% 206 | print(1) 207 | print(2) 208 | 209 | # %% 210 | print(3) 211 | print(5) 212 | ``` 213 | 214 | Just move cursor to some code block and use command `:REPLSendSession`, whole block will be sent to the REPL environment (e.g. Both `print(1)` and `print(2)`) 215 | 216 | Code block seperator are defined by 217 | 218 | ``` 219 | let g:repl_code_block_fences = {'python': '# %%', 'zsh': '# %%', 'markdown': '```'} 220 | ``` 221 | 222 | and `g:repl_code_block_fences_end` (by default the latter is the same as the former). So if you want to seperate code block by `###`, just put: 223 | 224 | ``` 225 | let g:repl_code_block_fences = {'python': '###', 'zsh': '# %%', 'markdown': '```'} 226 | ``` 227 | 228 | to `.vimrc` 229 | 230 | If you want to start code block with `### Start` and end it with `### End`, just put: 231 | 232 | ``` 233 | let g:repl_code_block_fences = {'python': '### Start', 'zsh': '# %%', 'markdown': '```'} 234 | let g:repl_code_block_fences_end = {'python': '### End', 'zsh': '# %%', 'markdown': '```'} 235 | ``` 236 | 237 | to `.vimrc` 238 | 239 | ### How to just send right hand side of current line to REPL environment? 240 | 241 | If your cursor is on line, for example: 242 | 243 | ``` 244 | return [x for x in range(10)] 245 | ``` 246 | 247 | and you only want to send `[x for x in range(10)]` to REPL environment and to check result of it, You can use command `:REPLSendRHSofCurrentLine`. 248 | 249 | ## Setting 250 | 251 | you can bind the `REPLToggle` command to a certain key to make it more convenience. 252 | 253 | ``` 254 | nnoremap r :REPLToggle 255 | ``` 256 | 257 | **g:repl_width** 258 | 259 | it represents the width of REPL windows. there is no default value. 260 | 261 | **g:sendtorepl_invoke_key** 262 | 263 | you can customize the key to send code to REPL environment. The default key is `w` 264 | 265 | ``` 266 | let g:sendtorepl_invoke_key = "w" 267 | ``` 268 | 269 | **repl_position** 270 | it controls the location where REPL windows will appear 271 | - 0 represents bottom 272 | - 1 represents top 273 | - 2 represents left 274 | - 3 represents right 275 | 276 | ``` 277 | let g:repl_position = 0 278 | ``` 279 | 280 | **repl_stayatrepl_when_open** 281 | 282 | it controls whether the cursor will return to the current buffer or just stay at the REPL environment when open REPL environment using `REPLToggle` command 283 | 284 | 0 represents return back to current file. 285 | 286 | 1 represents stay in REPL environment. 287 | 288 | ``` 289 | let g:repl_stayatrepl_when_open = 0 290 | ``` 291 | 292 | **repl_program** 293 | 294 | It controls which program will be run for certain filetype. If there is no entry in the dictionary, the program specified by "default" will be run. If there is no "default" entry, "bash" will be the choice. 295 | 296 | ``` 297 | let g:repl_program = { 298 | \ 'python': ['python'], 299 | \ 'default': ['bash'] 300 | \ } 301 | ``` 302 | 303 | > For those who use `ipython` as REPL program: Since ipython 7 and ipython 6 have a big difference, I have to treat them seperately and have to detect the version of ipython by `ipython --version` which will cause a obvious lagging. You have better to **specify version of ipython** by setting: 304 | 305 | ``` 306 | let g:repl_ipython_version = '6' 307 | ``` 308 | 309 | or 310 | 311 | ``` 312 | let g:repl_ipython_version = '7.7' 313 | ``` 314 | 315 | I have tested some version of ipython and find that this plugin cannot work on 7.0.1. Please use version >= 7.1.1 316 | 317 | **repl_exit_command** 318 | 319 | It controls the command to exit different repl program correctly. (Notice: exitcommand depends on repl program not filetype of the current file, so if you want to specify exit command for program like 'ipython', please add `"ipython": "quit()"` in the dictionary) 320 | 321 | ``` 322 | let g:repl_exit_commands = { 323 | \ 'python': 'quit()', 324 | \ 'bash': 'exit', 325 | \ 'zsh': 'exit', 326 | \ 'default': 'exit', 327 | \ } 328 | ``` 329 | 330 | Once user run `:REPLToggle` when the REPL environment is already open, this plugin will try to close the repl environment by the following step: 331 | 332 | - send a interupt signal `` to the program 333 | - if the program is not close, then send two `\n` and the `exit_command + \n` to the program. 334 | 335 | ``` 336 | let g:repl_auto_sends = ['class ', 'def ', 'for ', 'if ', 'while ', 'with ', 'async def', '@', 'try'] 337 | ``` 338 | 339 | If `g:repl_auto_sends` is defined, once user sends a line starts with any pattern contained in the list, whole block will be send automatically. 340 | 341 | ``` 342 | let g:repl_python_auto_send_unfinish_line = 1 343 | ``` 344 | 345 | If `g:repl_python_auto_send_unfinish_line` is set to 1, once user sends a line that is not finished yet, complete line will be send automatically. For example, for codes: 346 | 347 | ``` 348 | f(1, 349 | 2) 350 | ``` 351 | 352 | press `w` in the first line, `f(1,2)` will be sent automatically. 353 | 354 | ``` 355 | let g:repl_cursor_down = 1 356 | ``` 357 | 358 | If `g:repl_cursor_down` is 1, once user sends code blocks using visual selection, the cursor will move to the next line of the last line of the code blocks. 359 | 360 | ``` 361 | let g:repl_python_auto_import = 1 362 | ``` 363 | 364 | If `g:repl_python_auto_import` is 1, once user toggle python REPL environment, all import code will be automatically send to the REPL environment 365 | 366 | ``` 367 | let g:repl_python_automerge = 0 368 | ``` 369 | 370 | If `g:repl_python_automerge` is 1, once user sends code which is seperated into multilines, they are combined into one line automatically. For example, if the code is: 371 | 372 | ``` 373 | a = 1+\ 374 | 2+\ 375 | 3 376 | ``` 377 | 378 | , then `a = 1+2+3` will be sent to the repl environment instead of three lines. 379 | 380 | ``` 381 | let g:repl_console_name = 'ZYTREPL' 382 | ``` 383 | represents the name for repl console. 384 | 385 | ``` 386 | let g:repl_vimscript_engine = 0 387 | ``` 388 | 389 | If your vim doesn't support python or python3, I provides limited supported for it: 390 | - It works for `python` and `ipython` 391 | - It also works for `ptpython` but every line of the codes to be send should be complete, which means if you seperate a line of code into two or more lines, the plugin will not handle it correctly. 392 | 393 | ``` 394 | let g:repl_sendvariable_template = { 395 | \ 'python': 'print()', 396 | \ 'ipython': 'print()', 397 | \ 'ptpython': 'print()', 398 | \ } 399 | ``` 400 | 401 | `g:repl_sendvariable_template` defines how word is sent to REPL. For example, by default, if you select `some_variable` and presss `w`, `print(some_variable)` will be sent to REPL. You can define your rule with the help of `g:repl_sendvariable_template`. `` will be replaced by selected word and then be sent to REPL. 402 | 403 | ``` 404 | let g:repl_unhide_when_send_lines = 0 405 | ``` 406 | 407 | If `g:repl_unhide_when_send_lines = 1`, when REPL is hidden and you want to send lines, REPL environment will be unhiden before the code is sent. 408 | 409 | ``` 410 | g:repl_output_copy_to_register 411 | ``` 412 | 413 | If `g:repl_output_copy_to_register` is set to a letter (a-z), then output of REPL program will be copied to the corresponding register. (Currently only support ipython) 414 | 415 | ## My Configuration for Vim-Repl 416 | 417 | ``` 418 | Plug 'sillybun/vim-repl' 419 | let g:repl_program = { 420 | \ 'python': 'ipython', 421 | \ 'default': 'zsh', 422 | \ 'r': 'R', 423 | \ 'lua': 'lua', 424 | \ 'vim': 'vim -e', 425 | \ } 426 | let g:repl_predefine_python = { 427 | \ 'numpy': 'import numpy as np', 428 | \ 'matplotlib': 'from matplotlib import pyplot as plt' 429 | \ } 430 | let g:repl_cursor_down = 1 431 | let g:repl_python_automerge = 1 432 | let g:repl_ipython_version = '7' 433 | let g:repl_output_copy_to_register = "t" 434 | nnoremap r :REPLToggle 435 | nnoremap e :REPLSendSession 436 | autocmd Filetype python nnoremap :REPLDebugStopAtCurrentLine 437 | autocmd Filetype python nnoremap :REPLPDBN 438 | autocmd Filetype python nnoremap :REPLPDBS 439 | let g:repl_position = 3 440 | ``` 441 | 442 | ## Updates 443 | 444 | ### 2021.3.23 445 | 446 | - Add support for auto send uncompleted line 447 | - Fix the bug that continuously send lines to REPL will cause former codes missing. 448 | 449 | ### 2020.10.22 450 | 451 | - Add support for auto import package for python file 452 | - Add support for import from relative path. For example, if in package 'python_package', there are two file 'a.py' and 'b.py' and a `__init__.py`. If you import 'B.py' in 'A.py' through `import .B`. Then if you edit `A.py` using vim and run `vim-repl`. `import .B` will be automatically transformed into `import python_package.B` and be sent to REPL environment. 453 | 454 | ### 2020.4.29 455 | 456 | - Add support for mulitiple repl program. Thanks to @roachsinai 's great work. 457 | 458 | ### 2019.10.14 459 | 460 | - Add support for python virtual environment. 461 | 462 | ### 2019.8.27 463 | 464 | - Set the default program in Windows to `cmd.exe` 465 | 466 | ### 2019.8.16 467 | 468 | - Add support for vimscript REPL. 469 | 470 | ### 2019.8.11 471 | 472 | - Add send selected word function and `g:repl_sendvariable_template`. 473 | 474 | ### 2019.8.10 475 | 476 | - `vim-repl` no longer need the support of `vim-async` anymore. 477 | 478 | ### 2019.8.9 479 | 480 | - Add almost full support for vim without `+python` or `+python3` support. 481 | - Rewrite `vim-async` using `timer_start` 482 | - Set the default value of `g:repl_auto_sends` to `['class ', 'def ', 'for ', 'if ', 'while ']` 483 | - Set the default value of `g:repl_cursor_down` to 1 484 | 485 | ### 2019.8.7 486 | 487 | - Fix bug for windows 488 | - `g:repl_cursor_down` will also affect SendCurrentLine 489 | 490 | ### 2019.8.6 491 | 492 | - Add support for ipython version >= 7 493 | 494 | ### 2019.8.3 495 | 496 | - Rewrite the program to format python codes using python language 497 | - Abandon using C++ to handle python code 498 | - `g:repl_python_automerge` is provided. 499 | - `g:repl_console_name` is provided 500 | - Support both `python` and `python3` 501 | - Remove Checkpoint function 502 | 503 | ### 2019.5.28 504 | 505 | - Support REPL environment for Windows. 506 | 507 | ### 2019.5.14 508 | 509 | - `g:repl_cursor_down` is provided. 510 | 511 | ### 2019.4.27 512 | 513 | - Async feature is provided by [vim-async](https://github.com/sillybun/vim-async) 514 | 515 | ### 2018.7.7 516 | 517 | - Use job feature in vim 8.0 to provide better performance. 518 | 519 | ### 2018.7.26 520 | 521 | - Add support for temporary hide the terminal window. 522 | If the REPL is already open. `:REPLToggle` will close REPL. 523 | 524 | ## Troubleshooting 525 | 526 | - The python code cannot send porperly to REPL environment 527 | 528 | This trouble cann only happen for vim without `+python` or `+python3` support. Without python engine, vim-repl can only use vimscript to manipulate code to be sent, and it now cannot handle code seperated into multilines. For example, the following code cannot be sent porperly. 529 | 530 | ``` 531 | some_dict = {1:1, 532 | 2:2, 533 | 3:3} 534 | print(some_dict) 535 | ``` 536 | 537 | You should combine mulitlines code into one line to make the plugin work porperly as following: 538 | ``` 539 | some_dict = {1:1, 2:2, 3:3} 540 | print(some_dict) 541 | ``` 542 | 543 | For vim with `+python` or `+python3` support, this problem will not happen. If it happens, check whether `g:repl_vimscript_engine` is set to `0`. If `g:repl_vimscript_engine = 0`, there is a bug here. Please report the bug; If `g:repl_vimscript_engine=1`, search `let g:repl_vimscript_engine = 1` in vimrc and remove it. 544 | 545 | - `r` doesn't work for my vim 546 | 547 | `` in the example mean the leader key. Check the your leader key mapping in vimrc. To set leader key to ``, add `let g:mapleader=' '` 548 | 549 | - Error detected while processing function repl#REPLToggle [10].. repl #REPLOpen 550 | 551 | The reason of this error is that vim-repl try to open the program which is not installed on your machine. For example, if you havn't install `ipython` and set `g:repl_program['python']=['ipython']`, this error will occur. 552 | 553 | - How to change to Normal Mode in REPL environment? 554 | 555 | In REPL environment, press `N`. Or you can use the setting: 556 | 557 | ``` 558 | tnoremap N 559 | tnoremap Nk 560 | tnoremap Nj 561 | ``` 562 | 563 | And then you can press `` to change to Normal Mode. 564 | 565 | ----- 566 | 567 | If you like my plugin, please give me a star! 568 | 569 | -------------------------------------------------------------------------------- /assets/debug-python.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sillybun/vim-repl/e6c1eaebcf3c1755084279475d4b7909d472d85a/assets/debug-python.gif -------------------------------------------------------------------------------- /assets/repl.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sillybun/vim-repl/e6c1eaebcf3c1755084279475d4b7909d472d85a/assets/repl.gif -------------------------------------------------------------------------------- /assets/usage-1.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sillybun/vim-repl/e6c1eaebcf3c1755084279475d4b7909d472d85a/assets/usage-1.gif -------------------------------------------------------------------------------- /assets/usage-3.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sillybun/vim-repl/e6c1eaebcf3c1755084279475d4b7909d472d85a/assets/usage-3.gif -------------------------------------------------------------------------------- /assets/usage2.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sillybun/vim-repl/e6c1eaebcf3c1755084279475d4b7909d472d85a/assets/usage2.gif -------------------------------------------------------------------------------- /assets/usage4.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sillybun/vim-repl/e6c1eaebcf3c1755084279475d4b7909d472d85a/assets/usage4.gif -------------------------------------------------------------------------------- /assets/wechat.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sillybun/vim-repl/e6c1eaebcf3c1755084279475d4b7909d472d85a/assets/wechat.JPG -------------------------------------------------------------------------------- /autoload/async.vim: -------------------------------------------------------------------------------- 1 | let s:VaildCommand = ['let ', 'unlet ', 'echo ', 'echom ', 'execute ', 'call ', 'unlet ', 'map', 'umap', 'imap', 'nmap', 'vmap', 'inoremap ', 'nnoremap ', 'vnoremap ', 'autocmd ', 'Plug ', 'au ', 'set ', 'filetype ', 'syntax '] 2 | 3 | let s:filename=expand(':p:h') 4 | 5 | function! async#StartWith(string, substring) 6 | if strlen(a:string) < strlen(a:substring) 7 | return 0 8 | elseif a:string[0:(strlen(a:substring)-1)] ==# a:substring 9 | return 1 10 | else 11 | return 0 12 | endif 13 | endfunction 14 | 15 | function! async#StartWithAnyone(string, list) 16 | for l:l in a:list 17 | if async#StartWith(a:string, l:l) 18 | return 1 19 | endif 20 | endfor 21 | return 0 22 | endfunction 23 | 24 | function! async#AsyncRunEngine(codelist, currentline, wait_time, channel) abort 25 | let l:index = a:currentline 26 | let l:wait_time = a:wait_time 27 | while l:index != len(a:codelist) 28 | let l:currentcode = a:codelist[l:index] 29 | if async#StartWithAnyone(l:currentcode, s:VaildCommand) 30 | execute l:currentcode 31 | let l:index = l:index + 1 32 | continue 33 | elseif async#StartWith(l:currentcode, 'if ') 34 | if eval(l:currentcode[3:]) 35 | let l:index = l:index + 1 36 | continue 37 | else 38 | let l:temp = l:index + 1 39 | let l:level = 0 40 | while l:temp < len(a:codelist) 41 | if async#StartWith(a:codelist[l:temp], 'if ') 42 | let l:level = l:level + 1 43 | elseif async#StartWith(a:codelist[l:temp], 'endif') 44 | let l:level = l:level - 1 45 | endif 46 | if l:level == 0 && a:codelist[l:temp] ==# 'else' 47 | let l:index = l:temp + 1 48 | break 49 | elseif l:level == 0 && async#StartWith(a:codelist[l:temp], 'elseif') 50 | if eval(a:codelist[l:temp][7:]) 51 | let l:index = l:temp + 1 52 | break 53 | endif 54 | elseif l:level == -1 55 | let l:index = l:temp + 1 56 | break 57 | endif 58 | let l:temp = l:temp + 1 59 | endwhile 60 | endif 61 | elseif l:currentcode ==# 'else' 62 | let l:temp = l:index + 1 63 | let l:level = 0 64 | while l:temp < len(a:codelist) 65 | if async#StartWith(a:codelist[l:temp], 'if ') 66 | let l:level = l:level + 1 67 | elseif a:codelist[l:temp] ==# 'endif' 68 | let l:level = l:level - 1 69 | endif 70 | let l:temp = l:temp + 1 71 | if l:level == -1 72 | break 73 | endif 74 | endwhile 75 | let l:index = l:temp 76 | elseif l:currentcode ==# 'endif' 77 | let l:index = l:index + 1 78 | elseif async#StartWith(l:currentcode, 'wait') 79 | if eval(l:currentcode[5:]) 80 | let l:index = l:index + 1 81 | let l:wait_time = 0 82 | else 83 | let l:sleep_time = 80 + 10 * l:wait_time 84 | let l:wait_time = l:wait_time + 1 85 | call timer_start(l:sleep_time, function('async#AsyncRunEngine', [a:codelist, l:index, l:wait_time])) 86 | return 87 | endif 88 | elseif async#StartWith(l:currentcode, 'LABEL ') 89 | let l:index = l:index + 1 90 | elseif async#StartWith(l:currentcode, 'GOTO ') 91 | let l:temp = 0 92 | while l:temp < len(a:codelist) 93 | if async#StartWith(a:codelist[l:temp], 'LABEL ') && a:codelist[l:temp][6:] ==# l:currentcode[5:] 94 | let l:index = l:temp + 1 95 | break 96 | endif 97 | let l:temp = l:temp + 1 98 | endwhile 99 | elseif async#StartWith(l:currentcode, 'sleep ') 100 | call timer_start(str2nr(l:currentcode[6:]), function('async#AsyncRunEngine', [a:codelist, l:index+1, 0])) 101 | return 102 | elseif async#StartWith(l:currentcode, 'return') 103 | return 104 | endif 105 | endwhile 106 | endfunction 107 | 108 | function! async#AsyncCodeRun(...) 109 | call async#AsyncRunEngine(a:1, 0, 0, 0) 110 | endfunction 111 | -------------------------------------------------------------------------------- /autoload/formatpythoncode.vim: -------------------------------------------------------------------------------- 1 | function! formatpythoncode#Seperateintoblocks(codes) 2 | let l:index = 0 3 | let l:blocks = [] 4 | while l:index < len(a:codes) 5 | let l:indentlevel = repl#GetIndent(a:codes[l:index]) 6 | let l:blockend = l:index + 1 7 | let l:temp_block = [a:codes[l:index]] 8 | while l:blockend < len(a:codes) && repl#GetIndent(a:codes[l:blockend]) > l:indentlevel 9 | let l:temp_block = l:temp_block + [a:codes[l:blockend]] 10 | let l:blockend = l:blockend + 1 11 | endwhile 12 | let l:blocks = l:blocks + [l:temp_block] 13 | let l:index = l:blockend 14 | endwhile 15 | return blocks 16 | endfunction 17 | 18 | function! formatpythoncode#Trunctindent(blocks) 19 | let l:newblocks = [] 20 | for l:block in a:blocks 21 | let l:indentlevel = repl#GetIndent(l:block[0]) 22 | let l:temp_block = [] 23 | for l:line in l:block 24 | let l:temp_block = l:temp_block + [l:line[l:indentlevel:]] 25 | endfor 26 | let l:newblocks = l:newblocks + [l:temp_block] 27 | endfor 28 | return l:newblocks 29 | endfunction 30 | 31 | function! formatpythoncode#AutoStop(line, pythonprogram, version) 32 | if a:pythonprogram ==# 'ptpython' 33 | if repl#StartWith(a:line, 'pass ') 34 | return 1 35 | else 36 | return 0 37 | endif 38 | elseif a:pythonprogram ==# 'ipython' 39 | if a:version[0] == '7' 40 | return 0 41 | elseif repl#StartWithAny(a:version, ['pass ', 'return ', 'raise ', 'continue ', 'break ']) 42 | return 1 43 | else 44 | return 0 45 | endif 46 | endif 47 | endfunction 48 | 49 | function! formatpythoncode#Format_to_repl(codes, pythonprogram, version) 50 | let l:codes = [] 51 | for l:i in range(len(a:codes)) 52 | let l:code = a:codes[l:i] 53 | if len(repl#RStrip(l:code)) != 0 54 | let l:codes = l:codes + [l:code] 55 | endif 56 | endfor 57 | let l:blocks = formatpythoncode#Seperateintoblocks(l:codes) 58 | let l:blocks = formatpythoncode#Trunctindent(l:blocks) 59 | let l:newcodes = [] 60 | for l:i in range(len(l:blocks)) 61 | let l:block = l:blocks[l:i] 62 | for l:index in range(0, len(l:block)-1) 63 | let l:tempcodeline = l:block[l:index] 64 | if l:index == 0 || repl#StartWith(a:pythonprogram, 'python') 65 | let l:newcodes = l:newcodes + [l:tempcodeline] 66 | continue 67 | else 68 | if repl#GetIndent(l:block[l:index - 1]) > repl#GetIndent(l:tempcodeline) 69 | let l:lineneedbs = repl#LStrip(l:tempcodeline) 70 | let l:bs_number = repl#GetIndent(l:block[l:index - 1]) - repl#GetIndent(l:tempcodeline) + 4 * formatpythoncode#AutoStop(l:block[l:index - 1], a:pythonprogram, a:version) 71 | for l:i in range(l:bs_number) 72 | let l:lineneedbs = "\" . l:lineneedbs 73 | endfor 74 | let l:newcodes = l:newcodes + [l:lineneedbs] 75 | else 76 | let l:newcodes = l:newcodes + [repl#LStrip(l:tempcodeline)] 77 | endif 78 | endif 79 | endfor 80 | if repl#StartWith(a:pythonprogram, 'python') || a:pythonprogram ==# 'ptpython' 81 | if repl#StartWithAny(l:block[0], ['def ', 'class ', 'for ', 'while ', 'try ', 'if ']) 82 | let l:newcodes = l:newcodes + [''] 83 | endif 84 | else 85 | if repl#StartWithAny(l:block[0], ['def ', 'class ', 'for ', 'while ', 'try ', 'if ']) 86 | if repl#GetIndent(l:block[-1]) - 4 * formatpythoncode#AutoStop(l:block[-1], 'ipython', a:version) == 0 87 | let l:newcodes = l:newcodes + ['', ''] 88 | else 89 | let l:newcodes = l:newcodes + [''] 90 | endif 91 | endif 92 | endif 93 | endfor 94 | return l:newcodes 95 | endfunction 96 | -------------------------------------------------------------------------------- /autoload/formatvimscript.vim: -------------------------------------------------------------------------------- 1 | function! formatvimscript#Format_to_repl(codes) 2 | let l:codes = [] 3 | for l:i in range(len(a:codes)) 4 | let l:code = a:codes[l:i] 5 | if len(repl#RStrip(l:code)) != 0 6 | let l:codes = l:codes + [repl#LStrip(l:code)] 7 | endif 8 | endfor 9 | return l:codes 10 | endfunction 11 | -------------------------------------------------------------------------------- /autoload/repl.vim: -------------------------------------------------------------------------------- 1 | function! repl#AsList(value) 2 | if type(a:value) == type([]) 3 | return a:value 4 | else 5 | return [a:value] 6 | end 7 | endfunction 8 | 9 | function! repl#GetConsoleName() 10 | return g:repl_console_name . string(tabpagenr()) 11 | endfunction 12 | 13 | function! repl#Trim(value) 14 | if has('python3') 15 | python3 << EOF 16 | import vim 17 | value = vim.eval("a:value").strip() 18 | EOF 19 | return py3eval("value") 20 | elseif has('python') 21 | python << EOF 22 | import vim 23 | value = vim.eval("a:value").strip() 24 | EOF 25 | return pyeval("value") 26 | else 27 | return trim(a:value) 28 | end 29 | endfunction 30 | 31 | function! repl#ReverseStr(string) 32 | pythonx << EOF 33 | import vim 34 | value = vim.eval("a:string")[::-1] 35 | EOF 36 | return pyxeval("value") 37 | endfunction 38 | 39 | function! repl#RStrip(string) 40 | return substitute(a:string, '\s*$', '', '') 41 | endfunction 42 | 43 | function! repl#LStrip(string) 44 | return substitute(a:string, '^\s*', '', '') 45 | endfunction 46 | 47 | function! repl#Strip(string) 48 | return repl#LStrip(repl#RStrip(a:string)) 49 | endfunction 50 | 51 | function! repl#GetIndent(string) 52 | let l:string = substitute(a:string, "\t", " ", "g") 53 | if repl#Trim(a:string) ==# '' 54 | return 9999 55 | else 56 | return len(a:string) - len(repl#LStrip(a:string)) 57 | endif 58 | endfunction 59 | 60 | function! repl#StartWith(string, substring) 61 | if strlen(a:string) < strlen(a:substring) 62 | return 0 63 | elseif a:string[0:(strlen(a:substring)-1)] ==# a:substring 64 | return 1 65 | else 66 | return 0 67 | endif 68 | endfunction 69 | 70 | function! repl#EndWith(string, substring) 71 | return repl#StartWith(repl#ReverseStr(a:string), repl#ReverseStr(a:substring)) 72 | endfunction 73 | 74 | function! repl#EndWithAny(string, substringlist) 75 | for l:substring in a:substringlist 76 | if repl#EndWith(a:string, l:substring) 77 | return 1 78 | endif 79 | endfor 80 | return 0 81 | endfunction 82 | 83 | function! repl#StartWithAny(string, substringlist) 84 | for l:substring in a:substringlist 85 | if repl#StartWith(a:string, l:substring) 86 | return 1 87 | endif 88 | endfor 89 | return 0 90 | endfunction 91 | 92 | function! repl#CurrentFilePath() 93 | return expand("%:p:h") 94 | endfunction 95 | 96 | function! repl#REPLGetName() 97 | if exists('t:REPL_OPEN_TERMINAL') 98 | return t:REPL_OPEN_TERMINAL 99 | elseif &buftype ==# 'terminal' 100 | return bufname('%')[1:] 101 | elseif has_key(g:repl_program, &filetype) 102 | let l:repl_options = g:repl_program[&filetype] 103 | if type(l:repl_options) == 1 104 | return l:repl_options 105 | else 106 | let l:count = len(l:repl_options) 107 | if l:count == 1 108 | return l:repl_options[0] 109 | elseif l:count > 1 110 | let l:choice = inputlist([ 'Select your REPL:' ] 111 | \ + map(copy(l:repl_options), '(v:key+1).". ".v:val')) - 1 112 | redraw 113 | if l:choice < 0 || l:choice >= l:count 114 | throw "Unexpected-input-received" 115 | else 116 | return l:repl_options[l:choice] 117 | endif 118 | endif 119 | endif 120 | elseif has_key(g:repl_program, 'default') 121 | let l:repl_options = g:repl_program['default'] 122 | if type(l:repl_options) == 3 123 | return l:repl_options[0] 124 | else 125 | return l:repl_options 126 | else 127 | return 'bash' 128 | endif 129 | endfunction 130 | 131 | function! repl#StringAfter(word, token) 132 | let l:loc = strridx(a:word, a:token) 133 | return a:word[(l:loc+1):] 134 | endfunction 135 | 136 | function! repl#REPLGetShortName() 137 | let l:name = repl#REPLGetName() 138 | let l:temp = split(repl#StringAfter(l:name, '/'), ' ')[0] 139 | if l:temp ==# 'ptpython' 140 | return 'ptpython' 141 | elseif l:temp ==# 'ipython' 142 | return 'ipython' 143 | elseif l:temp ==# 'ipython3' 144 | return 'ipython' 145 | elseif l:temp =~# '.*python.*' 146 | return 'python' 147 | else 148 | return l:temp 149 | endif 150 | endfunction 151 | 152 | function! repl#REPLWin32Return() 153 | let l:name = repl#REPLGetShortName() 154 | if has('win32') 155 | if l:name ==# 'ipython' 156 | return 0 157 | else 158 | return 1 159 | endif 160 | else 161 | return 0 162 | endif 163 | endfunction 164 | 165 | function! repl#REPLGetShell() 166 | if has_key(g:repl_program, 'default') 167 | return g:repl_program['default'] 168 | elseif has('win32') 169 | return 'cmd.exe' 170 | else 171 | return 'bash' 172 | endif 173 | endfunction 174 | 175 | function! repl#REPLGetExitCommand(...) 176 | if a:0 == 0 177 | let l:name = repl#REPLGetShortName() 178 | else 179 | let l:name = a:1 180 | end 181 | if has_key(g:repl_exit_commands, l:name) 182 | return g:repl_exit_commands[l:name] 183 | elseif has_key(g:repl_exit_commands, 'default') 184 | return g:repl_exit_commands['default'] 185 | else 186 | return 'exit' 187 | endif 188 | endfunction 189 | 190 | function! repl#REPLGoToWindowForBufferName(name) 191 | if bufwinnr(bufnr(a:name)) != -1 192 | exe bufwinnr(bufnr(a:name)) . 'wincmd w' 193 | return 1 194 | else 195 | return 0 196 | endif 197 | endfunction 198 | function! repl#REPLClose() 199 | if repl#REPLIsVisible() 200 | if index(split(repl#REPLGetName(), ' '), 'ipdb') != -1 || index(split(repl#REPLGetName(), ' '), 'pdb') != -1 201 | call term_sendkeys(repl#GetConsoleName(), "\\") 202 | call repl#Sends(['quit()'], ['ipdb>', 'pdb>']) 203 | else 204 | call repl#REPLGoToWindowForBufferName(repl#GetConsoleName()) 205 | if mode() ==# 'n' 206 | execute "normal! i" 207 | endif 208 | exe "call term_sendkeys('" . repl#GetConsoleName() . ''', "\\")' 209 | exe "call term_wait('" . repl#GetConsoleName() . ''', 50)' 210 | if repl#REPLIsVisible() 211 | if repl#REPLWin32Return() 212 | exe "call term_sendkeys('" . repl#GetConsoleName() . "', \"\\r\\n\")" 213 | else 214 | exe "call term_sendkeys('" . repl#GetConsoleName() . "', \"\\n\")" 215 | endif 216 | exe "call term_wait('" . repl#GetConsoleName() . ''', 50)' 217 | if repl#REPLWin32Return() 218 | exe "call term_sendkeys('" . repl#GetConsoleName() . "', \"\\r\\n\")" 219 | else 220 | exe "call term_sendkeys('" . repl#GetConsoleName() . "', \"\\n\")" 221 | endif 222 | exe "call term_wait('" . repl#GetConsoleName() . ''', 50)' 223 | if repl#REPLWin32Return() 224 | exe "call term_sendkeys('" . repl#GetConsoleName() . ''', "' . repl#REPLGetExitCommand() . '\r\n")' 225 | else 226 | exe "call term_sendkeys('" . repl#GetConsoleName() . ''', "' . repl#REPLGetExitCommand() . '\n")' 227 | endif 228 | exe "call term_wait('" . repl#GetConsoleName() . ''', 50)' 229 | exe "call term_sendkeys('" . repl#GetConsoleName() . ''', "' . '\")' 230 | endif 231 | let l:temp_return = "\n" 232 | if has('win32') 233 | let l:temp_return = "\r" 234 | endif 235 | if exists('g:REPL_VIRTUAL_ENVIRONMENT') 236 | call term_sendkeys(repl#GetConsoleName(), 'deactivate' . l:temp_return) 237 | call term_wait(repl#GetConsoleName(), 50) 238 | call term_sendkeys(repl#GetConsoleName(), repl#REPLGetExitCommand(repl#REPLGetShell()) . l:temp_return) 239 | call term_wait(repl#GetConsoleName(), 50) 240 | unlet g:REPL_VIRTUAL_ENVIRONMENT 241 | endif 242 | endif 243 | elseif repl#REPLIsHidden() 244 | call repl#REPLUnhide() 245 | call repl#REPLClose() 246 | return 247 | endif 248 | exe bufwinnr(g:repl_target_n) . 'wincmd w' 249 | unlet t:REPL_OPEN_TERMINAL 250 | endfunction 251 | 252 | function! repl#REPLHide() 253 | if repl#REPLIsVisible() 254 | call repl#REPLGoToWindowForBufferName(repl#GetConsoleName()) 255 | hide 256 | endif 257 | endfunction 258 | 259 | function! repl#REPLUnhide() 260 | if repl#REPLIsHidden() 261 | if g:repl_position == 0 262 | exe 'bo unhide' 263 | elseif g:repl_position == 1 264 | exe 'to unhide' 265 | elseif g:repl_position == 2 266 | exe 'vert unhide' 267 | else 268 | exe 'vert rightb unhide' 269 | endif 270 | endif 271 | endfunction 272 | 273 | function! repl#REPLOpen(...) 274 | if a:0 == 0 275 | unlet! t:REPL_OPEN_TERMINAL 276 | let t:REPL_OPEN_TERMINAL = repl#REPLGetName() 277 | else 278 | let t:REPL_OPEN_TERMINAL = join(a:000, ' ') 279 | endif 280 | let l:REPL_OPEN_TERMINAL = t:REPL_OPEN_TERMINAL 281 | exe 'autocmd bufenter * if (winnr("$") == 1 && (&buftype == ''terminal'') && bufexists(repl#GetConsoleName())) | q! | endif' 282 | if !executable(split(repl#REPLGetName(), ' ')[0]) 283 | echoerr 'The program ' . split(repl#REPLGetName(), ' ')[0] . ' is not executable.' 284 | endif 285 | if repl#REPLGetShortName() =~# '.*python.*' 286 | if repl#REPLGetShortName() == 'ipython' && !exists("g:repl_ipython_version") 287 | let temp = system(t:REPL_OPEN_TERMINAL . ' --version') 288 | "This truncation was removed in part of fixing Issue #148 289 | "I (shawsa) am not sure what purpose this served, and I can only 290 | "test this on my particular configuration. It doesn't seem to have 291 | "broken anything, but I'll leave the old code in in case it needs 292 | "to be reverted (without reverting the other code in this commit). 293 | let g:repl_ipython_version = temp 294 | "let g:repl_ipython_version = temp[0:2] 295 | endif 296 | for l:i in range(1, line('$')) 297 | if repl#StartWith(getline(l:i), '#REPLENV:') 298 | let g:REPL_VIRTUAL_ENVIRONMENT = repl#Strip(getline(l:i)[strlen('#REPLENV:')+1: ]) 299 | if repl#StartWith(getline(l:i+1), "#PYTHONPATH:") 300 | let l:REPL_OPEN_TERMINAL = repl#Strip(getline(l:i+1)[strlen('#PYTHONPATH:')+1: ]) 301 | endif 302 | if g:repl_position == 0 303 | if exists('g:repl_height') 304 | exe 'bo term ++close ++rows=' . float2nr(g:repl_height) . ' ' . repl#REPLGetShell() 305 | else 306 | exe 'bo term ++close ' . repl#REPLGetShell() 307 | endif 308 | elseif g:repl_position == 1 309 | if exists('g:repl_height') 310 | exe 'to term ++close ++rows=' . float2nr(g:repl_height) . ' ' . repl#REPLGetShell() 311 | else 312 | exe 'to term ++close ' . repl#REPLGetShell() 313 | endif 314 | elseif g:repl_position == 2 315 | if exists('g:repl_width') 316 | exe 'vert term ++close ++cols=' . float2nr(g:repl_width) . ' ' . repl#REPLGetShell() 317 | else 318 | exe 'vert term ++close ' . repl#REPLGetShell() 319 | endif 320 | else 321 | if exists('g:repl_width') 322 | exe 'vert rightb term ++close ++cols=' . float2nr(g:repl_width) . ' ' . repl#REPLGetShell() 323 | else 324 | exe 'vert rightb term ++close ' . repl#REPLGetShell() 325 | endif 326 | endif 327 | exe 'file ' . repl#GetConsoleName() 328 | exe 'setlocal noswapfile' 329 | if has('win32') 330 | let l:temp_return = "\r\n" 331 | else 332 | let l:temp_return = "\n" 333 | endif 334 | if repl#StartWith(g:REPL_VIRTUAL_ENVIRONMENT, "conda") 335 | call term_sendkeys(repl#GetConsoleName(), g:REPL_VIRTUAL_ENVIRONMENT . l:temp_return) 336 | else 337 | call term_sendkeys(repl#GetConsoleName(), 'source ' . g:REPL_VIRTUAL_ENVIRONMENT . l:temp_return) 338 | endif 339 | call term_wait(repl#GetConsoleName(), 100) 340 | call term_sendkeys(repl#GetConsoleName(), l:REPL_OPEN_TERMINAL . l:temp_return) 341 | return 342 | endif 343 | endfor 344 | if exists('g:repl_python_pre_launch_command') 345 | if g:repl_position == 0 346 | if exists('g:repl_height') 347 | exe 'bo term ++close ++rows=' . float2nr(g:repl_height) . ' ' . repl#REPLGetShell() 348 | else 349 | exe 'bo term ++close ' . repl#REPLGetShell() 350 | endif 351 | elseif g:repl_position == 1 352 | if exists('g:repl_height') 353 | exe 'to term ++close ++rows=' . float2nr(g:repl_height) . ' ' . repl#REPLGetShell() 354 | else 355 | exe 'to term ++close ' . repl#REPLGetShell() 356 | endif 357 | elseif g:repl_position == 2 358 | if exists('g:repl_width') 359 | exe 'vert term ++close ++cols=' . float2nr(g:repl_width) . ' ' . repl#REPLGetShell() 360 | else 361 | exe 'vert term ++close ' . repl#REPLGetShell() 362 | endif 363 | else 364 | if exists('g:repl_width') 365 | exe 'vert rightb term ++close ++cols=' . float2nr(g:repl_width) . ' ' . repl#REPLGetShell() 366 | else 367 | exe 'vert rightb term ++close ' . repl#REPLGetShell() 368 | endif 369 | endif 370 | exe 'file ' . repl#GetConsoleName() 371 | exe 'setlocal noswapfile' 372 | if has('win32') 373 | let l:temp_return = "\r" 374 | else 375 | let l:temp_return = "\n" 376 | endif 377 | if has('win32') 378 | if repl#StartWith(g:repl_python_pre_launch_command, 'conda ') 379 | let g:REPL_VIRTUAL_ENVIRONMENT = repl#Strip(g:repl_python_pre_launch_command[strlen('conda '):]) 380 | endif 381 | else 382 | if repl#StartWith(g:repl_python_pre_launch_command, 'source ') 383 | let g:REPL_VIRTUAL_ENVIRONMENT = repl#Strip(g:repl_python_pre_launch_command[strlen('source '):]) 384 | endif 385 | endif 386 | call term_sendkeys(repl#GetConsoleName(), g:repl_python_pre_launch_command . l:temp_return) 387 | call term_wait(repl#GetConsoleName(), 100) 388 | call term_sendkeys(repl#GetConsoleName(), l:REPL_OPEN_TERMINAL . l:temp_return) 389 | return 390 | endif 391 | endif 392 | if g:repl_position == 0 393 | if exists('g:repl_height') 394 | exe 'bo term ++close ++rows=' . float2nr(g:repl_height) . ' ' . repl#REPLGetName() 395 | else 396 | exe 'bo term ++close ' . repl#REPLGetName() 397 | endif 398 | elseif g:repl_position == 1 399 | if exists('g:repl_height') 400 | exe 'to term ++close ++rows=' . float2nr(g:repl_height) . ' ' . repl#REPLGetName() 401 | else 402 | exe 'to term ++close ' . repl#REPLGetName() 403 | endif 404 | elseif g:repl_position == 2 405 | if exists('g:repl_width') 406 | exe 'vert term ++close ++cols=' . float2nr(g:repl_width) . ' ' . repl#REPLGetName() 407 | else 408 | exe 'vert term ++close ' . repl#REPLGetName() 409 | endif 410 | else 411 | if exists('g:repl_width') 412 | exe 'vert rightb term ++close ++cols=' . float2nr(g:repl_width) . ' ' . repl#REPLGetName() 413 | else 414 | exe 'vert rightb term ++close ' . repl#REPLGetName() 415 | endif 416 | endif 417 | exe 'file ' . repl#GetConsoleName() 418 | exe 'setlocal noswapfile' 419 | endfunction 420 | 421 | function! repl#REPLIsHidden() 422 | if bufnr(repl#GetConsoleName()) == -1 423 | return 0 424 | elseif repl#REPLIsVisible() == 1 425 | return 0 426 | else 427 | return 1 428 | endif 429 | endfunction 430 | 431 | function! repl#REPLIsVisible() 432 | if bufwinnr(bufnr(repl#GetConsoleName())) != -1 433 | return 1 434 | else 435 | return 0 436 | endif 437 | endfunction 438 | 439 | function! repl#REPLToggle(...) 440 | if repl#REPLIsVisible() 441 | call repl#REPLClose() 442 | elseif repl#REPLIsHidden() 443 | call repl#REPLUnhide() 444 | else 445 | let l:cursor_pos = getpos('.') 446 | let g:repl_target_n = bufnr('') 447 | let g:repl_target_f = @% 448 | try 449 | call call(function('repl#REPLOpen'), a:000) 450 | catch /Unexpected-input-received/ 451 | echom "Unexpected input received, REPL launch abort." 452 | return 453 | endtry 454 | exe 'setlocal nonu' 455 | if g:repl_stayatrepl_when_open == 0 456 | exe bufwinnr(g:repl_target_n) . 'wincmd w' 457 | if exists('g:repl_predefine_' . repl#REPLGetShortName()) 458 | let l:command_dict = eval('g:repl_predefine_' . repl#REPLGetShortName()) 459 | let l:precode = [] 460 | for l:key in keys(l:command_dict) 461 | if search(l:key) != 0 462 | call add(l:precode, l:command_dict[l:key]) 463 | endif 464 | endfor 465 | call repl#Sends(l:precode, ['>>>', '...', 'ipdb>', 'pdb>']) 466 | endif 467 | if repl#REPLGetShortName() =~# '.*python.*' && g:repl_python_auto_import 468 | let l:code_tobe_sent = [] 469 | for l:line_number in range(1, line("$")) 470 | let l:gl = repl#Strip(getline(l:line_number)) 471 | if l:gl =~# '^import ' || l:gl =~# '^from .* import .*' || l:gl =~# '^sys\.path' 472 | let l:code_tobe_sent = l:code_tobe_sent + [l:gl] 473 | endif 474 | endfor 475 | let l:sn = repl#REPLGetShortName() 476 | if l:sn ==# 'ptpython' 477 | call repl#Sends(repl#ToREPLPythonCode(l:code_tobe_sent, 'ptpython'), ['\.\.\.', '>>>', 'ipdb>', 'pdb>']) 478 | elseif l:sn ==# 'ipython' 479 | call repl#Sends(repl#ToREPLPythonCode(l:code_tobe_sent, 'ipython'), ['\.\.\.', 'In']) 480 | elseif l:sn =~# 'python' || l:sn =~# 'python3' 481 | call repl#Sends(repl#ToREPLPythonCode(l:code_tobe_sent, 'python'), ['>>>', '...', 'ipdb>', 'pdb>']) 482 | endif 483 | endif 484 | call cursor(l:cursor_pos[1], l:cursor_pos[2]) 485 | endif 486 | endif 487 | endfunction 488 | 489 | function! repl#SendCurrentLine() 490 | if g:repl_unhide_when_send_lines && repl#REPLIsHidden() 491 | call repl#REPLUnhide() 492 | endif 493 | if bufexists(repl#GetConsoleName()) 494 | let l:cursor_pos = getpos('.') 495 | if repl#REPLWin32Return() 496 | let l:code_tobe_sent = getline('.') . "\r\n" 497 | else 498 | let l:code_tobe_sent = getline('.') . "\n" 499 | endif 500 | if repl#REPLGetShortName() =~# '.*python.*' 501 | if exists('g:repl_auto_sends') && repl#StartWithAny(repl#Trim(getline('.')), g:repl_auto_sends) 502 | let l:end_line_number = repl#SendWholeBlock() 503 | " if g:repl_cursor_down 504 | " call cursor(l:end_line_number + 1, l:cursor_pos[2]) 505 | " endif 506 | if g:repl_cursor_down 507 | let l:next_line_number = l:end_line_number + 1 508 | while l:next_line_number <= line("$") && (repl#Strip(getline(l:next_line_number)) == "" || repl#StartWith(repl#Strip(getline(l:next_line_number)), "#")) 509 | let l:next_line_number = l:next_line_number + 1 510 | endwhile 511 | call cursor(l:next_line_number, l:cursor_pos[2]) 512 | endif 513 | return 514 | endif 515 | if exists('g:repl_auto_sends') && repl#EndWith(repl#RStrip(getline(".")), "\\") 516 | let l:end_line_number = repl#SendWholeBlock() 517 | if g:repl_cursor_down 518 | let l:next_line_number = l:end_line_number + 1 519 | while l:next_line_number <= line("$") && (repl#Strip(getline(l:next_line_number)) == "" || repl#StartWith(repl#Strip(getline(l:next_line_number)), "#")) 520 | let l:next_line_number = l:next_line_number + 1 521 | endwhile 522 | call cursor(l:next_line_number, l:cursor_pos[2]) 523 | endif 524 | return 525 | endif 526 | if exists('g:repl_python_auto_send_unfinish_line') && !repl#IsCodeFinish(repl#Strip(getline("."))) 527 | let l:end_line_number = repl#SendCompleteLine() 528 | if g:repl_cursor_down 529 | let l:next_line_number = l:end_line_number + 1 530 | while l:next_line_number <= line("$") && (repl#Strip(getline(l:next_line_number)) == "" || repl#StartWith(repl#Strip(getline(l:next_line_number)), "#")) 531 | let l:next_line_number = l:next_line_number + 1 532 | endwhile 533 | call cursor(l:next_line_number, l:cursor_pos[2]) 534 | endif 535 | return 536 | endif 537 | if repl#REPLGetShortName() ==# 'ipython' 538 | let l:terminalline = repl#GetTerminalLine() 539 | if repl#StartWith(l:terminalline, "In [") 540 | let l:code_tobe_sent = repl#LStrip(l:code_tobe_sent) 541 | else 542 | let l:bs_number = len(l:terminalline) - len(repl#RStrip(l:terminalline)) - 2 543 | let l:code_tobe_sent = repeat("\", l:bs_number) . l:code_tobe_sent 544 | endif 545 | elseif repl#REPLGetShortName() ==# 'ptpython' 546 | let l:terminalline = repl#GetTerminalLine() 547 | let l:bs_number = len(l:terminalline) - len(repl#RStrip(l:terminalline)) - 2 548 | let l:code_tobe_sent = repeat("\", l:bs_number) . l:code_tobe_sent 549 | elseif repl#REPLGetShortName() ==# 'python' || repl#REPLGetShortName() ==# 'python2' || repl#REPLGetShortName() ==# 'python3' 550 | let l:terminalline = repl#GetTerminalLine() 551 | if repl#StartWith(l:terminalline, '>>> ') 552 | let l:code_tobe_sent = repl#LStrip(l:code_tobe_sent) 553 | endif 554 | endif 555 | endif 556 | if repl#REPLGetShortName() ==# "ipython" 557 | call repl#Sends(repl#ToREPLPythonCode([l:code_tobe_sent], 'ipython'), ['\.\.\.', 'In']) 558 | else 559 | call term_sendkeys(repl#GetConsoleName(), l:code_tobe_sent) 560 | endif 561 | call term_wait(repl#GetConsoleName(), 50) 562 | if g:repl_cursor_down 563 | " call cursor(l:cursor_pos[1] + 1, l:cursor_pos[2]) 564 | let l:next_line_number = l:cursor_pos[1] + 1 565 | while l:next_line_number <= line("$") && (repl#Strip(getline(l:next_line_number)) == "" || repl#StartWith(repl#Strip(getline(l:next_line_number)), "#")) 566 | let l:next_line_number = l:next_line_number + 1 567 | endwhile 568 | call cursor(l:next_line_number, l:cursor_pos[2]) 569 | endif 570 | endif 571 | endfunction 572 | 573 | function! repl#SendRHSofCurrentLine() 574 | if g:repl_unhide_when_send_lines && repl#REPLIsHidden() 575 | call repl#REPLUnhide() 576 | endif 577 | if bufexists(repl#GetConsoleName()) 578 | let l:cursor_pos = getpos('.') 579 | if repl#REPLWin32Return() 580 | let l:code_tobe_sent = getline('.') . "\r\n" 581 | else 582 | let l:code_tobe_sent = getline('.') . "\n" 583 | endif 584 | if repl#REPLGetShortName() =~# '.*python.*' 585 | if repl#REPLGetShortName() ==# 'ipython' 586 | let l:terminalline = repl#GetTerminalLine() 587 | if repl#StartWith(l:terminalline, "In [") 588 | let l:code_tobe_sent = repl#LStrip(l:code_tobe_sent) 589 | else 590 | let l:bs_number = len(l:terminalline) - len(repl#RStrip(l:terminalline)) - 2 591 | let l:code_tobe_sent = repeat("\", l:bs_number) . l:code_tobe_sent 592 | endif 593 | elseif repl#REPLGetShortName() ==# 'ptpython' 594 | let l:terminalline = repl#GetTerminalLine() 595 | let l:bs_number = len(l:terminalline) - len(repl#RStrip(l:terminalline)) - 2 596 | let l:code_tobe_sent = repeat("\", l:bs_number) . l:code_tobe_sent 597 | elseif repl#REPLGetShortName() ==# 'python' || repl#REPLGetShortName() ==# 'python2' || repl#REPLGetShortName() ==# 'python3' 598 | let l:terminalline = repl#GetTerminalLine() 599 | if repl#StartWith(l:terminalline, '>>> ') 600 | let l:code_tobe_sent = repl#LStrip(l:code_tobe_sent) 601 | endif 602 | endif 603 | endif 604 | if repl#REPLGetShortName() ==# "ipython" 605 | call repl#Sends([repl#RHSPythonCode(l:code_tobe_sent)], ['\.\.\.', 'In']) 606 | else 607 | call term_sendkeys(repl#GetConsoleName(), repl#RHSPythonCode(l:code_tobe_sent)) 608 | endif 609 | call term_wait(repl#GetConsoleName(), 50) 610 | if g:repl_cursor_down 611 | let l:next_line_number = l:cursor_pos[1] + 1 612 | while l:next_line_number <= line("$") && (repl#Strip(getline(l:next_line_number)) == "" || repl#StartWith(repl#Strip(getline(l:next_line_number)), "#")) 613 | let l:next_line_number = l:next_line_number + 1 614 | endwhile 615 | call cursor(l:next_line_number, l:cursor_pos[2]) 616 | endif 617 | endif 618 | endfunction 619 | 620 | function! repl#ToVimScript(lines) 621 | return formatvimscript#Format_to_repl(a:lines) 622 | endfunction 623 | 624 | function! repl#IsCodeFinish(code) 625 | if has('python3') 626 | python3 << EOF 627 | import vim 628 | import sys 629 | # sys.path.append(vim.eval("g:REPLVIM_PATH") + "autoload/") 630 | import replpython 631 | code = vim.eval("a:code") 632 | if isinstance(code, list): 633 | finish_flag = int(replpython.getpythonindent(code)[1]) 634 | else: 635 | finish_flag = int(replpython.getpythonindent([code])[1]) 636 | EOF 637 | return py3eval("finish_flag") 638 | elseif has('python') 639 | python << EOF 640 | import vim 641 | import sys 642 | # sys.path.append(vim.eval("g:REPLVIM_PATH") + "autoload/") 643 | import replpython 644 | code = vim.eval("a:code") 645 | if isinstance(code, list): 646 | finish_flag = int(replpython.getpythonindent(code)[1]) 647 | else: 648 | finish_flag = int(replpython.getpythonindent([code])[1]) 649 | EOF 650 | return pyeval("finish_flag") 651 | else 652 | return 1 653 | end 654 | endfunction 655 | 656 | function! repl#RHSPythonCode(line) 657 | if has('python3') 658 | python3 << EOF 659 | import vim 660 | import re 661 | code = vim.eval("a:line").strip() 662 | ret = code 663 | regex = re.compile(r"[\w.]+[ ]*=[ ]*(.+)") 664 | if code.startswith("return "): 665 | ret = code[len("return "):].strip() 666 | elif code.startswith("yield "): 667 | ret = code[len("yield "):].strip() 668 | else: 669 | m = regex.fullmatch(code) 670 | if m: 671 | ret = m.group(1) 672 | EOF 673 | return py3eval('ret') 674 | elseif has('python') 675 | python << EOF 676 | import vim 677 | import re 678 | code = vim.eval("a:line").strip() 679 | ret = code 680 | regex = re.compile(r"[\w.]+[ ]*=[ ]*(.+)") 681 | if code.startswith("return "): 682 | ret = code[len("return "):].strip() 683 | elif code.startswith("yield "): 684 | ret = code[len("yield "):].strip() 685 | else: 686 | m = regex.fullmatch(code) 687 | if m: 688 | ret = m.group(1) 689 | EOF 690 | return pyeval('ret') 691 | endif 692 | endfunction 693 | 694 | function! repl#ToREPLPythonCode(lines, pythonprogram) 695 | if exists('g:repl_ipython_version') 696 | let l:version = g:repl_ipython_version 697 | else 698 | let l:version = -1 699 | endif 700 | if !has('python3') && !has('python') || g:repl_vimscript_engine 701 | if a:pythonprogram ==# 'ipython' 702 | let l:temp = formatpythoncode#Format_to_repl(a:lines, 'python', '') 703 | return ['%autoindent'] + l:temp + ['%autoindent'] 704 | endif 705 | return formatpythoncode#Format_to_repl(a:lines, a:pythonprogram, l:version) 706 | elseif has('python3') 707 | python3 << EOF 708 | import vim 709 | import sys 710 | # sys.path.append(vim.eval("g:REPLVIM_PATH") + "autoload/") 711 | import formatpythoncode 712 | codes = vim.eval("a:lines") 713 | pythonprogram = vim.eval("a:pythonprogram") 714 | mergeunfinishline = int(vim.eval("g:repl_python_automerge")) 715 | version = vim.eval("l:version") 716 | newcodes = formatpythoncode.format_to_repl(codes, pythonprogram, mergeunfinishline, version, vim.eval("repl#CurrentFilePath()")) 717 | EOF 718 | return py3eval('newcodes') 719 | elseif has('python') 720 | python << EOF 721 | import vim 722 | import sys 723 | # sys.path.append(vim.eval("g:REPLVIM_PATH") + "autoload/") 724 | import formatpythoncode 725 | codes = vim.eval("a:lines") 726 | pythonprogram = vim.eval("a:pythonprogram") 727 | mergeunfinishline = int(vim.eval("g:repl_python_automerge")) 728 | version = vim.eval("l:version") 729 | newcodes = formatpythoncode.format_to_repl(codes, pythonprogram, mergeunfinishline, version, vim.eval("repl#CurrentFilePath()")) 730 | EOF 731 | return pyeval('newcodes') 732 | endif 733 | endfunction 734 | 735 | function! repl#GetTerminalLine() abort 736 | let l:tl = term_getline(repl#GetConsoleName(), '.') 737 | " return repl#RStrip(l:tl) 738 | return l:tl 739 | endfunction 740 | 741 | function! repl#GetCurrentLineNumber() abort 742 | return term_getcursor(repl#GetConsoleName())[0] 743 | endfunction 744 | 745 | function! repl#CheckInputState() 746 | let l:tl = repl#GetTerminalLine() 747 | if g:currentrepltype ==# 'ipython' && (!exists("g:repl_tasks") || (g:taskprocess == 0 || g:repl_tasks[g:taskprocess-1] ==# '') && (g:taskprocess == len(g:repl_tasks) || (g:repl_tasks[g:taskprocess] !=# '')) && (len(g:repl_tasks) > 1)) 748 | if match(l:tl, 'In') != -1 749 | return 1 750 | else 751 | return 0 752 | endif 753 | endif 754 | for l:symbol in g:waitforsymbols 755 | if match(l:tl, l:symbol) != -1 756 | return 1 757 | endif 758 | endfor 759 | return 0 760 | endfunction 761 | 762 | function! repl#Sends(tasks, symbols) 763 | " echom a:tasks 764 | if len(a:tasks) == 0 765 | return 766 | end 767 | if exists("g:repl_tasks") 768 | let g:repl_tasks = g:repl_tasks + a:tasks 769 | return 770 | endif 771 | let g:repl_tasks = a:tasks 772 | let g:waitforsymbols = repl#AsList(a:symbols) 773 | let g:taskprocess = 0 774 | let g:currentlinenumber = -1 775 | let g:currentrepltype = repl#REPLGetShortName() 776 | if repl#REPLWin32Return() 777 | let g:term_send_task_codes = ['LABEL Start', 'sleep 10', 'wait repl#CheckInputState()', 'call term_sendkeys("' . repl#GetConsoleName() . '", g:repl_tasks[g:taskprocess] . "\r\n")', 'let g:taskprocess = g:taskprocess + 1', 'if g:taskprocess == len(g:repl_tasks)', 'unlet g:repl_tasks', 'return', 'endif', 'GOTO Start'] 778 | else 779 | let g:term_send_task_codes = ['LABEL Start', 'sleep 10', 'wait repl#CheckInputState()', 'call term_sendkeys("' . repl#GetConsoleName() . '", g:repl_tasks[g:taskprocess] . "\n")', 'let g:taskprocess = g:taskprocess + 1', 'if g:taskprocess == len(g:repl_tasks)', 'unlet g:repl_tasks','return', 'endif', 'GOTO Start'] 780 | endif 781 | if exists("g:repl_output_copy_to_register") && repl#REPLGetShortName() ==# "ipython" 782 | let g:term_send_task_codes = g:term_send_task_codes[:-4] + ["sleep 300", "wait repl#CheckInputState()", "call repl#GetTerminalLastOutput('" . g:repl_output_copy_to_register . "')"] + g:term_send_task_codes[-3:] 783 | endif 784 | " echom g:term_send_task_codes 785 | call async#AsyncCodeRun(g:term_send_task_codes, "term_send_task") 786 | " endif 787 | endfunction 788 | 789 | function! repl#WaitForSymbolsHandler(channel) 790 | let l:tl = repl#GetTerminalLine() 791 | if index(s:waitforsymbols, l:tl) == -1 792 | call repl#WAITFORSYMBOLS() 793 | return 794 | else 795 | return 796 | endif 797 | endfunction 798 | 799 | function! repl#WAITFORSYMBOLS() abort 800 | call job_start('sleep 0.03s', {'close_cb': 'repl#WaitForSymbolsHandler'}) 801 | endfunction 802 | 803 | function! repl#WaitFor(symbols) 804 | let s:waitforsymbols = repl#AsList(a:symbols) 805 | call repl#WaitForSymbolsHandler(0) 806 | endfunction 807 | 808 | function! repl#SendChunkLines() range abort 809 | if g:repl_unhide_when_send_lines && repl#REPLIsHidden() 810 | call repl#REPLUnhide() 811 | endif 812 | if a:firstline == a:lastline 813 | let [l:line_start, l:column_start] = getpos("'<")[1:2] 814 | let [l:line_end, l:column_end] = getpos("'>")[1:2] 815 | let l:currentline = getline(a:firstline) 816 | if l:column_end - l:column_start + 1 >= len(l:currentline) 817 | call repl#SendLines(a:firstline, a:firstline) 818 | else 819 | let l:selected_content = l:currentline[l:column_start - 1 : l:column_end - 1] 820 | let l:selected_content = repl#Strip(l:selected_content) 821 | let l:repl_program = repl#REPLGetShortName() 822 | if has_key(g:repl_sendvariable_template, l:repl_program) 823 | let l:template = g:repl_sendvariable_template[l:repl_program] 824 | if repl#REPLWin32Return() 825 | call term_sendkeys(repl#GetConsoleName(), substitute(l:template, '', l:selected_content, '') . "\r\n") 826 | else 827 | call term_sendkeys(repl#GetConsoleName(), substitute(l:template, '', l:selected_content, '') . "\n") 828 | endif 829 | else 830 | if repl#REPLWin32Return() 831 | call term_sendkeys(repl#GetConsoleName(), l:selected_content . "\r\n") 832 | else 833 | call term_sendkeys(repl#GetConsoleName(), l:selected_content . "\n") 834 | endif 835 | endif 836 | endif 837 | else 838 | call repl#SendLines(a:firstline, a:lastline) 839 | endif 840 | if g:repl_cursor_down 841 | call cursor(a:lastline+1, 0) 842 | endif 843 | endfunction 844 | 845 | function! repl#SendLines(first, last) abort 846 | if bufexists(repl#GetConsoleName()) 847 | let l:firstline = a:first 848 | while(l:firstline <= a:last && strlen(getline(l:firstline)) == 0) 849 | let l:firstline = l:firstline + 1 850 | endwhile 851 | let l:sn = repl#REPLGetShortName() 852 | if l:sn ==# 'ptpython' 853 | call repl#Sends(repl#ToREPLPythonCode(getline(l:firstline, a:last), 'ptpython'), ['\.\.\.', '>>>', 'ipdb>', 'pdb>']) 854 | elseif l:sn ==# 'ipython' 855 | call repl#Sends(repl#ToREPLPythonCode(getline(l:firstline, a:last), 'ipython'), ['\.\.\.', 'In']) 856 | elseif l:sn =~# 'python' || l:sn =~# 'python3' 857 | call repl#Sends(repl#ToREPLPythonCode(getline(l:firstline, a:last), 'python'), ['>>>', '...', 'ipdb>', 'pdb>']) 858 | elseif l:sn ==# 'vim' 859 | call repl#Sends(repl#ToVimScript(getline(l:firstline, a:last)), [':']) 860 | elseif has_key(g:repl_input_symbols, l:sn) 861 | call repl#Sends(add(getline(l:firstline, a:last), ''), g:repl_input_symbols[l:sn]) 862 | else 863 | let l:fl = getline(l:firstline) 864 | let l:i = 0 865 | while(l:i < strlen(l:fl) && l:fl[l:i] ==# ' ') 866 | let l:i = l:i + 1 867 | endwhile 868 | for line in getline(l:firstline, a:last) 869 | let l:deletespaceline = line[l:i:] 870 | if repl#REPLWin32Return() 871 | exe "call term_sendkeys('" . repl#GetConsoleName() . ''', l:deletespaceline . "\r\n")' 872 | else 873 | exe "call term_sendkeys('" . repl#GetConsoleName() . ''', l:deletespaceline . "\n")' 874 | endif 875 | exe 'call term_wait("' . repl#GetConsoleName() . '", 50)' 876 | endfor 877 | if repl#REPLWin32Return() 878 | exe "call term_sendkeys('" . repl#GetConsoleName() . ''', "\r\n")' 879 | else 880 | exe "call term_sendkeys('" . repl#GetConsoleName() . ''', "\n")' 881 | endif 882 | endif 883 | endif 884 | endfunction 885 | 886 | function! repl#SendAll() abort 887 | call repl#SendLines(1, line('$')) 888 | endfunction 889 | 890 | function! repl#SendSession() abort 891 | if g:repl_unhide_when_send_lines && repl#REPLIsHidden() 892 | call repl#REPLUnhide() 893 | endif 894 | call cursor(0, col("$")) 895 | let g:repl_code_block_begin = get(g:repl_code_block_fences, &ft, '# %%') 896 | if exists("g:repl_code_block_fences_end") && has_key(g:repl_code_block_fences_end, &ft) 897 | let g:repl_code_block_end = g:repl_code_block_fences_end[&ft] 898 | else 899 | let g:repl_code_block_end = g:repl_code_block_begin 900 | endif 901 | let l:begin_line_number = search('^' . g:repl_code_block_begin, 'bnW') 902 | if l:begin_line_number == 0 903 | let l:begin_line_number = 1 904 | endif 905 | let l:end_line_number = search('^' . g:repl_code_block_end, 'nW') 906 | if l:end_line_number == 0 907 | let l:end_line_number = line("$") 908 | endif 909 | if l:begin_line_number == l:end_line_number 910 | echo "No more blocks below." 911 | return 912 | endif 913 | if g:repl_cursor_down 914 | call cursor(l:end_line_number+1, 0) 915 | endif 916 | if getline(l:begin_line_number) =~ '^' . g:repl_code_block_begin 917 | let l:begin_line_number += 1 918 | endif 919 | if getline(l:end_line_number) =~ '^' . g:repl_code_block_end 920 | let l:end_line_number -= 1 921 | endif 922 | if l:begin_line_number <= l:end_line_number 923 | call repl#SendLines(l:begin_line_number, l:end_line_number) 924 | endif 925 | endfunction 926 | 927 | function! repl#SendWholeBlock() abort 928 | let l:begin_line = getline('.') 929 | let l:begin_line_number = line('.') 930 | let l:begin_indent = repl#GetIndent(l:begin_line) 931 | let l:end_line_number = line('$') 932 | for i in range(line('.') + 1, line('$')) 933 | if repl#GetIndent(getline(i)) <= l:begin_indent 934 | if repl#GetIndent(getline(i)) == l:begin_indent && repl#StartWithAny(repl#LStrip(getline(i)), ['else:', 'elif ', 'except:', 'finally:', 'except ']) 935 | continue 936 | end 937 | if i == l:begin_line_number + 1 && repl#StartWith(repl#LStrip(l:begin_line), "@") && repl#StartWithAny(repl#LStrip(getline(i)), ['def ', 'class ']) 938 | continue 939 | endif 940 | let l:end_line_number = i - 1 941 | break 942 | endif 943 | endfor 944 | call repl#SendLines(l:begin_line_number, l:end_line_number) 945 | return l:end_line_number 946 | endfunction 947 | 948 | function! repl#SendCompleteLine() abort 949 | let l:begin_line = getline('.') 950 | let l:begin_line_number = line('.') 951 | let l:end_line_number = line('$') 952 | let l:codes = [getline('.')] 953 | for i in range(line('.') + 1, line('$')) 954 | let l:codes = l:codes + [getline(i)] 955 | if repl#IsCodeFinish(l:codes) 956 | let l:end_line_number = i 957 | break 958 | endif 959 | if i > line('.') + 100 960 | let l:end_line_number = l:begin_line_number 961 | break 962 | endif 963 | endfor 964 | call repl#SendLines(l:begin_line_number, l:end_line_number) 965 | return l:end_line_number 966 | endfunction 967 | 968 | function! repl#GetTerminalContent() abort 969 | return getbufline(repl#GetConsoleName(), max([1, line("$", bufwinid(repl#GetConsoleName())) - 300]), "$") 970 | endfunction 971 | 972 | function! repl#GetTerminalLastOutput(...) abort 973 | let l:terminal_content = repl#GetTerminalContent() 974 | try 975 | if has('python3') 976 | python3 << EOF 977 | import vim 978 | # sys.path.append(vim.eval("g:REPLVIM_PATH") + "autoload/") 979 | from replpython import GetLastOutput 980 | terminal_content = vim.eval("l:terminal_content") 981 | last_out = GetLastOutput(terminal_content, "ipython") 982 | EOF 983 | if a:0 == 1 984 | try 985 | execute "let @" . a:1 . " = '" . py3eval("last_out") . "'" 986 | catch /.*/ 987 | echom v:exception 988 | endtry 989 | endif 990 | elseif has('python') 991 | python << EOF 992 | import vim 993 | # sys.path.append(vim.eval("g:REPLVIM_PATH") + "autoload/") 994 | from replpython import GetLastOutput 995 | terminal_content = vim.eval("l:terminal_content") 996 | last_out = GetLastOutput(terminal_content, "ipython") 997 | EOF 998 | if a:0 == 1 999 | try 1000 | execute "let @" . a:1 . " = '" . pyeval("last_out") . "'" 1001 | catch /.*/ 1002 | echom v:exception 1003 | endtry 1004 | endif 1005 | endif 1006 | catch /.*/ 1007 | echo 'Something went wrong, but I do not know what' 1008 | endtry 1009 | endfunction 1010 | 1011 | function! repl#REPLDebug() abort 1012 | echo "VIM-REPL, last update: 2019.8.23" 1013 | if has('nvim') 1014 | echoerr "this plugin dosen't work on neovim. Please use vim >= 8.1 instead." 1015 | endif 1016 | if has('win32') 1017 | let l:os = 'Windows' 1018 | else 1019 | let l:os = substitute(system('uname'), "\n", "", "") 1020 | endif 1021 | echo 'Operation System: ' . l:os 1022 | echo 'Support python3: ' . has('python3') 1023 | echo 'Support python: ' . has('python') 1024 | echo 'has +terminal: ' . has('terminal') 1025 | echo 'has +timers: ' . has('timers') 1026 | if ! has('python3') && ! has('python') && ! g:repl_vimscript_engine 1027 | echoerr "g:repl_vimscript_engine should be set to 1 for vim not supported with python or python3" 1028 | echoerr 'you should add `let g:repl_vimscript_engine = 1` to vimrc' 1029 | endif 1030 | if has('python3') 1031 | python3 << EOF 1032 | import sys 1033 | print(sys.version) 1034 | print(sys.path) 1035 | EOF 1036 | elseif has('python') 1037 | python << EOF 1038 | import sys 1039 | print sys.version 1040 | print sys.path 1041 | EOF 1042 | endif 1043 | echo 'REPL program:' 1044 | echo g:repl_program 1045 | for l:file in keys(g:repl_program) 1046 | let l:pros = g:repl_program[l:file] 1047 | if type(l:pros) == 3 1048 | for l:pro in l:pros 1049 | if !executable(split(l:pro, ' ')[0]) 1050 | echo split(l:pro, ' ')[0] . ' for ' . l:file . ' is not executable.' 1051 | endif 1052 | endfor 1053 | elseif type(l:pros) == 1 1054 | let l:pro = l:pros 1055 | if !executable(split(l:pro, ' ')[0]) 1056 | echo split(l:pro, ' ')[0] . ' for ' . l:file . ' is not executable.' 1057 | endif 1058 | endif 1059 | endfor 1060 | unlet! t:REPL_OPEN_TERMINAL 1061 | try 1062 | let t:REPL_OPEN_TERMINAL = repl#REPLGetName() 1063 | catch /Unexpected-input-received/ 1064 | echom "Unexpected input received, REPL Debug abort." 1065 | return 1066 | endtry 1067 | if repl#REPLGetShortName() == 'ipython' 1068 | if !exists("g:repl_ipython_version") 1069 | let temp = system(t:REPL_OPEN_TERMINAL . ' --version') 1070 | let g:repl_ipython_version = temp[0:2] 1071 | echo "ipython version: " . temp 1072 | endif 1073 | echo "setted ipython version" . g:repl_ipython_version 1074 | if g:repl_ipython_version == '7.0' 1075 | echoerr "This plugin cannot work on ipython 7.01. Please use ipython >= 7.1.1" 1076 | endif 1077 | endif 1078 | echo 'REPL exit commands:' 1079 | echo g:repl_exit_commands 1080 | echo 'Current File Type: ' . &filetype 1081 | echo 'Current Type: ' . repl#REPLGetName() 1082 | echo 'Current Exit Commands: ' . repl#REPLGetExitCommand() 1083 | endfunction 1084 | -------------------------------------------------------------------------------- /ftplugin/perl/psh: -------------------------------------------------------------------------------- 1 | #! /usr/bin/perl 2 | 3 | print "In : "; 4 | while (<>) { 5 | chomp; 6 | my $result = eval; 7 | print "Out: $result\n"; 8 | print "In: "; 9 | } 10 | -------------------------------------------------------------------------------- /ftplugin/python/python-repl.vim: -------------------------------------------------------------------------------- 1 | if !exists('g:REPLPythonLoaded') 2 | let g:REPLPythonLoaded = 1 3 | else 4 | finish 5 | endif 6 | 7 | function! s:REPLDebugRunAsync() abort 8 | let l:code = ["wait repl#Strip(repl#GetTerminalLine()) == 'ipdb>'", 'call term_sendkeys("' . repl#GetConsoleName() . '", "c\n")', "sleep 20ms", "wait repl#Strip(repl#GetTerminalLine()) == 'ipdb>'", 'call g:REPLDebugMoveCursor()'] 9 | call async#AsyncCodeRun(l:code, 'REPLDebugRunAsync') 10 | endfunction 11 | 12 | function! s:REPLDebugRun() abort 13 | if repl#REPLIsVisible() 14 | if repl#Strip(repl#GetTerminalLine()) != 'ipdb>' 15 | call term_sendkeys(repl#GetConsoleName(), "\n") 16 | call term_wait(repl#GetConsoleName(), 50) 17 | endif 18 | call s:REPLDebugRunAsync() 19 | else 20 | call s:REPLDebugIPDB() 21 | call term_wait(repl#GetConsoleName(), 50) 22 | call s:REPLDebugRun() 23 | endif 24 | endfunction 25 | 26 | function! g:REPLDebugMoveCursor() abort 27 | for l:currentlinenumber in range(repl#GetCurrentLineNumber(), 1, -1) 28 | let l:t = term_getline(repl#GetConsoleName(), l:currentlinenumber) 29 | if stridx(l:t, '>') == 0 30 | let l:t = l:t[2:] 31 | let l:i = stridx(l:t, '(') 32 | let l:j = l:currentlinenumber 33 | while l:i == -1 34 | let l:j = l:j + 1 35 | let l:nextline = term_getline(repl#GetConsoleName(), l:j) 36 | let l:t = l:t . l:nextline 37 | let l:i = stridx(l:t, '(') 38 | endwhile 39 | let l:filefullpath = l:t[0:(l:i - 1)] 40 | let l:linenumber = str2nr(l:t[(l:i+1):]) 41 | if l:filefullpath !=# expand('%:p') && l:filefullpath[0] ==# '/' 42 | silent exe 'edit ' . l:filefullpath 43 | endif 44 | if l:linenumber != line('.') 45 | call cursor(l:linenumber, 1) 46 | endif 47 | break 48 | endif 49 | endfor 50 | endfunction 51 | 52 | function! s:REPLDebugN() abort 53 | if !repl#REPLIsVisible() 54 | return 55 | endif 56 | let l:code = ['if repl#Strip(repl#GetTerminalLine()) != "ipdb>"', 'call term_sendkeys("' . repl#GetConsoleName() . '", "\n")', 'endif', 'call term_sendkeys("' . repl#GetConsoleName() . '", "n\n")', 'sleep 20ms', 'wait repl#Strip(repl#GetTerminalLine()) == "ipdb>"', 'call g:REPLDebugMoveCursor()'] 57 | call async#AsyncCodeRun(l:code, "REPLDebugN") 58 | endfunction 59 | 60 | function! s:REPLDebugU() abort 61 | if !repl#REPLIsVisible() 62 | return 63 | endif 64 | let l:code = ['if repl#Strip(repl#GetTerminalLine()) != "ipdb>"', 'call term_sendkeys("' . repl#GetConsoleName() . '", "\n")', 'endif', 'call term_sendkeys("' . repl#GetConsoleName() . '", "u\n")', 'sleep 20ms', 'wait repl#Strip(repl#GetTerminalLine()) == "ipdb>"', 'call g:REPLDebugMoveCursor()'] 65 | call async#AsyncCodeRun(l:code, "REPLDebugU") 66 | endfunction 67 | 68 | function! s:REPLDebugS() abort 69 | if !repl#REPLIsVisible() 70 | return 71 | endif 72 | let l:code = ['if repl#Strip(repl#GetTerminalLine()) != "ipdb>"', 'call term_sendkeys("' . repl#GetConsoleName() . '", "\n")', 'endif', 'call term_sendkeys("' . repl#GetConsoleName() . '", "s\n")', 'sleep 20ms', 'wait repl#Strip(repl#GetTerminalLine()) == "ipdb>"', 'call g:REPLDebugMoveCursor()'] 73 | call async#AsyncCodeRun(l:code, "REPLDebugS") 74 | endfunction 75 | 76 | function! s:REPLDebugStopAtCurrentLine(...) abort 77 | if repl#REPLIsVisible() 78 | let l:code = ['if repl#Strip(repl#GetTerminalLine()) != "ipdb>"', 'call term_sendkeys("' . repl#GetConsoleName() . '", "\n")', 'endif', 'call term_sendkeys("' . repl#GetConsoleName() . '", "tbreak ' . line('.') . '\n")', 'sleep 20ms', 'call term_sendkeys("' . repl#GetConsoleName() . '", "c\n")', 'sleep 20', 'wait repl#Strip(repl#GetTerminalLine()) == "ipdb>"', 'call g:REPLDebugMoveCursor()'] 79 | call async#AsyncCodeRun(l:code, "REPLDebugStopAtCurrentLine") 80 | else 81 | call s:REPLDebugIPDB() 82 | call call(function('s:REPLDebugStopAtCurrentLine'), a:000) 83 | endif 84 | endfunction 85 | 86 | function! s:REPLDebugIPDB() abort 87 | if repl#REPLIsVisible() 88 | return 89 | else 90 | let g:repl_target_n = bufnr('') 91 | let g:repl_target_f = @% 92 | " call repl#REPLOpen('python3 -m ipdb %') 93 | if !has_key(g:repl_program, 'python-debug') 94 | echo "please specify debug procedure for python" 95 | echo "for example: adding `'python-debug': 'python3 -m ipdb'` to g:repl_program" 96 | endif 97 | call repl#REPLOpen(g:repl_program['python-debug'] . ' %') 98 | endif 99 | if g:repl_stayatrepl_when_open == 0 100 | exe bufwinnr(g:repl_target_n) . 'wincmd w' 101 | endif 102 | call term_wait(repl#GetConsoleName(), 20) 103 | let l:n = 0 104 | while l:n < 1000 105 | let l:tl = repl#Strip(repl#GetTerminalLine()) 106 | if !(l:tl ==# 'ipdb>') 107 | call term_wait(repl#GetConsoleName(), 20) 108 | else 109 | break 110 | endif 111 | let l:n = l:n + 1 112 | endwhile 113 | endfunction 114 | 115 | command! -nargs=* REPLDebugStopAtCurrentLine call s:REPLDebugStopAtCurrentLine() 116 | command! REPLPDBC call s:REPLDebugRun() 117 | command! REPLPDBN call s:REPLDebugN() 118 | command! REPLPDBS call s:REPLDebugS() 119 | command! REPLPDBU call s:REPLDebugU() 120 | command! REPLDebug call s:REPLDebugIPDB() 121 | -------------------------------------------------------------------------------- /plugin/default.vim: -------------------------------------------------------------------------------- 1 | let g:REPLVIM_PATH = expand(':p') 2 | let g:REPLVIM_PATH = g:REPLVIM_PATH[:strridx(g:REPLVIM_PATH, "plugin") - 1] 3 | 4 | if has('win32') 5 | let s:repl_default_program = { 6 | \ 'python': 'python', 7 | \ 'python-debug': 'python3 -m ipdb', 8 | \ 'default': 'cmd.exe', 9 | \ 'vim': 'vim -e', 10 | \ } 11 | else 12 | let s:repl_default_program = { 13 | \ 'python': 'python', 14 | \ 'python-debug': 'python3 -m ipdb', 15 | \ 'default': 'bash', 16 | \ 'vim': 'vim -e', 17 | \ } 18 | endif 19 | if exists("g:repl_program") 20 | call extend(s:repl_default_program, g:repl_program) 21 | endif 22 | let g:repl_program = s:repl_default_program 23 | 24 | if !has_key(g:repl_program, 'perl') 25 | let g:repl_program.perl = [] 26 | if executable('perlconsole') 27 | let g:repl_program.perl = ['perlconsole'] 28 | elseif executable('reply') 29 | let g:repl_program.perl = ['reply'] 30 | elseif executable('re.pl') 31 | let g:repl_program.perl = ['re.pl'] 32 | else 33 | if has('win32') 34 | let g:repl_program.perl = [g:REPLVIM_PATH . 'ftplugin\\perl\\psh'] 35 | else 36 | let g:repl_program.perl = [g:REPLVIM_PATH . 'ftplugin/perl/psh'] 37 | endif 38 | endif 39 | endif 40 | 41 | if !exists('g:sendtorepl_invoke_key') 42 | let g:sendtorepl_invoke_key = "w" 43 | endif 44 | 45 | if !exists('g:repl_auto_sends') 46 | let g:repl_auto_sends = ['class ', 'def ', 'for ', 'if ', 'while ', 'with ', 'async def', '@', 'try'] 47 | endif 48 | 49 | if !exists('g:repl_cursor_down') 50 | let g:repl_cursor_down = 1 51 | endif 52 | 53 | if !exists('g:repl_python_automerge') 54 | let g:repl_python_automerge = 0 55 | endif 56 | 57 | if !exists('g:repl_vimscript_engine') 58 | let g:repl_vimscript_engine = 0 59 | endif 60 | 61 | if !exists('g:repl_console_name') 62 | let g:repl_console_name = 'ZYTREPL' 63 | endif 64 | 65 | let s:repl_default_exit_commands = { 66 | \ "python": "quit()", 67 | \ "ptpython": "quit()", 68 | \ "ipython": "quit()", 69 | \ "bash": "exit", 70 | \ "zsh": "exit", 71 | \ "R": "q()", 72 | \ 'lua': 'os.exit()', 73 | \ 'vim': 'q', 74 | \ "default": "exit", 75 | \ } 76 | if exists('g:repl_exit_commands') 77 | call extend(s:repl_default_exit_commands, g:repl_exit_commands) 78 | endif 79 | let g:repl_exit_commands = s:repl_default_exit_commands 80 | 81 | let s:repl_default_input_symbols = { 82 | \ 'python': ['>>>', '>>>>', 'ipdb>', 'pdb', '...'], 83 | \ 'vim': [':'], 84 | \ } 85 | if exists('g:repl_input_symbols') 86 | call extend(s:repl_default_input_symbols, g:repl_input_symbols) 87 | end 88 | let g:repl_input_symbols = s:repl_default_input_symbols 89 | 90 | if !exists('g:repl_position') 91 | let g:repl_position = 0 92 | endif 93 | 94 | if !exists('g:repl_stayatrepl_when_open') 95 | let g:repl_stayatrepl_when_open = 0 96 | endif 97 | 98 | if !exists('g:repl_python_auto_import') 99 | let g:repl_python_auto_import = 1 100 | endif 101 | 102 | if !exists('g:repl_python_auto_send_unfinish_line') 103 | let g:repl_python_auto_send_unfinish_line = 1 104 | endif 105 | 106 | if !exists('g:repl_sendvariable_template') 107 | let g:repl_sendvariable_template = { 108 | \ 'python': 'print()', 109 | \ 'ipython': 'print()', 110 | \ 'ptpython': 'print()', 111 | \ } 112 | endif 113 | 114 | if !exists('g:repl_unhide_when_send_lines') 115 | let g:repl_unhide_when_send_lines = 1 116 | endif 117 | 118 | if !exists('g:repl_code_block_fences') 119 | let g:repl_code_block_fences = {'python': '# %%', 'zsh': '# %%', 'markdown': '```'} 120 | endif 121 | 122 | " if !exists('g:repl_code_block_end') 123 | " let g:repl_code_block_end = '# END' 124 | " endif 125 | -------------------------------------------------------------------------------- /plugin/vim-repl.vim: -------------------------------------------------------------------------------- 1 | let invoke_key = g:sendtorepl_invoke_key 2 | 3 | silent! exe 'nnoremap ' . invoke_key . ' :SendCurrentLine' 4 | silent! exe 'vnoremap ' . invoke_key . ' :SendLineToREPL' 5 | 6 | command! -range SendLineToREPL ,call repl#SendChunkLines() 7 | command! SendCurrentLine call repl#SendCurrentLine() 8 | command! REPLSendRHSofCurrentLine call repl#SendRHSofCurrentLine() 9 | command! -nargs=* REPLToggle call repl#REPLToggle() 10 | command! REPLDebugInfo call repl#REPLDebug() 11 | command! REPLIsVisible echo repl#REPLIsVisible() 12 | command! REPLTerminalLine echo repl#GetTerminalLine() 13 | command! REPLHide call repl#REPLHide() 14 | command! REPLUnhide call repl#REPLUnhide() 15 | command! REPLSendAll call repl#SendAll() 16 | command! REPLSendSession call repl#SendSession() 17 | -------------------------------------------------------------------------------- /pythonx/filemanager.py: -------------------------------------------------------------------------------- 1 | #! python3.8 -u 2 | # -*- coding: utf-8 -*- 3 | 4 | ############################## 5 | ## Package PyCTLib 6 | ############################## 7 | __all__ = """ 8 | path 9 | file 10 | """.split() 11 | 12 | import os, re, struct 13 | 14 | """ 15 | from pyctlib.system.filemanager import * 16 | """ 17 | 18 | def totuple(num): 19 | if isinstance(num, str): return (num,) 20 | try: return tuple(num) 21 | except: return (num,) 22 | 23 | class path: 24 | 25 | def __init__(self, _path): 26 | self._path = os.path.abspath(".") 27 | 28 | def parent(self): 29 | return path(os.path.abspath(self._path + os.path.pathsep + "..")) 30 | 31 | def name(self): 32 | return self._path.split(os.path.pathsep)[-1].split(os.path.extsep)[0] 33 | 34 | def ls(self): 35 | return os.listdir(self._path) 36 | -------------------------------------------------------------------------------- /pythonx/formatpythoncode.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import os 3 | 4 | # currentpath = os.path.dirname(os.path.abspath(__file__)) 5 | # sys.path = [currentpath] + sys.path 6 | 7 | """ 8 | sys.path.append("/Users/zhangyiteng/.vim/plugged/vim-repl/autoload") 9 | """ 10 | 11 | # try: 12 | # import afpython as replpython 13 | # except Exception: 14 | import replpython 15 | from filemanager import path 16 | import filemanager 17 | 18 | from itertools import zip_longest 19 | 20 | THREE_DOUBLEQUOTE = '"' * 3 21 | THREE_SINGLEQUOTE = '"' * 3 22 | 23 | class Version: 24 | def __init__(self, version_string: str, name: str=None): 25 | self.nums = tuple(map(int, version_string.split('.'))) 26 | 27 | def __repr__(self): 28 | return f'Version({".".join(map(str, self.nums))})' 29 | 30 | @property 31 | def major(self): 32 | return str(self.nums[0]) 33 | 34 | @property 35 | def minor(self): 36 | if len(self.nums) < 2: 37 | return None 38 | return '.'.join(map(str, self.nums[1:])) 39 | 40 | def __iter__(self): 41 | yield from self.nums 42 | 43 | def __eq__(self, ver2): 44 | return all(v1 == v2 for v1, v2 in zip_longest(self, ver2, fillvalue=0)) 45 | 46 | def __gt__(self, ver2): 47 | for num1, num2 in zip_longest(self, ver2, fillvalue=0): 48 | if num1 > num2: 49 | return True 50 | if num1 < num2: 51 | return False 52 | return False 53 | 54 | def __ge__(self, ver2): 55 | return self==ver2 or self>ver2 56 | 57 | 58 | class UnfinishType: 59 | LEFT_PARAENTHESE = 1 # ( 60 | LEFT_BRACE = 2 # { 61 | LEFT_BRACKET = 3 # [ 62 | DOUBLEQUOTE = 4 # " 63 | SINGLEQUOTE = 5 # ' 64 | LONGSTRING = 11 # ''' 65 | RAWLONGSTRING = 12 66 | RAWCOMMENT = 13 67 | COMMENT = 6 # """ 68 | TYPEHINT = 7 # def f(a: int) 69 | TYPEALPHA = 10 70 | DEFAULTVALUE = 8 # def f(a=1) 71 | DICTVALUE = 9 # {1:2} 72 | 73 | class pythoncodes: 74 | def __init__(self, replprogram = "ipython", flag_mergefinishline = False, version="", filepath=""): 75 | self.rawcontents = list() 76 | self.replprogram = replprogram 77 | self.flag_mergefinishline = flag_mergefinishline 78 | self.version = version 79 | self.filepath = filepath 80 | self.blocks = list() # List[List[str], List[int]] 81 | 82 | def getcode(self, code): 83 | self.rawcontents = [line.replace("\t", " ") for line in code if len(line.strip()) != 0] 84 | self.removecomments() 85 | if len(self.rawcontents) == 0: 86 | return self 87 | if self.flag_mergefinishline == 1 and len(self.rawcontents) > 1: 88 | self.mergeunfinishline() 89 | self.analysepythonindent() 90 | self.seperateintoblocks() 91 | self.trunctindent() 92 | self.expand_import_from_relative_path() 93 | return self 94 | 95 | def expand_import_from_relative_path(self): 96 | if self.filepath == "": 97 | return 98 | for index in range(len(self.blocks)): 99 | block = self.blocks[index] 100 | if len(block[0]) == 1 and (block[0][0].lstrip().startswith("import .") or block[0][0].lstrip().startswith("from .")): 101 | code = block[0][0] 102 | p = path(self.filepath) 103 | dot_number = len(code.split()[1]) - len(code.split()[1].lstrip(".")) 104 | for _ in range(dot_number - 1): 105 | p = p.parent() 106 | if "__init__.py" not in [t[-1] for t in p.ls()]: 107 | temp = code[:code.index(".")] + code[code.index(".")+dot_number:] 108 | else: 109 | extra = "" 110 | while p and "__init__.py" in [t[-1] for t in p.ls()]: 111 | extra = p.name + ("." if extra else "") + extra 112 | p = p.parent 113 | temp = code[:code.index(".")] + extra + ("." if not code[code.index(".") + dot_number:].startswith(" ") else "") + code[code.index(".") + dot_number:] 114 | self.blocks[index] = ([temp], self.blocks[index][1]) 115 | 116 | def tructcomments(self, line): 117 | doublecomment = False 118 | singlecomment = False 119 | index = 0 120 | while index < len(line): 121 | if doublecomment: 122 | if line[index] == "\\": 123 | index += 2 124 | continue 125 | if line[index] == '"': 126 | doublecomment = False 127 | elif singlecomment: 128 | if line[index] == "\\": 129 | index += 2 130 | continue 131 | if line[index] == "'": 132 | singlecomment = False 133 | elif line[index] == '"': 134 | doublecomment = True 135 | elif line[index] == "'": 136 | singlecomment = True 137 | elif line[index] == "#": 138 | return line[:index].rstrip() 139 | index += 1 140 | return line 141 | 142 | def removecomments(self): 143 | newrawcontents = list() 144 | i = 0 145 | multi_indent = replpython.getpythonindent_multiline(self.rawcontents) 146 | while i < len(self.rawcontents): 147 | if i == 0: 148 | indentlevel, finishflag, unfinishtype = (0, False, -1) 149 | else: 150 | indentlevel, finishflag, unfinishtype = multi_indent[i - 1] 151 | if unfinishtype in {UnfinishType.DOUBLEQUOTE, UnfinishType.SINGLEQUOTE, UnfinishType.LONGSTRING, UnfinishType.COMMENT, UnfinishType.RAWCOMMENT, UnfinishType.RAWLONGSTRING}: 152 | newrawcontents.append(self.rawcontents[i]) 153 | i += 1 154 | continue 155 | if self.rawcontents[i].strip().startswith("#"): 156 | i += 1 157 | continue 158 | if finishflag and self.rawcontents[i].strip().startswith(THREE_DOUBLEQUOTE): 159 | for j in range(i, len(self.rawcontents)): 160 | j_indentlevel, j_finishflag, j_unfinishtype = replpython.getpythonindent(self.rawcontents[i:j+1]) 161 | if j_finishflag == True: 162 | break 163 | i = j + 1 164 | continue 165 | newrawcontents.append(self.tructcomments(self.rawcontents[i])) 166 | i += 1 167 | self.rawcontents = newrawcontents 168 | 169 | def mergeunfinishline(self): 170 | tempcodeindent = replpython.getpythonindent_multiline(self.rawcontents) 171 | newrawcontents = list() 172 | i = 0 173 | while i < len(self.rawcontents): 174 | tempcodeline = "" 175 | j = i 176 | while j < len(self.rawcontents): 177 | tobeadded = self.rawcontents[j] 178 | Flag_NeedMerge = not tempcodeindent[j][1] 179 | if j != i and tempcodeindent[j-1][2] not in {UnfinishType.DOUBLEQUOTE, UnfinishType.SINGLEQUOTE, UnfinishType.LONGSTRING, UnfinishType.COMMENT, UnfinishType.RAWLONGSTRING}: 180 | tobeadded = tobeadded.lstrip() 181 | if tempcodeindent[j][2] not in {UnfinishType.LONGSTRING, UnfinishType.COMMENT, UnfinishType.RAWCOMMENT, UnfinishType.RAWLONGSTRING}: 182 | tobeadded = tobeadded.rstrip() 183 | if tempcodeindent[j][2] in {UnfinishType.LONGSTRING, UnfinishType.COMMENT}: 184 | tobeadded = tobeadded + "\\n" 185 | Flag_NeedMerge = True 186 | if tempcodeindent[j][2] in {UnfinishType.RAWCOMMENT}: 187 | tobeadded = tobeadded + THREE_DOUBLEQUOTE + ' "\\n" ' + THREE_DOUBLEQUOTE 188 | Flag_NeedMerge = True 189 | if tempcodeindent[j][2] in {UnfinishType.RAWLONGSTRING}: 190 | tobeadded = tobeadded + THREE_SINGLEQUOTE + ' "\\n" ' + THREE_SINGLEQUOTE 191 | Flag_NeedMerge = True 192 | if tempcodeindent[j][2] not in {UnfinishType.LONGSTRING, UnfinishType.COMMENT, UnfinishType.RAWCOMMENT, UnfinishType.RAWLONGSTRING} and self.rawcontents[j][-1] == "\\": 193 | if tempcodeindent[j][2] not in {UnfinishType.DOUBLEQUOTE, UnfinishType.SINGLEQUOTE}: 194 | tobeadded = tobeadded[:-1] + " " 195 | else: 196 | tobeadded = tobeadded[:-1] 197 | Flag_NeedMerge = True 198 | tempcodeline += tobeadded 199 | if Flag_NeedMerge: 200 | j = j + 1 201 | else: 202 | break 203 | i = j + 1 204 | newrawcontents.append(tempcodeline) 205 | self.rawcontents = newrawcontents 206 | 207 | return self 208 | 209 | def getindentlevel(self, line): 210 | return len(line) - len(line.lstrip()) 211 | 212 | def analysepythonindent(self): 213 | self.codeindent = replpython.getpythonindent_multiline(self.rawcontents) 214 | 215 | def isstartofline(self, index): 216 | if index == 0: 217 | return True 218 | else: 219 | return self.codeindent[index-1][1] 220 | 221 | def canbestartofblock(self, index): 222 | if not self.isstartofline(index): 223 | return False 224 | line = self.rawcontents[index].strip() 225 | if line.startswith("else:"): 226 | return False 227 | elif line.startswith("except "): 228 | return False 229 | elif line.startswith("except:"): 230 | return False 231 | elif line.startswith("elif "): 232 | return False 233 | else: 234 | return True 235 | 236 | def seperateintoblocks(self): 237 | index = 0 238 | self.blocks = list() 239 | while index < len(self.rawcontents): 240 | indentlevel = self.getindentlevel(self.rawcontents[index]) 241 | blockend = next((i for i in range(index + 1, len(self.rawcontents)) 242 | if self.canbestartofblock(i) and self.getindentlevel(self.rawcontents[i]) <= indentlevel), 243 | len(self.rawcontents)) 244 | self.blocks.append((self.rawcontents[index:blockend], list(range(index, blockend)))) 245 | index = blockend 246 | 247 | def trunctindent(self): 248 | for i in range(len(self.blocks)): 249 | indentlevel = self.getindentlevel(self.blocks[i][0][0]) 250 | temp = list() 251 | for j in range(len(self.blocks[i][0])): 252 | if self.isstartofline(self.blocks[i][1][j]): 253 | temp.append(self.blocks[i][0][j][indentlevel:]) 254 | else: 255 | temp.append(self.blocks[i][0][j]) 256 | self.blocks[i] = (temp, self.blocks[i][1]) 257 | 258 | def addbackspace(self): 259 | def AutoStop(line): 260 | line = line.lstrip() 261 | if self.replprogram == "ptpython": 262 | if line.startswith("pass "): 263 | return True 264 | else: 265 | return False 266 | elif self.replprogram == "ipython": 267 | version = Version(self.version) 268 | # print(f'{version=}, {self.version=}') 269 | if version >= Version('7.1'): 270 | return False 271 | if line.startswith("pass ") or line.startswith("return ") or line.startswith("raise ") or line.startswith("continue ") or line.startswith("break "): 272 | return True 273 | else: 274 | return False 275 | else: 276 | return False 277 | if self.replprogram == "ipython": 278 | for i in range(len(self.blocks)): 279 | temp = list() 280 | block = self.blocks[i][0] 281 | # print(block) 282 | lastline = 0 283 | lastback = 0 284 | for j in range(len(block)): 285 | if j == 0: 286 | currentindent = -1 287 | temp.append(block[j].strip()) 288 | continue 289 | elif self.isstartofline(self.blocks[i][1][j]): 290 | lastline = j 291 | p = j - 1 292 | # while not self.isstartofline(self.blocks[i][1][p]) or not self.codeindent[self.blocks[i][1][p]][1]: 293 | while not self.isstartofline(self.blocks[i][1][p]): 294 | p -= 1 295 | previousindent = self.codeindent[self.blocks[i][1][p]][0] 296 | currentindent = self.codeindent[self.blocks[i][1][j]][0] 297 | # print(j, previousindent, currentindent) 298 | if previousindent > currentindent: 299 | temp.append(''.join(["\b" * (previousindent - currentindent - 4 * AutoStop(block[p]))]) + block[j].strip()) 300 | lastback = previousindent - currentindent - 4 * AutoStop(block[p]) 301 | else: 302 | temp.append(block[j].strip()) 303 | lastback = 0 304 | else: 305 | if self.codeindent[self.blocks[i][1][j-1]][2] in {UnfinishType.DOUBLEQUOTE, UnfinishType.SINGLEQUOTE, UnfinishType.LONGSTRING, UnfinishType.COMMENT}: 306 | temp.append(block[j]) 307 | else: 308 | if self.version == "6" and self.isstartofline(self.blocks[i][1][j - 1]): 309 | temp.append(''.join(["\b" * lastback]) + block[j].strip()) 310 | else: 311 | temp.append(block[j].strip()) 312 | # print("temp", temp) 313 | 314 | if i == len(self.blocks) - 1 and self.codeindent[self.blocks[i][1][-1]][1] == False: 315 | pass 316 | else: 317 | if self.blocks[i][0][0].startswith('def '): 318 | if currentindent - 4 * AutoStop(block[lastline]) == 0: 319 | temp += ["", ""] 320 | else: 321 | temp += [""] 322 | elif self.blocks[i][0][0].startswith('async def '): 323 | if currentindent - 4 * AutoStop(block[lastline]) == 0: 324 | temp += ["", ""] 325 | else: 326 | temp += [""] 327 | elif self.blocks[i][0][0].startswith('class '): 328 | if currentindent - 4 * AutoStop(block[lastline]) == 0: 329 | temp += ["", ""] 330 | else: 331 | temp += [""] 332 | elif self.blocks[i][0][0].startswith('for '): 333 | if currentindent - 4 * AutoStop(block[lastline]) == 0: 334 | temp += ["", ""] 335 | else: 336 | temp += [""] 337 | elif self.blocks[i][0][0].startswith('while '): 338 | if currentindent - 4 * AutoStop(block[lastline]) == 0: 339 | temp += ["", ""] 340 | else: 341 | temp += [""] 342 | elif self.blocks[i][0][0].startswith('try:'): 343 | if currentindent - 4 * AutoStop(block[lastline]) == 0: 344 | temp += ["", ""] 345 | else: 346 | temp += [""] 347 | elif self.blocks[i][0][0].startswith('if '): 348 | if currentindent - 4 * AutoStop(block[lastline]) == 0: 349 | temp += ["", ""] 350 | else: 351 | temp += [""] 352 | elif self.blocks[i][0][0].startswith('with '): 353 | if currentindent - 4 * AutoStop(block[lastline]) == 0: 354 | temp += ["", ""] 355 | else: 356 | temp += [""] 357 | # print(temp) 358 | self.blocks[i] = (temp, self.blocks[i][1]) 359 | elif self.replprogram == "ptpython": 360 | for i in range(len(self.blocks)): 361 | temp = list() 362 | block = self.blocks[i][0] 363 | # print(block) 364 | lastline = 0 365 | for j in range(len(block)): 366 | if j == 0: 367 | currentindent = -1 368 | temp.append(block[j].strip()) 369 | continue 370 | elif self.isstartofline(self.blocks[i][1][j]): 371 | lastline = j 372 | p = j - 1 373 | while not self.isstartofline(self.blocks[i][1][p]): 374 | p -= 1 375 | previousindent = self.codeindent[self.blocks[i][1][p]][0] 376 | currentindent = self.codeindent[self.blocks[i][1][j]][0] 377 | # print(j, previousindent, currentindent) 378 | if previousindent > currentindent: 379 | temp.append(''.join(["\b" * (previousindent - currentindent - 4 * AutoStop(block[p]))]) + block[j].strip()) 380 | else: 381 | temp.append(block[j].strip()) 382 | else: 383 | if self.codeindent[self.blocks[i][1][j-1]][2] in {UnfinishType.DOUBLEQUOTE, UnfinishType.SINGLEQUOTE, UnfinishType.LONGSTRING, UnfinishType.COMMENT}: 384 | temp.append(block[j]) 385 | else: 386 | temp.append(block[j].strip()) 387 | if i == len(self.blocks) - 1 and self.codeindent[self.blocks[i][1][-1]][1] == False: 388 | pass 389 | else: 390 | if self.blocks[i][0][0].startswith('def '): 391 | temp += [""] 392 | elif self.blocks[i][0][0].startswith('async def '): 393 | temp += [""] 394 | elif self.blocks[i][0][0].startswith('class '): 395 | temp += [""] 396 | elif self.blocks[i][0][0].startswith('for '): 397 | temp += [""] 398 | elif self.blocks[i][0][0].startswith('while '): 399 | temp += [""] 400 | elif self.blocks[i][0][0].startswith('try:'): 401 | temp += [""] 402 | elif self.blocks[i][0][0].startswith('if '): 403 | temp += [""] 404 | elif self.blocks[i][0][0].startswith('with '): 405 | temp += [""] 406 | # print(temp) 407 | 408 | self.blocks[i] = (temp, self.blocks[i][1]) 409 | elif self.replprogram == "python": 410 | for i in range(len(self.blocks)): 411 | if i == len(self.blocks) - 1 and self.codeindent[self.blocks[i][1][-1]][1] == False: 412 | continue 413 | temp = list() 414 | temp = self.blocks[i][0] 415 | if i == len(self.blocks) - 1 and self.codeindent[self.blocks[i][1][-1]][1] == False: 416 | pass 417 | else: 418 | if self.blocks[i][0][0].startswith('def '): 419 | temp += [""] 420 | elif self.blocks[i][0][0].startswith('async def '): 421 | temp += [""] 422 | elif self.blocks[i][0][0].startswith('class '): 423 | temp += [""] 424 | elif self.blocks[i][0][0].startswith('for '): 425 | temp += [""] 426 | elif self.blocks[i][0][0].startswith('while '): 427 | temp += [""] 428 | elif self.blocks[i][0][0].startswith('try:'): 429 | temp += [""] 430 | elif self.blocks[i][0][0].startswith('if '): 431 | temp += [""] 432 | elif self.blocks[i][0][0].startswith('with '): 433 | temp += [""] 434 | 435 | self.blocks[i] = (temp, self.blocks[i][1]) 436 | 437 | def generatecodes(self): 438 | newcode = list() 439 | if len(self.rawcontents) == 0: 440 | return newcode 441 | self.addbackspace() 442 | for i in range(len(self.blocks)): 443 | newcode += self.blocks[i][0] 444 | return newcode 445 | 446 | def format_to_repl(codes, pythonprogram = "ipython", mergeunfinishline=False, version="", filepath=""): 447 | pc = pythoncodes(replprogram=pythonprogram, flag_mergefinishline=mergeunfinishline, version=version, filepath=filepath) 448 | pc.getcode(codes) 449 | # print(pc.generatecodes()) 450 | return pc.generatecodes() 451 | 452 | class testreplpython: 453 | def __init__(self): 454 | self.pc = pythoncodes() 455 | self.pc_merge = pythoncodes(flag_mergefinishline = True) 456 | 457 | def test1(self): 458 | code = ["a = b + 1", "", "return"] 459 | self.pc.getcode(code) 460 | assert len(self.pc.blocks) == 2 461 | assert self.pc.rawcontents == ["a = b + 1", "return"] 462 | 463 | def test2(self): 464 | code = ["def f(a, b):", ' """', ' this is a test function', 465 | ' """', ' return a+b'] 466 | self.pc.getcode(code) 467 | assert len(self.pc.blocks) == 1 468 | assert self.pc.rawcontents == ["def f(a, b):", " return a+b"] 469 | 470 | def testcodeandnewcode(self, code, newcode): 471 | code = code.split("\n")[1:-1] 472 | newcode = newcode.split("\n")[1:-1] 473 | assert self.pc.getcode(code).rawcontents == newcode 474 | 475 | def testcodeandnewcode_merge(self, code, newcode): 476 | code = code.split("\n")[1:-1] 477 | newcode = newcode.split("\n")[1:-1] 478 | assert self.pc_merge.getcode(code).rawcontents == newcode 479 | 480 | def test3(self): 481 | code = """ 482 | def f(a, b): 483 | # this is a test of function 484 | c = a + b 485 | 486 | return c 487 | """ 488 | newcode = """ 489 | def f(a, b): 490 | c = a + b 491 | return c 492 | """ 493 | self.testcodeandnewcode(code, newcode) 494 | 495 | # def test4(self): 496 | # code = """ 497 | # def f(a, 498 | # # this is a test 499 | # b 500 | # ): 501 | # return a + b 502 | # """ 503 | 504 | 505 | # newcode = """ 506 | # def f(a, 507 | # b 508 | # ): 509 | # return a + b 510 | # """ 511 | 512 | # newcode_merge = """ 513 | # def f(a,b): 514 | # return a + b 515 | # """ 516 | 517 | # self.testcodeandnewcode(code, newcode) 518 | # self.testcodeandnewcode_merge(code, newcode_merge) 519 | 520 | def test4(self): 521 | code = ["if a:", " b = 1", "else:", " b = 2"] 522 | newcode = ["if a:", "b = 1", "\b\b\b\belse:", "b = 2", ""] 523 | assert format_to_repl(code) == newcode 524 | 525 | def test5(self): 526 | code = ["def f(a, b):", " if a:", " return", " else:", " b = 2"] 527 | newcode = ["def f(a, b):", "if a:", "return", "else:", "b = 2", ""] 528 | assert format_to_repl(code) == newcode 529 | 530 | def test6(self): 531 | code = ["if 'lon\\", " g sentence':", " print('hello')"] 532 | newcode = ["if 'lon\\", " g sentence':", "print('hello')", ""] 533 | assert format_to_repl(code) == newcode 534 | 535 | def test7(self): 536 | code = ['def train(self):', 537 | ' if 1:', 538 | ' 2', 539 | ' f(1,', 540 | ' 2)', 541 | ' mean_acc = list()', 542 | ' return 1'] 543 | newcode = ['def train(self):', 544 | 'if 1:', 545 | '2', 546 | '\b\b\b\bf(1,', 547 | '\b\b\b\b2)', 548 | 'mean_acc = list()', 549 | 'return 1', '', ''] 550 | assert format_to_repl(code) == newcode 551 | 552 | def test8(self): 553 | code = ["def f(a, b):", " if a:", " return", " else:", " b = 2"] 554 | newcode = ["def f(a, b):", "if a:", "return", "\b\b\b\belse:", "b = 2", ""] 555 | assert format_to_repl(code, pythonprogram="ptpython") == newcode 556 | 557 | def test9(self): 558 | code = ["def f(a, b):", " if a:", " return", " else:", " b = 2"] 559 | newcode = ["def f(a, b):", "if a:", "return", "\b\b\b\belse:", "b = 2", ""] 560 | assert format_to_repl(code, pythonprogram="ipython", version="7") == newcode 561 | 562 | def test(self): 563 | self.test1() 564 | self.test2() 565 | self.test3() 566 | self.test4() 567 | self.test5() 568 | self.test6() 569 | self.test7() 570 | self.test8() 571 | self.test9() 572 | print("All test unit are successfully passed!") 573 | 574 | def test_speed(): 575 | infile = open("./testspeedrawcode.txt", "r") 576 | code = infile.readlines() 577 | code = [line[:-1] for line in code] 578 | format_to_repl(code) 579 | 580 | def main(): 581 | test = testreplpython() 582 | test.test() 583 | 584 | if __name__ == "__main__": 585 | main() 586 | # test_speed() 587 | -------------------------------------------------------------------------------- /pythonx/replpython.py: -------------------------------------------------------------------------------- 1 | import re 2 | 3 | class PlainData: 4 | def __init__(self): 5 | self.tokentype = -1 6 | self.rownumber = -1 7 | 8 | class PlainStack: 9 | def __init__(self): 10 | self.size = 0 11 | self.content = list() 12 | 13 | def top(self): 14 | if self.size == 0: 15 | raise ValueError("empty") 16 | else: 17 | return self.content[self.size - 1] 18 | 19 | def pop(self): 20 | if self.size == 0: 21 | raise ValueError("empty") 22 | else: 23 | self.size -= 1 24 | 25 | def push(self, tokentype, rownumber): 26 | data = PlainData() 27 | data.tokentype = tokentype 28 | data.rownumber = rownumber 29 | if len(self.content) > self.size: 30 | self.content[self.size] = data 31 | self.size += 1 32 | else: 33 | self.content.append(data) 34 | self.size += 1 35 | 36 | def clear(self): 37 | self.size = 0 38 | 39 | 40 | def indentofline(line): 41 | index = 0 42 | while index < len(line) and line[index] == ' ': 43 | index += 1 44 | return index 45 | 46 | class UnfinishType: 47 | LEFT_PARAENTHESE = 1 # ( 48 | LEFT_BRACE = 2 # { 49 | LEFT_BRACKET = 3 # [ 50 | DOUBLEQUOTE = 4 # " 51 | SINGLEQUOTE = 5 # ' 52 | LONGSTRING = 11 # ''' 53 | COMMENT = 6 # """ 54 | TYPEHINT = 7 # def f(a: int) 55 | TYPEALPHA = 10 56 | DEFAULTVALUE = 8 # def f(a=1) 57 | DICTVALUE = 9 # {1:2} 58 | RAWLONGSTRING = 12 59 | RAWCOMMENT = 13 60 | 61 | # @jit(nopython=True, cache=True) 62 | def getpythonindent(codes): 63 | # conditionstack = Stack() 64 | if len(codes) == 0: 65 | return (0, True, -1) 66 | 67 | conditionstack = PlainStack() 68 | operator = ['+', '-', '*', '/', '&', '^', '%', '<', '>', '|', '!', ':', '=', ','] 69 | characterinname = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', ' q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B', 'C', 70 | 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '_', '.'] 71 | 72 | LEFT_PARAENTHESE = 1 # ( 73 | LEFT_BRACE = 2 # { 74 | LEFT_BRACKET = 3 # [ 75 | DOUBLEQUOTE = 4 # " 76 | SINGLEQUOTE = 5 # ' 77 | LONGSTRING = 11 # ''' 78 | RAWLONGSTRING = 12 79 | COMMENT = 6 # """ 80 | TYPEHINT = 7 # def f(a: int) 81 | TYPEALPHA = 10 82 | DEFAULTVALUE = 8 # def f(a=1) 83 | DICTVALUE = 9 # {1:2} 84 | RAWCOMMENT = 13 85 | for rownumber in range(len(codes)): 86 | line = codes[rownumber] 87 | # flag = True 88 | col = 0 89 | # for col in range(len(line)): 90 | while col < len(line): 91 | character = line[col] 92 | col += 1 93 | if character == ' ': 94 | continue 95 | elif character == '\t': 96 | continue 97 | elif character in characterinname: 98 | continue 99 | elif character in operator: 100 | continue 101 | if conditionstack.size == 0: 102 | if character == '@': 103 | continue 104 | elif character == '#': 105 | break 106 | elif character == '(': 107 | conditionstack.push(LEFT_PARAENTHESE, rownumber) 108 | continue 109 | elif character == '[': 110 | conditionstack.push(LEFT_BRACKET, rownumber) 111 | continue 112 | elif character == '{': 113 | conditionstack.push(LEFT_BRACE, rownumber) 114 | continue 115 | elif character == '"': 116 | # print(line, line[col - 2]) 117 | if col + 1 < len(line) and line[col:col + 2] == '""': 118 | if col-2 > 0 and line[col - 2] == "r": 119 | conditionstack.push(RAWCOMMENT, rownumber) 120 | else: 121 | conditionstack.push(COMMENT, rownumber) 122 | col += 2 123 | else: 124 | conditionstack.push(DOUBLEQUOTE, rownumber) 125 | continue 126 | elif character == "'": 127 | if col + 1 < len(line) and line[col:col + 2] == "''": 128 | if col-2 > 0 and line[col - 2] == "r": 129 | conditionstack.push(RAWLONGSTRING, rownumber) 130 | else: 131 | conditionstack.push(LONGSTRING, rownumber) 132 | col += 2 133 | else: 134 | conditionstack.push(SINGLEQUOTE, rownumber) 135 | continue 136 | else: 137 | # print("############################") 138 | # print("Error found: {}".format(line)) 139 | # print("############################") 140 | continue 141 | elif conditionstack.top().tokentype == LEFT_PARAENTHESE: 142 | if character == '(': 143 | conditionstack.push(LEFT_PARAENTHESE, rownumber) 144 | continue 145 | elif character == '[': 146 | conditionstack.push(LEFT_BRACKET, rownumber) 147 | continue 148 | elif character == '{': 149 | conditionstack.push(LEFT_BRACE, rownumber) 150 | continue 151 | elif character == ')': 152 | conditionstack.pop() 153 | continue 154 | elif character == '"': 155 | # print(line, line[col - 2]) 156 | if col + 1 < len(line) and line[col:col + 2] == '""': 157 | if col-2 > 0 and line[col - 2] == "r": 158 | conditionstack.push(RAWCOMMENT, rownumber) 159 | else: 160 | conditionstack.push(COMMENT, rownumber) 161 | col += 2 162 | else: 163 | conditionstack.push(DOUBLEQUOTE, rownumber) 164 | continue 165 | elif character == "'": 166 | if col + 1 < len(line) and line[col:col + 2] == "''": 167 | if col-2 > 0 and line[col - 2] == "r": 168 | conditionstack.push(RAWLONGSTRING, rownumber) 169 | else: 170 | conditionstack.push(LONGSTRING, rownumber) 171 | col += 2 172 | else: 173 | conditionstack.push(SINGLEQUOTE, rownumber) 174 | continue 175 | elif character == "#": 176 | break 177 | else: 178 | # print("############################") 179 | # print("Error found: {}".format(line)) 180 | # print("############################") 181 | continue 182 | elif conditionstack.top().tokentype == LEFT_BRACKET: 183 | if character == '(': 184 | conditionstack.push(LEFT_PARAENTHESE, conditionstack.top().rownumber) 185 | continue 186 | elif character == '[': 187 | conditionstack.push(LEFT_BRACKET, conditionstack.top().rownumber) 188 | continue 189 | elif character == '{': 190 | conditionstack.push(LEFT_BRACE, conditionstack.top().rownumber) 191 | continue 192 | elif character == ']': 193 | conditionstack.pop() 194 | continue 195 | elif character == '"': 196 | # print(line, line[col - 2]) 197 | if col + 1 < len(line) and line[col:col + 2] == '""': 198 | if col-2 > 0 and line[col - 2] == "r": 199 | conditionstack.push(RAWCOMMENT, rownumber) 200 | else: 201 | conditionstack.push(COMMENT, rownumber) 202 | col += 2 203 | else: 204 | conditionstack.push(DOUBLEQUOTE, rownumber) 205 | continue 206 | elif character == "'": 207 | if col + 1 < len(line) and line[col:col + 2] == "''": 208 | if col-2 > 0 and line[col - 2] == "r": 209 | conditionstack.push(RAWLONGSTRING, rownumber) 210 | else: 211 | conditionstack.push(LONGSTRING, rownumber) 212 | col += 2 213 | else: 214 | conditionstack.push(SINGLEQUOTE, rownumber) 215 | continue 216 | elif character == "#": 217 | break 218 | else: 219 | # print("############################") 220 | # print("Error found: {}".format(line)) 221 | # print("############################") 222 | continue 223 | elif conditionstack.top().tokentype == LEFT_BRACE: 224 | if character == '(': 225 | conditionstack.push(LEFT_PARAENTHESE, conditionstack.top().rownumber) 226 | continue 227 | elif character == '[': 228 | conditionstack.push(LEFT_BRACKET, conditionstack.top().rownumber) 229 | continue 230 | elif character == '{': 231 | conditionstack.push(LEFT_BRACE, conditionstack.top().rownumber) 232 | continue 233 | elif character == '}': 234 | conditionstack.pop() 235 | continue 236 | elif character == '"': 237 | # print(line, line[col - 2]) 238 | if col + 1 < len(line) and line[col:col + 2] == '""': 239 | if col-2 > 0 and line[col - 2] == "r": 240 | conditionstack.push(RAWCOMMENT, rownumber) 241 | else: 242 | conditionstack.push(COMMENT, rownumber) 243 | col += 2 244 | else: 245 | conditionstack.push(DOUBLEQUOTE, rownumber) 246 | continue 247 | elif character == "'": 248 | if col + 1 < len(line) and line[col:col + 2] == "''": 249 | if col-2 > 0 and line[col - 2] == "r": 250 | conditionstack.push(RAWLONGSTRING, rownumber) 251 | else: 252 | conditionstack.push(LONGSTRING, rownumber) 253 | col += 2 254 | else: 255 | conditionstack.push(SINGLEQUOTE, rownumber) 256 | continue 257 | elif character == "#": 258 | break 259 | else: 260 | # print("############################") 261 | # print("Error found: {}".format(line)) 262 | # print("############################") 263 | continue 264 | elif conditionstack.top().tokentype == DOUBLEQUOTE: 265 | if character == '\\': 266 | col += 1 267 | continue 268 | elif character == '"': 269 | conditionstack.pop() 270 | continue 271 | else: 272 | continue 273 | elif conditionstack.top().tokentype == SINGLEQUOTE: 274 | if character== '\\': 275 | col += 1 276 | continue 277 | elif character == '\'': 278 | conditionstack.pop() 279 | continue 280 | else: 281 | continue 282 | elif conditionstack.top().tokentype in {COMMENT, RAWCOMMENT}: 283 | if col + 1 < len(line) and line[col - 1:col + 2] == '"""': 284 | conditionstack.pop() 285 | elif character == '\\': 286 | col += 1 287 | continue 288 | elif conditionstack.top().tokentype in {LONGSTRING, RAWLONGSTRING}: 289 | if col + 1 < len(line) and line[col - 1:col + 2] == "'''": 290 | conditionstack.pop() 291 | elif character == '\\': 292 | col += 1 293 | continue 294 | # if conditionstack.size != 0: 295 | # if conditionstack.top().tokentype == DOUBLEQUOTE or conditionstack.top().tokentype == SINGLEQUOTE: 296 | # conditionstack.clear() 297 | # break 298 | indentlevel = 0 299 | if conditionstack.size != 0: 300 | lastrow = codes[conditionstack.top().rownumber] 301 | indentlevel = indentofline(lastrow) 302 | finishflag = False 303 | unfinishedtype = conditionstack.top().tokentype 304 | else: 305 | lastrownumber = len(codes) - 1 306 | while lastrownumber >= 0 and len(codes[lastrownumber]) == 0: 307 | lastrownumber -= 1 308 | lastrow = codes[lastrownumber] 309 | indentlevel = indentofline(lastrow) 310 | finishflag = True 311 | unfinishedtype = -1 312 | return (indentlevel, finishflag, unfinishedtype) 313 | 314 | 315 | def getpythonindent_multiline(codes): 316 | if len(codes) == 0: 317 | return [(0, True, -1)] 318 | 319 | multi_indent = list() 320 | conditionstack = PlainStack() 321 | operator = ['+', '-', '*', '/', '&', '^', '%', '<', '>', '|', '!', ':', '=', ','] 322 | characterinname = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', ' q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B', 'C', 323 | 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '_', '.'] 324 | 325 | LEFT_PARAENTHESE = 1 # ( 326 | LEFT_BRACE = 2 # { 327 | LEFT_BRACKET = 3 # [ 328 | DOUBLEQUOTE = 4 # " 329 | SINGLEQUOTE = 5 # ' 330 | LONGSTRING = 11 # ''' 331 | RAWLONGSTRING = 12 332 | RAWCOMMENT = 13 333 | COMMENT = 6 # """ 334 | TYPEHINT = 7 # def f(a: int) 335 | TYPEALPHA = 10 336 | DEFAULTVALUE = 8 # def f(a=1) 337 | DICTVALUE = 9 # {1:2} 338 | for rownumber in range(len(codes)): 339 | line = codes[rownumber] 340 | # flag = True 341 | col = 0 342 | # for col in range(len(line)): 343 | while col < len(line): 344 | character = line[col] 345 | col += 1 346 | if character == ' ': 347 | continue 348 | elif character == '\t': 349 | continue 350 | elif character in characterinname: 351 | continue 352 | elif character in operator: 353 | continue 354 | if conditionstack.size == 0: 355 | if character == '@': 356 | continue 357 | elif character == '#': 358 | break 359 | elif character == '(': 360 | conditionstack.push(LEFT_PARAENTHESE, rownumber) 361 | continue 362 | elif character == '[': 363 | conditionstack.push(LEFT_BRACKET, rownumber) 364 | continue 365 | elif character == '{': 366 | conditionstack.push(LEFT_BRACE, rownumber) 367 | continue 368 | elif character == '"': 369 | # print(line, line[col - 2]) 370 | if col + 1 < len(line) and line[col:col + 2] == '""': 371 | if col-2 > 0 and line[col - 2] == "r": 372 | conditionstack.push(RAWCOMMENT, rownumber) 373 | else: 374 | conditionstack.push(COMMENT, rownumber) 375 | col += 2 376 | else: 377 | conditionstack.push(DOUBLEQUOTE, rownumber) 378 | continue 379 | elif character == "'": 380 | if col + 1 < len(line) and line[col:col + 2] == "''": 381 | if col-2 > 0 and line[col - 2] == "r": 382 | conditionstack.push(RAWLONGSTRING, rownumber) 383 | else: 384 | conditionstack.push(LONGSTRING, rownumber) 385 | col += 2 386 | else: 387 | conditionstack.push(SINGLEQUOTE, rownumber) 388 | continue 389 | else: 390 | # print("############################") 391 | # print("Error found: {}".format(line)) 392 | # print("############################") 393 | continue 394 | elif conditionstack.top().tokentype == LEFT_PARAENTHESE: 395 | if character == '(': 396 | conditionstack.push(LEFT_PARAENTHESE, rownumber) 397 | continue 398 | elif character == '[': 399 | conditionstack.push(LEFT_BRACKET, rownumber) 400 | continue 401 | elif character == '{': 402 | conditionstack.push(LEFT_BRACE, rownumber) 403 | continue 404 | elif character == ')': 405 | conditionstack.pop() 406 | continue 407 | elif character == '"': 408 | if col + 1 < len(line) and line[col:col + 2] == '""': 409 | if col-2 > 0 and line[col - 2] == "r": 410 | conditionstack.push(RAWCOMMENT, rownumber) 411 | else: 412 | conditionstack.push(COMMENT, rownumber) 413 | col += 2 414 | else: 415 | conditionstack.push(DOUBLEQUOTE, rownumber) 416 | continue 417 | elif character == "'": 418 | if col + 1 < len(line) and line[col:col + 2] == "''": 419 | if col-2 > 0 and line[col - 2] == "r": 420 | conditionstack.push(RAWLONGSTRING, rownumber) 421 | else: 422 | conditionstack.push(LONGSTRING, rownumber) 423 | col += 2 424 | else: 425 | conditionstack.push(SINGLEQUOTE, rownumber) 426 | continue 427 | elif character == "#": 428 | break 429 | else: 430 | continue 431 | elif conditionstack.top().tokentype == LEFT_BRACKET: 432 | if character == '(': 433 | conditionstack.push(LEFT_PARAENTHESE, conditionstack.top().rownumber) 434 | continue 435 | elif character == '[': 436 | conditionstack.push(LEFT_BRACKET, conditionstack.top().rownumber) 437 | continue 438 | elif character == '{': 439 | conditionstack.push(LEFT_BRACE, conditionstack.top().rownumber) 440 | continue 441 | elif character == ']': 442 | conditionstack.pop() 443 | continue 444 | elif character == '"': 445 | if col + 1 < len(line) and line[col:col + 2] == '""': 446 | if col-2 > 0 and line[col - 2] == "r": 447 | conditionstack.push(RAWCOMMENT, rownumber) 448 | else: 449 | conditionstack.push(COMMENT, rownumber) 450 | col += 2 451 | else: 452 | conditionstack.push(DOUBLEQUOTE, rownumber) 453 | continue 454 | elif character == "'": 455 | if col + 1 < len(line) and line[col:col + 2] == "''": 456 | if col-2 > 0 and line[col - 2] == "r": 457 | conditionstack.push(RAWLONGSTRING, rownumber) 458 | else: 459 | conditionstack.push(LONGSTRING, rownumber) 460 | col += 2 461 | else: 462 | conditionstack.push(SINGLEQUOTE, rownumber) 463 | continue 464 | elif character == "#": 465 | break 466 | else: 467 | continue 468 | elif conditionstack.top().tokentype == LEFT_BRACE: 469 | if character == '(': 470 | conditionstack.push(LEFT_PARAENTHESE, conditionstack.top().rownumber) 471 | continue 472 | elif character == '[': 473 | conditionstack.push(LEFT_BRACKET, conditionstack.top().rownumber) 474 | continue 475 | elif character == '{': 476 | conditionstack.push(LEFT_BRACE, conditionstack.top().rownumber) 477 | continue 478 | elif character == '}': 479 | conditionstack.pop() 480 | continue 481 | elif character == '"': 482 | if col + 1 < len(line) and line[col:col + 2] == '""': 483 | if col-2 > 0 and line[col - 2] == "r": 484 | conditionstack.push(RAWCOMMENT, rownumber) 485 | else: 486 | conditionstack.push(COMMENT, rownumber) 487 | col += 2 488 | else: 489 | conditionstack.push(DOUBLEQUOTE, rownumber) 490 | continue 491 | elif character == "'": 492 | if col + 1 < len(line) and line[col:col + 2] == "''": 493 | if col-2 > 0 and line[col - 2] == "r": 494 | conditionstack.push(RAWLONGSTRING, rownumber) 495 | else: 496 | conditionstack.push(LONGSTRING, rownumber) 497 | col += 2 498 | else: 499 | conditionstack.push(SINGLEQUOTE, rownumber) 500 | continue 501 | elif character == "#": 502 | break 503 | else: 504 | # print("############################") 505 | # print("Error found: {}".format(line)) 506 | # print("############################") 507 | continue 508 | elif conditionstack.top().tokentype == DOUBLEQUOTE: 509 | if character == '\\': 510 | col += 1 511 | continue 512 | elif character == '"': 513 | conditionstack.pop() 514 | continue 515 | else: 516 | continue 517 | elif conditionstack.top().tokentype == SINGLEQUOTE: 518 | if character== '\\': 519 | col += 1 520 | continue 521 | elif character == '\'': 522 | conditionstack.pop() 523 | continue 524 | else: 525 | continue 526 | elif conditionstack.top().tokentype in {COMMENT, RAWCOMMENT}: 527 | if col + 1 < len(line) and line[col - 1:col + 2] == '"""': 528 | conditionstack.pop() 529 | elif character == '\\': 530 | col += 1 531 | continue 532 | elif conditionstack.top().tokentype in {LONGSTRING, RAWLONGSTRING}: 533 | if col + 1 < len(line) and line[col - 1:col + 2] == "'''": 534 | conditionstack.pop() 535 | elif character == '\\': 536 | col += 1 537 | continue 538 | 539 | 540 | indentlevel = 0 541 | if conditionstack.size != 0: 542 | lastrow = codes[conditionstack.top().rownumber] 543 | indentlevel = indentofline(lastrow) 544 | finishflag = False 545 | unfinishedtype = conditionstack.top().tokentype 546 | else: 547 | lastrownumber = rownumber 548 | while lastrownumber >= 0 and len(codes[lastrownumber]) == 0: 549 | lastrownumber -= 1 550 | lastrow = codes[lastrownumber] 551 | indentlevel = indentofline(lastrow) 552 | finishflag = True 553 | unfinishedtype = -1 554 | multi_indent.append((indentlevel, finishflag, unfinishedtype)) 555 | return multi_indent 556 | 557 | def GetLastOutput(buffer, pythonprogram): 558 | if pythonprogram == "ipython": 559 | blocks = list() 560 | current = [] 561 | flag = False 562 | for line in buffer: 563 | if re.match(r"^In \[\d+\]:.*$", line): 564 | if flag == True: 565 | while current and current[-1].strip() == "": 566 | current = current[:-1] 567 | blocks.append(current) 568 | current = [line] 569 | flag = True 570 | else: 571 | current.append(line) 572 | for block in blocks[::-1]: 573 | out = GetOutputOfBlock(block, pythonprogram) 574 | if "Error" in out and "Traceback" in out: 575 | return "" 576 | if out: 577 | return out 578 | return "" 579 | return "" 580 | 581 | def GetOutputOfBlock(content, pythonprogram): 582 | if not content: 583 | return "" 584 | if pythonprogram == "ipython": 585 | assert re.match(r"^In \[\d+\]:.*$", content[0]) 586 | index = 1 587 | while index < len(content): 588 | if re.match("^ {3,}\.\.\.:.*$", content[index]): 589 | index += 1 590 | continue 591 | m = re.match(r"^Out\[\d+\]:(.*)$", content[index]) 592 | if m: 593 | return m.group(1).strip() 594 | if content[index]: 595 | break 596 | index += 1 597 | else: 598 | return "" 599 | return "\n".join(content[index:]) 600 | 601 | def main(): 602 | code = ["if a:", " b = 1", "else:", " b = 2"] 603 | print(getpythonindent_multiline(code)) 604 | 605 | if __name__ == "__main__": 606 | main() 607 | -------------------------------------------------------------------------------- /pythonx/testpythonx.py: -------------------------------------------------------------------------------- 1 | def f(a): 2 | return 1 3 | -------------------------------------------------------------------------------- /test/UUUU.log: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sillybun/vim-repl/e6c1eaebcf3c1755084279475d4b7909d472d85a/test/UUUU.log -------------------------------------------------------------------------------- /test/comment.py: -------------------------------------------------------------------------------- 1 | def func(a): 2 | # a is a list 3 | s = """ 4 | # test 5 | """ 6 | return len(a) 7 | 8 | def fung(a): 9 | """ 10 | # this is a test 11 | """ 12 | return len(a) 13 | -------------------------------------------------------------------------------- /test/function1.py: -------------------------------------------------------------------------------- 1 | def idf_modified_dot(tf_hash_x, tf_hash_y=None): 2 | inner_product = 0 3 | if tf_hash_y is None: 4 | for value in tf_hash_x.values(): 5 | inner_product += value ** 2 6 | return inner_product 7 | for word in set(tf_hash_x.keys()).intersection(set(tf_hash_y.keys())): 8 | inner_product += tf_hash_x[word] * tf_hash_y[word] 9 | return inner_product 10 | -------------------------------------------------------------------------------- /test/gcd.py: -------------------------------------------------------------------------------- 1 | def gcd(a, b): 2 | if a < b: 3 | return gcd(b, a) 4 | elif a % b == 0: 5 | return b 6 | else: 7 | return gcd(b, a % b) 8 | 9 | 10 | gcd(10, 13) 11 | gcd(10, 13) 12 | gcd(10, 13) 13 | -------------------------------------------------------------------------------- /test/ipython_log.py: -------------------------------------------------------------------------------- 1 | # IPython log file 2 | 3 | get_ipython().run_line_magic('logstart', '') 4 | quit() 5 | -------------------------------------------------------------------------------- /test/long_sentence.py: -------------------------------------------------------------------------------- 1 | if right == len(temp_train) or len(temp_train[right][0]) != len(temp_train[left][0]): 2 | to_be_return.append((torch.stack(tuple(x[0] for x in temp_train[left:right])), torch.Tensor( 3 | list(x[1] for x in temp_train[left:right])))) 4 | left = right 5 | 6 | 7 | if self._data['type'][i] == 'test': 8 | self.test_data.append( 9 | (longcontent, 1 if self._data['label'][i] == 'pos' else 0)) 10 | else: 11 | if self._data['label'][i] == 'unsup': 12 | self.train_data_unlabeled.append(longcontent) 13 | else: 14 | self.train_data_labeled.append( 15 | (longcontent, 1 if self._data['label'][i] == 'pos' else 0)) 16 | -------------------------------------------------------------------------------- /test/perl/test.pl: -------------------------------------------------------------------------------- 1 | $x = 1 2 | 2 ** 3 3 | $x 4 | -------------------------------------------------------------------------------- /test/python.db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sillybun/vim-repl/e6c1eaebcf3c1755084279475d4b7909d472d85a/test/python.db -------------------------------------------------------------------------------- /test/pythonpdb.py: -------------------------------------------------------------------------------- 1 | import time 2 | 3 | for i in range(10): 4 | for j in range(10): 5 | time.sleep(1) 6 | print(i + j) 7 | 8 | -------------------------------------------------------------------------------- /test/test.py: -------------------------------------------------------------------------------- 1 | def f(a, b): 2 | print("hello") 3 | print("hello") 4 | print("hello") 5 | print("hello") 6 | print("hello") 7 | 8 | f(range(4), range(3)) 9 | 10 | # test: 11 | for i in [1, 2, 3]: 12 | print(i) 13 | 14 | 15 | def f(a, # 假设这一行很长 16 | b 17 | ): 18 | return a + b 19 | -------------------------------------------------------------------------------- /test/test_Chinese.py: -------------------------------------------------------------------------------- 1 | print("中文测试") 2 | -------------------------------------------------------------------------------- /test/test_asyncdef.py: -------------------------------------------------------------------------------- 1 | async def test(): 2 | print("test") 3 | 4 | def test1(a): 5 | return a 6 | -------------------------------------------------------------------------------- /test/test_automerge.py: -------------------------------------------------------------------------------- 1 | a= "1123\ 2 | 4567" 3 | 4 | a = """123 5 | 134 6 | 678""" 7 | 8 | print(a) 9 | 10 | b = 1 + 2\ 11 | +3\ 12 | +4 13 | print(b) 14 | 15 | def f(a, b): 16 | return a + b 17 | 18 | b = 1 + 2\ 19 | +3\ 20 | +4\ 21 | + f(1, 22 | 2) +\ 23 | 5 24 | 25 | print(b) 26 | 27 | a = "abc\ 28 | def" 29 | 30 | print(a) 31 | 32 | output1 = """ 33 | R1#show ip interface brief 34 | Interface IP-Address OK? Method Status Protocol 35 | FastEthernet0/0 15.0.15.1 YES manual up up 36 | FastEthernet0/1 10.0.12.1 YES manual up up 37 | FastEthernet0/2 10.0.13.1 YES manual up up 38 | FastEthernet0/3 unassigned YES unset up up 39 | Loopback0 10.1.1.1 YES manual up up 40 | Loopback100 100.0.0.1 YES manual up up 41 | """ 42 | -------------------------------------------------------------------------------- /test/test_autopaste.py: -------------------------------------------------------------------------------- 1 | import pandas as pd 2 | wb = pd.ExcelFile('32180.xlsx') 3 | wb.sheet_names 4 | -------------------------------------------------------------------------------- /test/test_autosend.py: -------------------------------------------------------------------------------- 1 | for i in range(19): 2 | print(i) 3 | 4 | if 1: 5 | print(2) 6 | else: 7 | print(3) 8 | -------------------------------------------------------------------------------- /test/test_autosend_unfinished_line.py: -------------------------------------------------------------------------------- 1 | def f(a, b): 2 | return a+b 3 | 4 | f(1, 5 | 2) 6 | 7 | """ 8 | 13 9 | 1141231 10 | 14124412 11 | 11321 12 | """ 13 | -------------------------------------------------------------------------------- /test/test_class.py: -------------------------------------------------------------------------------- 1 | class A: 2 | 3 | def __init__(self): 4 | A.a = 1 5 | print(1) 6 | 7 | def fun(self): 8 | return 9 | 10 | a = A() 11 | print(a.a) 12 | 13 | 14 | class Dictionary: 15 | def __init__(self): 16 | if os.path.exists(self.word_index_count_file): 17 | for line in word_index_count: 18 | content = line.split(" ") 19 | self.freq = self.freq / self.freq.sum() 20 | 21 | def count_word_number(self): 22 | content = list() 23 | -------------------------------------------------------------------------------- /test/test_decoration.py: -------------------------------------------------------------------------------- 1 | @decoration 2 | class C: 3 | stuff 4 | 5 | @decoration 6 | def test(): 7 | return 8 | -------------------------------------------------------------------------------- /test/test_dill.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | 3 | class myclass: 4 | def __init__(self): 5 | self.x = 1 6 | self.y = 1 7 | 8 | x = myclass() 9 | 10 | y: int = 1 11 | 12 | z = {"ZYT": 1993} 13 | 14 | z["zyt"] = 1993 15 | 16 | # CHECKPOINT 2153462 17 | # 2018-08-12 18 | 19 | # CHECKPOINT 7277560 20 | # 2018-08-12 21 | 22 | # CP 5321993 23 | # 2018-08-13 24 | -------------------------------------------------------------------------------- /test/test_error.py: -------------------------------------------------------------------------------- 1 | a = 1 2 | b = aa 3 | c = b 4 | 5 | def func(a, b): 6 | return a / b 7 | 8 | func(1, 0) 9 | 10 | import math 11 | 12 | math.sqrt(-1) 13 | 14 | -------------------------------------------------------------------------------- /test/test_for.py: -------------------------------------------------------------------------------- 1 | i = 0 2 | for i in range(10): 3 | print(i) 4 | -------------------------------------------------------------------------------- /test/test_gcn.py: -------------------------------------------------------------------------------- 1 | def f(): 2 | if i % 1000 == 0: 3 | mean_acc = list() 4 | for vf in test_feed: 5 | if vf[self.word_num] == 0: 6 | mean_acc.append(0) 7 | else: 8 | mean_acc.append(self.sess.run(self.top_accuracy[0], vf)) 9 | print("After %d training steps, validation top 1 accuracy using average model is %g " % 10 | (i, sum(mean_acc) / len(mean_acc))) 11 | mean_acc = list() 12 | for vf in test_feed: 13 | if vf[self.word_num] == 0: 14 | mean_acc.append(0) 15 | else: 16 | mean_acc.append(self.sess.run(self.top_accuracy[1], vf)) 17 | print("After %d training steps, validation top 2 accuracy using average model is %g " % 18 | -------------------------------------------------------------------------------- /test/test_git107.py: -------------------------------------------------------------------------------- 1 | import pandas as pd 2 | wb = pd.ExcelFile('32180.xlsx') 3 | wb.sheet_names 4 | -------------------------------------------------------------------------------- /test/test_github127.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | 3 | ### 4 | arr = np.random.randint(low=0,high=100,size=(5,6)) 5 | for i in arr: 6 | print(i) 7 | ### 8 | 9 | print("hello") 10 | -------------------------------------------------------------------------------- /test/test_magic_command.py: -------------------------------------------------------------------------------- 1 | %%timeit 2 | mean, var = 0., 0. 3 | for i in range(1000000): 4 | x = np.random.randn() 5 | a = np.random.randn() 6 | z = np.random.randn() 7 | m = np.random.randn() 8 | y = x * a * z * m 9 | mean += y 10 | var += y**2 11 | mean / 1000000, math.sqrt(var / 1000000) 12 | -------------------------------------------------------------------------------- /test/test_multi_lines.py: -------------------------------------------------------------------------------- 1 | def train(self): 2 | if 1: 3 | 2 4 | f(1, 5 | 2) 6 | mean_acc = list() 7 | return 1 8 | 9 | def f(a, b, c): 10 | return a + b + c 11 | 12 | if 1: 13 | f(1, 14 | 2, 15 | 3) 16 | print("hello") 17 | -------------------------------------------------------------------------------- /test/test_multisends.py: -------------------------------------------------------------------------------- 1 | from time import sleep 2 | 3 | sleep(3) 4 | print(1) 5 | sleep(3) 6 | print(2) 7 | sleep(3) 8 | print(3) 9 | sleep(1) 10 | print(4) 11 | sleep(1) 12 | print(5) 13 | sleep(1) 14 | print(6) 15 | sleep(1) 16 | print(7) 17 | 18 | -------------------------------------------------------------------------------- /test/test_rhs.py: -------------------------------------------------------------------------------- 1 | a = 1123123 2 | b = a 3 | -------------------------------------------------------------------------------- /test/test_session.py: -------------------------------------------------------------------------------- 1 | # %% 2 | print(1) 3 | print(2) 4 | 5 | # %% 6 | print(3) 7 | print(4) 8 | -------------------------------------------------------------------------------- /test/test_space.py: -------------------------------------------------------------------------------- 1 | 1 + 1 2 | 3 | 1 + 1 4 | 5 | -------------------------------------------------------------------------------- /test/test_tab.py: -------------------------------------------------------------------------------- 1 | def start_of_object(stripped): 2 | i = len(stripped) - 1 3 | depth = 0 4 | instringsingle = False 5 | instringdouble = False 6 | while i >= 0: 7 | if not instringsingle and not instringdouble: 8 | if stripped[i] in [')', ']', '}']: 9 | depth += 1 10 | i-=1 11 | continue 12 | if stripped[i] in ['(', '[', '{']: 13 | depth -= 1 14 | if depth < 0: 15 | break 16 | i-=1 17 | continue 18 | if stripped[i] == '"': 19 | instringdouble = True 20 | i-=1 21 | continue 22 | if stripped[i] == '\'': 23 | instringsingle = True 24 | i-=1 25 | continue 26 | if stripped[i] in [' ', '+', '-', '*', '/', '=', ':', ',', '&', '>', '<'] and depth == 0: 27 | break 28 | elif instringsingle: 29 | if stripped[i] == '\'' and (i == 0 or stripped[i-1] != '\\'): 30 | instringsingle = False 31 | i-=1 32 | continue 33 | else: 34 | if stripped[i] == '"' and (i == 0 or stripped[i-1] != '\\'): 35 | instringdouble = False 36 | i-=1 37 | continue 38 | i-=1 39 | return i + 1 40 | -------------------------------------------------------------------------------- /test/test_try.py: -------------------------------------------------------------------------------- 1 | import sys 2 | from os.path import join, dirname, realpath, abspath, exists 3 | from dotenv import load_dotenv, find_dotenv 4 | load_dotenv(dotenv_path=find_dotenv(), verbose=True) 5 | 6 | try: 7 | cur_path = dirname(realpath(__file__)) 8 | except Exception as e: 9 | cur_path = dirname(realpath('__file__')) 10 | else: 11 | print(cur_path) 12 | sys.path.append(abspath(join(cur_path, '../'))) 13 | sys.path.append(abspath(join(cur_path, '../schema'))) 14 | 15 | def process_etl(): 16 | a = 1 17 | -------------------------------------------------------------------------------- /test/test_virtualenv.py: -------------------------------------------------------------------------------- 1 | ###REPLENV: ~/.PythonEnvironment/replenv/bin/activate 2 | 3 | from sko.GA import GA 4 | -------------------------------------------------------------------------------- /test/test_with.py: -------------------------------------------------------------------------------- 1 | with open("./gcd.py") as input: 2 | content = input.readlines() 3 | -------------------------------------------------------------------------------- /test/testforsleep.py: -------------------------------------------------------------------------------- 1 | # BEGIN 2 | import time 3 | 4 | for i in range(10): 5 | time.sleep(1) 6 | 7 | print("hello") 8 | # END 9 | -------------------------------------------------------------------------------- /test/testgcd.py: -------------------------------------------------------------------------------- 1 | import gcd 2 | 3 | print(gcd.gcd(12, 20)) 4 | -------------------------------------------------------------------------------- /test/testif.py: -------------------------------------------------------------------------------- 1 | if 1: 2 | if 1: 3 | 1 4 | else: 5 | pass 6 | else: 7 | pass 8 | 9 | def func(): 10 | if True: 11 | return 1 12 | for i in range(3): 13 | return 0 14 | -------------------------------------------------------------------------------- /test/testlongsentence.py: -------------------------------------------------------------------------------- 1 | if "1".startswith("longlonglong long lon\ 2 | test"): 3 | print("hello") 4 | 5 | if "1".startswith("longlonglong long lon test"): 6 | print("hello") 7 | -------------------------------------------------------------------------------- /test/testnumpy.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | a_variable = np.zeros(19) 3 | b_variable = np.ones(10) 4 | --------------------------------------------------------------------------------