aboutsummaryrefslogtreecommitdiffhomepage
path: root/share/functions/funced.fish
blob: 6439e53fabd7da0eb5d322863ebf43f602f07838 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
function funced --description 'Edit function definition'
    set -l editor
    # Check VISUAL first since theoretically EDITOR could be ed
    if set -q VISUAL
        set editor $VISUAL
    else if set -q EDITOR
        set editor $EDITOR
    end
    set -l interactive
    set -l funcname
    while set -q argv[1]
        switch $argv[1]
            case -h --help
                __fish_print_help funced
                return 0

            case -e --editor
                set editor $argv[2]
                set -e argv[2]

            case -i --interactive
                set interactive 1

            case --
                set funcname $funcname $argv[2]
                set -e argv[2]

            case '-*'
                set_color red
                printf (_ "%s: Unknown option %s\n") funced $argv[1]
                set_color normal
                return 1

            case '*' '.*'
                set funcname $funcname $argv[1]
        end
        set -e argv[1]
    end

    if test (count $funcname) -ne 1
        set_color red
        _ "funced: You must specify one function name
"
        set_color normal
        return 1
    end

    set -l init
    switch $funcname
        case '-*'
        set init function -- $funcname\n\nend
        case '*'
        set init function $funcname\n\nend
    end

    # Break editor up to get its first command (i.e. discard flags)
    if test -n "$editor"
        set -l editor_cmd
        eval set editor_cmd $editor
        if not type -q -f "$editor_cmd[1]"
            _ "funced: The value for \$EDITOR '$editor' could not be used because the command '$editor_cmd[1]' could not be found
    "
            set editor fish
        end
    end
    
    # If no editor is specified, use fish
    if test -z "$editor"
        set editor fish
    end

    if begin; set -q interactive[1]; or test "$editor" = fish; end
        set -l IFS
        if functions -q -- $funcname
            # Shadow IFS here to avoid array splitting in command substitution
            set init (functions -- $funcname | fish_indent --no-indent)
        end

        set -l prompt 'printf "%s%s%s> " (set_color green) '$funcname' (set_color normal)'
        # Unshadow IFS since the fish_title breaks otherwise
        set -e IFS
        if read -p $prompt -c "$init" -s cmd
            # Shadow IFS _again_ to avoid array splitting in command substitution
            set -l IFS
            eval (echo -n $cmd | fish_indent)
        end
        return 0
    end

    set tmpname (mktemp -t fish_funced.XXXXXXXXXX.fish)

    if functions -q -- $funcname
        functions -- $funcname > $tmpname
    else
        echo $init > $tmpname
    end
        # Repeatedly edit until it either parses successfully, or the user cancels
        # If the editor command itself fails, we assume the user cancelled or the file
        # could not be edited, and we do not try again
        while true
            if not eval $editor $tmpname
                        _ "Editing failed or was cancelled"
                        echo
                else
                if not source $tmpname
                                # Failed to source the function file. Prompt to try again.
                                echo # add a line between the parse error and the prompt
                                set -l repeat
                                set -l prompt (_ 'Edit the file again\? [Y/n]')
                                while test -z "$repeat"
                                        read -p "echo $prompt\  " repeat
                                end
                                if not contains $repeat n N no NO No nO
                                        continue
                                end
                                _ "Cancelled function editing"
                                echo
                        end
                end
                break
        end
    set -l stat $status
    rm -f $tmpname >/dev/null
    return $stat
end