vimlm 0.1.0__py3-none-any.whl → 0.1.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {vimlm-0.1.0.dist-info → vimlm-0.1.1.dist-info}/METADATA +3 -25
- vimlm-0.1.1.dist-info/RECORD +7 -0
- vimlm.py +119 -15
- vimlm-0.1.0.dist-info/RECORD +0 -7
- {vimlm-0.1.0.dist-info → vimlm-0.1.1.dist-info}/LICENSE +0 -0
- {vimlm-0.1.0.dist-info → vimlm-0.1.1.dist-info}/WHEEL +0 -0
- {vimlm-0.1.0.dist-info → vimlm-0.1.1.dist-info}/entry_points.txt +0 -0
- {vimlm-0.1.0.dist-info → vimlm-0.1.1.dist-info}/top_level.txt +0 -0
| @@ -1,6 +1,6 @@ | |
| 1 1 | 
             
            Metadata-Version: 2.2
         | 
| 2 2 | 
             
            Name: vimlm
         | 
| 3 | 
            -
            Version: 0.1. | 
| 3 | 
            +
            Version: 0.1.1
         | 
| 4 4 | 
             
            Summary: VimLM - LLM-powered Vim assistant
         | 
| 5 5 | 
             
            Home-page: https://github.com/JosefAlbers/vimlm
         | 
| 6 6 | 
             
            Author: Josef Albers
         | 
| @@ -55,6 +55,7 @@ vimlm | |
| 55 55 | 
             
            |-------------|---------|-----------------------------------------|  
         | 
| 56 56 | 
             
            | `Ctrl-l`    | Insert  | Generate code suggestion                |  
         | 
| 57 57 | 
             
            | `Ctrl-p`    | Insert  | Insert generated code                   |  
         | 
| 58 | 
            +
            | `Ctrl-j`    | Insert  | Generate and insert code                |
         | 
| 58 59 |  | 
| 59 60 | 
             
            *Example Workflow*:  
         | 
| 60 61 | 
             
            1. Place cursor where you need code  
         | 
| @@ -69,7 +70,7 @@ def quicksort(arr): | |
| 69 70 | 
             
                return quicksort(left) + middle + quicksort(right)
         | 
| 70 71 | 
             
            ```
         | 
| 71 72 |  | 
| 72 | 
            -
            2. `Ctrl-l` to trigger → `Ctrl-p` to insert | 
| 73 | 
            +
            2. Use `Ctrl-j` to generate and insert the code (or `Ctrl-l` to trigger → `Ctrl-p` to insert)
         | 
| 73 74 |  | 
| 74 75 | 
             
            ### **Repository-Level Code Completion**
         | 
| 75 76 |  | 
| @@ -178,29 +179,6 @@ Simplify complex tasks by chaining multiple commands together into a single, reu | |
| 178 179 | 
             
            :VimLM Add Google-style docstrings !include % !continue 4000
         | 
| 179 180 | 
             
            ```
         | 
| 180 181 |  | 
| 181 | 
            -
            ## Smart Autocomplete  
         | 
| 182 | 
            -
            **Fill code gaps intelligently**
         | 
| 183 | 
            -
             | 
| 184 | 
            -
            | Key Binding | Mode    | Action                                  |  
         | 
| 185 | 
            -
            |-------------|---------|-----------------------------------------|  
         | 
| 186 | 
            -
            | `Ctrl-l`    | Insert  | Generate code suggestion                |  
         | 
| 187 | 
            -
            | `Ctrl-p`    | Insert  | Insert generated code                   |  
         | 
| 188 | 
            -
             | 
| 189 | 
            -
            *Example Workflow*:  
         | 
| 190 | 
            -
            1. Place cursor where you need code  
         | 
| 191 | 
            -
            ```python
         | 
| 192 | 
            -
            def quicksort(arr):
         | 
| 193 | 
            -
                if len(arr) <= 1:
         | 
| 194 | 
            -
                    return arr
         | 
| 195 | 
            -
                pivot = arr[len(arr) // 2]
         | 
| 196 | 
            -
                # <Cursor here>
         | 
| 197 | 
            -
                middle = [x for x in arr if x == pivot]
         | 
| 198 | 
            -
                right = [x for x in arr if x > pivot]
         | 
| 199 | 
            -
                return quicksort(left) + middle + quicksort(right)
         | 
| 200 | 
            -
            ```
         | 
| 201 | 
            -
             | 
| 202 | 
            -
            2. `Ctrl-l` to trigger → `Ctrl-p` to insert  
         | 
| 203 | 
            -
             | 
| 204 182 | 
             
            ## Configuration
         | 
| 205 183 |  | 
| 206 184 | 
             
            ### 1. **Model Settings**
         | 
| @@ -0,0 +1,7 @@ | |
| 1 | 
            +
            vimlm.py,sha256=C8b9W3HthJhSF5tU5YNK7E26R-7OZJwsezOINSzV_28,33956
         | 
| 2 | 
            +
            vimlm-0.1.1.dist-info/LICENSE,sha256=f1xgK8fAXg_intwnbc9nLkHf7ODPLtgpHs7DetQHOro,11343
         | 
| 3 | 
            +
            vimlm-0.1.1.dist-info/METADATA,sha256=jjtEcKF0tKJseHGLEQ83AOuz1UC72QG4JVTE3vUaGYM,6359
         | 
| 4 | 
            +
            vimlm-0.1.1.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
         | 
| 5 | 
            +
            vimlm-0.1.1.dist-info/entry_points.txt,sha256=mU5V4MYsuIzCc6YB-Ro-6USSHWN5vHw8UDnTEoq0isw,36
         | 
| 6 | 
            +
            vimlm-0.1.1.dist-info/top_level.txt,sha256=I8GjqoiP--scYsO3AfLhha-6Ax9ci3IvbWvVbPv8g94,6
         | 
| 7 | 
            +
            vimlm-0.1.1.dist-info/RECORD,,
         | 
    
        vimlm.py
    CHANGED
    
    | @@ -29,6 +29,10 @@ from pathlib import Path | |
| 29 29 | 
             
            from string import Template
         | 
| 30 30 | 
             
            import re
         | 
| 31 31 |  | 
| 32 | 
            +
            import sys
         | 
| 33 | 
            +
            import tty
         | 
| 34 | 
            +
            import termios
         | 
| 35 | 
            +
             | 
| 32 36 | 
             
            DEFAULTS = dict(
         | 
| 33 37 | 
             
                LLM_MODEL = "mlx-community/Qwen2.5-Coder-3B-Instruct-4bit", # None | "mlx-community/DeepSeek-R1-Distill-Qwen-7B-4bit" | "mlx-community/deepseek-r1-distill-qwen-1.5b" |  "mlx-community/phi-4-4bit" (8.25gb) |  "mlx-community/Qwen2.5-Coder-14B-Instruct-4bit" (8.31gb) |  "mlx-community/Qwen2.5-Coder-3B-Instruct-4bit" (1.74gb)
         | 
| 34 38 | 
             
                FIM_MODEL = "mlx-community/Qwen2.5-Coder-0.5B-4bit", # None | "mlx-community/Qwen2.5-Coder-32B-4bit" |  "mlx-community/Qwen2.5-Coder-0.5B-4bit" (278mb)
         | 
| @@ -40,7 +44,7 @@ DEFAULTS = dict( | |
| 40 44 | 
             
                SEP_CMD = '!',
         | 
| 41 45 | 
             
                THINK = ('<think>', '</think>'),
         | 
| 42 46 | 
             
                VERSION = '0.1.0',
         | 
| 43 | 
            -
                DEBUG =  | 
| 47 | 
            +
                DEBUG = False,
         | 
| 44 48 | 
             
            )
         | 
| 45 49 |  | 
| 46 50 | 
             
            DATE_FORM = "%Y_%m_%d_%H_%M_%S"
         | 
| @@ -94,7 +98,7 @@ def toout(s, key=None, mode=None): | |
| 94 98 | 
             
                tolog(s, key='tovim'+key+':'+mode)
         | 
| 95 99 |  | 
| 96 100 | 
             
            def tolog(log, key='debug'):
         | 
| 97 | 
            -
                if not DEBUG and  | 
| 101 | 
            +
                if not DEBUG and 'debug' in key:
         | 
| 98 102 | 
             
                    return
         | 
| 99 103 | 
             
                try:
         | 
| 100 104 | 
             
                    with open(LOG_PATH, "r", encoding="utf-8") as log_f:
         | 
| @@ -692,6 +696,7 @@ function! SplitAtCursorInInsert() | |
| 692 696 | 
             
                let current_file = expand('%:p')
         | 
| 693 697 | 
             
                let tree_file = s:watched_dir . '/tree'
         | 
| 694 698 | 
             
                call writefile([current_file], tree_file, 'w')
         | 
| 699 | 
            +
                call ScrollToTop()
         | 
| 695 700 | 
             
            endfunction
         | 
| 696 701 |  | 
| 697 702 | 
             
            function! InsertResponse()
         | 
| @@ -706,16 +711,27 @@ function! InsertResponse() | |
| 706 711 | 
             
                let col = col('.')
         | 
| 707 712 | 
             
                let line = getline('.')
         | 
| 708 713 | 
             
                if col == len(line) + 1
         | 
| 709 | 
            -
                    normal! " | 
| 714 | 
            +
                    normal! "zgp
         | 
| 710 715 | 
             
                else
         | 
| 711 | 
            -
                    normal! " | 
| 716 | 
            +
                    normal! "zgP
         | 
| 712 717 | 
             
                endif
         | 
| 713 718 | 
             
            endfunction
         | 
| 714 719 |  | 
| 720 | 
            +
            function! TabInInsert()
         | 
| 721 | 
            +
                let wip_file = s:watched_dir . '/wip'
         | 
| 722 | 
            +
                call writefile([], wip_file, 'w')
         | 
| 723 | 
            +
                call SplitAtCursorInInsert()
         | 
| 724 | 
            +
                while filereadable(wip_file)
         | 
| 725 | 
            +
                    sleep 10m
         | 
| 726 | 
            +
                endwhile
         | 
| 727 | 
            +
                call InsertResponse()
         | 
| 728 | 
            +
            endfunction
         | 
| 729 | 
            +
             | 
| 715 730 | 
             
            command! ToggleVimLM call ToggleVimLM()
         | 
| 716 731 | 
             
            command! -range -nargs=+ VimLM call VimLM(<f-args>)
         | 
| 717 | 
            -
            inoremap <silent>  | 
| 718 | 
            -
            inoremap <silent>  | 
| 732 | 
            +
            inoremap <silent> $mapl <C-\><C-o>:call SplitAtCursorInInsert()<CR>
         | 
| 733 | 
            +
            inoremap <silent> $mapp <C-\><C-o>:call InsertResponse()<CR><Right>
         | 
| 734 | 
            +
            inoremap <silent> $mapj <C-\><C-o>:call TabInInsert()<CR><Right>
         | 
| 719 735 | 
             
            nnoremap $mapp :call PasteIntoLastVisualSelection()<CR>
         | 
| 720 736 | 
             
            vnoremap $mapp <Cmd>:call PasteIntoLastVisualSelection()<CR>
         | 
| 721 737 | 
             
            vnoremap $mapl <Cmd>:call VisualPrompt()<CR>
         | 
| @@ -759,6 +775,80 @@ def get_common_dir_and_children(file_paths): | |
| 759 775 | 
             
                repo_name = os.path.basename(os.path.dirname(parent_path))
         | 
| 760 776 | 
             
                return repo_name, parent_path, child_paths
         | 
| 761 777 |  | 
| 778 | 
            +
            def get_key():
         | 
| 779 | 
            +
                fd = sys.stdin.fileno()
         | 
| 780 | 
            +
                old_settings = termios.tcgetattr(fd)
         | 
| 781 | 
            +
                try:
         | 
| 782 | 
            +
                    tty.setraw(sys.stdin.fileno())
         | 
| 783 | 
            +
                    ch = sys.stdin.read(1)
         | 
| 784 | 
            +
                    if ch == '\x1b': 
         | 
| 785 | 
            +
                        ch = sys.stdin.read(2)
         | 
| 786 | 
            +
                        if ch == '[A':
         | 
| 787 | 
            +
                            return 'up'
         | 
| 788 | 
            +
                        elif ch == '[B':
         | 
| 789 | 
            +
                            return 'down'
         | 
| 790 | 
            +
                    elif ch == 'j':
         | 
| 791 | 
            +
                        return 'down'
         | 
| 792 | 
            +
                    elif ch == 'k':
         | 
| 793 | 
            +
                        return 'up'
         | 
| 794 | 
            +
                    elif ch in [' ', 'x']:
         | 
| 795 | 
            +
                        return 'space'
         | 
| 796 | 
            +
                    elif ch == '\r':
         | 
| 797 | 
            +
                        return 'enter'
         | 
| 798 | 
            +
                    elif ch == 'q':
         | 
| 799 | 
            +
                        return 'quit'
         | 
| 800 | 
            +
                finally:
         | 
| 801 | 
            +
                    termios.tcsetattr(fd, termios.TCSADRAIN, old_settings)
         | 
| 802 | 
            +
                return None
         | 
| 803 | 
            +
             | 
| 804 | 
            +
            def select_files_interactive(file_paths):
         | 
| 805 | 
            +
                selected = [False] * len(file_paths)
         | 
| 806 | 
            +
                current_row = 0
         | 
| 807 | 
            +
                visible_start = 0
         | 
| 808 | 
            +
                visible_end = 0
         | 
| 809 | 
            +
                max_visible = 10
         | 
| 810 | 
            +
                def display():
         | 
| 811 | 
            +
                    nonlocal visible_start, visible_end
         | 
| 812 | 
            +
                    visible_start = max(0, current_row - max_visible + 2)
         | 
| 813 | 
            +
                    visible_end = min(len(file_paths), visible_start + max_visible)
         | 
| 814 | 
            +
                    sys.stdout.write(f"\x1b[{max_visible + 2}A") 
         | 
| 815 | 
            +
                    for i in range(visible_start, visible_end):
         | 
| 816 | 
            +
                        prefix = "> " if i == current_row else "  "
         | 
| 817 | 
            +
                        check = "[X]" if selected[i] else "[ ]"
         | 
| 818 | 
            +
                        filename = os.path.basename(file_paths[i])[:40] 
         | 
| 819 | 
            +
                        sys.stdout.write(f"\x1b[K{prefix}{check} {filename}\n") 
         | 
| 820 | 
            +
                    scroll_indicator = f" [{visible_start+1}-{visible_end} of {len(file_paths)}] "
         | 
| 821 | 
            +
                    sys.stdout.write(f"\x1b[K{scroll_indicator}\nSpace:Toggle Enter:Confirm Arrows:Navigate\n")
         | 
| 822 | 
            +
                    sys.stdout.flush()
         | 
| 823 | 
            +
                sys.stdout.write("\n" * (max_visible + 2))
         | 
| 824 | 
            +
                display()
         | 
| 825 | 
            +
                while True:
         | 
| 826 | 
            +
                    key = get_key()
         | 
| 827 | 
            +
                    if key == 'up' and current_row > 0:
         | 
| 828 | 
            +
                        current_row -= 1
         | 
| 829 | 
            +
                        if current_row < visible_start:
         | 
| 830 | 
            +
                            visible_start = max(0, visible_start - 1)
         | 
| 831 | 
            +
                            visible_end = visible_start + max_visible
         | 
| 832 | 
            +
                        display()
         | 
| 833 | 
            +
                    elif key == 'down' and current_row < len(file_paths) - 1:
         | 
| 834 | 
            +
                        current_row += 1
         | 
| 835 | 
            +
                        if current_row >= visible_end:
         | 
| 836 | 
            +
                            visible_start = min(len(file_paths) - max_visible, visible_start + 1)
         | 
| 837 | 
            +
                            visible_end = visible_start + max_visible
         | 
| 838 | 
            +
                        display()
         | 
| 839 | 
            +
                    elif key == 'space':
         | 
| 840 | 
            +
                        selected[current_row] = not selected[current_row]
         | 
| 841 | 
            +
                        display()
         | 
| 842 | 
            +
                    elif key == 'enter':
         | 
| 843 | 
            +
                        sys.stdout.write(f"\x1b[{max_visible + 2}B")
         | 
| 844 | 
            +
                        sys.stdout.write("\x1b[J") 
         | 
| 845 | 
            +
                        break
         | 
| 846 | 
            +
                    elif key == 'quit':
         | 
| 847 | 
            +
                        # selected = []
         | 
| 848 | 
            +
                        # break
         | 
| 849 | 
            +
                        return None
         | 
| 850 | 
            +
                return [file_paths[i] for i in range(len(file_paths)) if selected[i]]
         | 
| 851 | 
            +
             | 
| 762 852 | 
             
            def get_repo(args_repo, args_vim):
         | 
| 763 853 | 
             
                if not args_repo:
         | 
| 764 854 | 
             
                    return None
         | 
| @@ -767,18 +857,32 @@ def get_repo(args_repo, args_vim): | |
| 767 857 | 
             
                    if not arg.startswith('-'):
         | 
| 768 858 | 
             
                        if os.path.exists(arg):
         | 
| 769 859 | 
             
                            vim_files.append(os.path.abspath(arg))
         | 
| 770 | 
            -
                 | 
| 771 | 
            -
                rest_files = []
         | 
| 860 | 
            +
                repo_paths = []
         | 
| 772 861 | 
             
                for pattern in args_repo:
         | 
| 773 862 | 
             
                    expanded_paths = glob.glob(pattern)
         | 
| 774 863 | 
             
                    if expanded_paths:
         | 
| 775 864 | 
             
                        for path in expanded_paths:
         | 
| 776 | 
            -
                            if not os.path.isfile(path) or path in vim_files+ | 
| 865 | 
            +
                            if not os.path.isfile(path) or path in vim_files+repo_paths or os.path.basename(path).startswith('.') or is_binary(path):
         | 
| 777 866 | 
             
                                continue
         | 
| 778 | 
            -
                             | 
| 779 | 
            -
             | 
| 780 | 
            -
             | 
| 781 | 
            -
             | 
| 867 | 
            +
                            repo_paths.append(os.path.abspath(path))
         | 
| 868 | 
            +
                if len(repo_paths) > 9:
         | 
| 869 | 
            +
                    try:
         | 
| 870 | 
            +
                        sys.stdout.write("\n") 
         | 
| 871 | 
            +
                        selected_paths = select_files_interactive(repo_paths)
         | 
| 872 | 
            +
                        if not selected_paths:
         | 
| 873 | 
            +
                            return None
         | 
| 874 | 
            +
                        sys.stdout.write("\x1b[2A")  
         | 
| 875 | 
            +
                        sys.stdout.write("\x1b[J") 
         | 
| 876 | 
            +
                        repo_paths = selected_paths
         | 
| 877 | 
            +
                    except:
         | 
| 878 | 
            +
                        pass
         | 
| 879 | 
            +
                repo_files = []
         | 
| 880 | 
            +
                rest_files = []
         | 
| 881 | 
            +
                for path in repo_paths:
         | 
| 882 | 
            +
                    if path in vim_files:
         | 
| 883 | 
            +
                        rest_files.append(os.path.abspath(path))
         | 
| 884 | 
            +
                    else:
         | 
| 885 | 
            +
                        repo_files.append(os.path.abspath(path))
         | 
| 782 886 | 
             
                repo_name, repo_path, child_paths = get_common_dir_and_children(repo_files+rest_files)
         | 
| 783 887 | 
             
                repo_names, rest_names = child_paths[:len(repo_files)], child_paths[len(repo_files):]
         | 
| 784 888 | 
             
                list_content = [f'<|repo_name|>{repo_name}\n']
         | 
| @@ -789,7 +893,7 @@ def get_repo(args_repo, args_vim): | |
| 789 893 | 
             
                            list_content.append(f'<|file_sep|>{n}\n{f.read()}\n')
         | 
| 790 894 | 
             
                        list_mtime.append(int(os.path.getmtime(p)))
         | 
| 791 895 | 
             
                    except Exception as e:
         | 
| 792 | 
            -
                        tolog(f'Skipped {p} d/t {e}', 'get_repo()')
         | 
| 896 | 
            +
                        tolog(f'Skipped {p} d/t {e}', 'debug:get_repo()')
         | 
| 793 897 | 
             
                return dict(repo_files=repo_files, rest_files=rest_files, rest_names=rest_names, vim_files=vim_files, list_mtime=list_mtime, list_content=list_content, repo_path=repo_path)
         | 
| 794 898 |  | 
| 795 899 | 
             
            def run():
         | 
| @@ -799,7 +903,7 @@ def run(): | |
| 799 903 | 
             
                parser.add_argument('--repo', nargs='*', help="Paths to directories or files (e.g., assets/*, path/to/file)")
         | 
| 800 904 | 
             
                args = parser.parse_args()
         | 
| 801 905 | 
             
                dict_repo = get_repo(args.repo, args.args_vim)
         | 
| 802 | 
            -
                tolog(dict_repo, 'get_repo()')
         | 
| 906 | 
            +
                tolog(dict_repo, 'debug:get_repo()')
         | 
| 803 907 | 
             
                if args.test:
         | 
| 804 908 | 
             
                    return
         | 
| 805 909 | 
             
                reset_dir(WATCH_DIR)
         | 
    
        vimlm-0.1.0.dist-info/RECORD
    DELETED
    
    | @@ -1,7 +0,0 @@ | |
| 1 | 
            -
            vimlm.py,sha256=DHobmBa6aYYPUY0altPO2mrf_ZORfNnW2vDRl5Hpx8s,30436
         | 
| 2 | 
            -
            vimlm-0.1.0.dist-info/LICENSE,sha256=f1xgK8fAXg_intwnbc9nLkHf7ODPLtgpHs7DetQHOro,11343
         | 
| 3 | 
            -
            vimlm-0.1.0.dist-info/METADATA,sha256=H0-gRitfoH9U1MoiV8aEYQam8QYHceR4mSw3z5vbdPA,6959
         | 
| 4 | 
            -
            vimlm-0.1.0.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
         | 
| 5 | 
            -
            vimlm-0.1.0.dist-info/entry_points.txt,sha256=mU5V4MYsuIzCc6YB-Ro-6USSHWN5vHw8UDnTEoq0isw,36
         | 
| 6 | 
            -
            vimlm-0.1.0.dist-info/top_level.txt,sha256=I8GjqoiP--scYsO3AfLhha-6Ax9ci3IvbWvVbPv8g94,6
         | 
| 7 | 
            -
            vimlm-0.1.0.dist-info/RECORD,,
         | 
| 
            File without changes
         | 
| 
            File without changes
         | 
| 
            File without changes
         | 
| 
            File without changes
         |