Fortran · 4368 bytes Raw Blame History
1 ! ==============================================================================
2 ! Module: abbreviations
3 ! Purpose: Shell abbreviation functionality (fish-style auto-expanding shortcuts)
4 ! ==============================================================================
5 module abbreviations
6 use shell_types
7 use iso_fortran_env, only: output_unit, error_unit
8 implicit none
9
10 ! Maximum number of abbreviations
11 integer, parameter :: MAX_ABBREVIATIONS = 100
12
13 ! Abbreviation entry type
14 type :: abbr_entry_t
15 character(len=64) :: short_form = ''
16 character(len=256) :: expanded_form = ''
17 end type abbr_entry_t
18
19 ! Global abbreviation storage
20 type(abbr_entry_t), save :: abbr_table(MAX_ABBREVIATIONS)
21 integer, save :: num_abbreviations = 0
22
23 contains
24
25 ! Add or update an abbreviation
26 subroutine set_abbreviation(short_form, expanded_form)
27 character(len=*), intent(in) :: short_form, expanded_form
28 integer :: i, empty_slot
29
30 empty_slot = -1
31
32 ! Look for existing abbreviation or empty slot
33 do i = 1, MAX_ABBREVIATIONS
34 if (trim(abbr_table(i)%short_form) == trim(short_form)) then
35 ! Update existing abbreviation
36 abbr_table(i)%expanded_form = expanded_form
37 return
38 else if (len_trim(abbr_table(i)%short_form) == 0) then
39 if (empty_slot == -1) empty_slot = i
40 end if
41 end do
42
43 ! Add new abbreviation if there's space
44 if (empty_slot > 0) then
45 abbr_table(empty_slot)%short_form = short_form
46 abbr_table(empty_slot)%expanded_form = expanded_form
47 num_abbreviations = num_abbreviations + 1
48 else
49 write(error_unit, '(a)') 'abbr: too many abbreviations defined'
50 end if
51 end subroutine set_abbreviation
52
53 ! Get the expanded form of an abbreviation
54 function get_abbreviation(short_form) result(expanded_form)
55 character(len=*), intent(in) :: short_form
56 character(len=:), allocatable :: expanded_form
57 integer :: i
58
59 expanded_form = ''
60
61 do i = 1, MAX_ABBREVIATIONS
62 if (trim(abbr_table(i)%short_form) == trim(short_form)) then
63 expanded_form = trim(abbr_table(i)%expanded_form)
64 return
65 end if
66 end do
67 end function get_abbreviation
68
69 ! Check if a word is an abbreviation
70 function is_abbreviation(word) result(found)
71 character(len=*), intent(in) :: word
72 logical :: found
73 integer :: i
74
75 found = .false.
76 do i = 1, MAX_ABBREVIATIONS
77 if (trim(abbr_table(i)%short_form) == trim(word)) then
78 found = .true.
79 return
80 end if
81 end do
82 end function is_abbreviation
83
84 ! Remove an abbreviation
85 subroutine unset_abbreviation(short_form)
86 character(len=*), intent(in) :: short_form
87 integer :: i
88
89 do i = 1, MAX_ABBREVIATIONS
90 if (trim(abbr_table(i)%short_form) == trim(short_form)) then
91 abbr_table(i)%short_form = ''
92 abbr_table(i)%expanded_form = ''
93 num_abbreviations = num_abbreviations - 1
94 return
95 end if
96 end do
97
98 write(error_unit, '(a)') 'abbr: ' // trim(short_form) // ': not found'
99 end subroutine unset_abbreviation
100
101 ! Show all abbreviations
102 subroutine show_abbreviations()
103 integer :: i, count
104
105 count = 0
106 do i = 1, MAX_ABBREVIATIONS
107 if (len_trim(abbr_table(i)%short_form) > 0) then
108 write(output_unit, '(a)') 'abbr ' // trim(abbr_table(i)%short_form) // &
109 '=' // "'" // trim(abbr_table(i)%expanded_form) // "'"
110 count = count + 1
111 end if
112 end do
113
114 if (count == 0) then
115 write(output_unit, '(a)') 'No abbreviations defined'
116 end if
117 end subroutine show_abbreviations
118
119 ! Erase all abbreviations
120 subroutine erase_all_abbreviations()
121 integer :: i
122
123 do i = 1, MAX_ABBREVIATIONS
124 abbr_table(i)%short_form = ''
125 abbr_table(i)%expanded_form = ''
126 end do
127 num_abbreviations = 0
128 end subroutine erase_all_abbreviations
129
130 ! Expand abbreviation in current word (returns expanded form or empty if not an abbr)
131 ! This is called from readline when space/enter is pressed
132 function try_expand_abbreviation(word) result(expanded)
133 character(len=*), intent(in) :: word
134 character(len=:), allocatable :: expanded
135
136 if (is_abbreviation(word)) then
137 expanded = get_abbreviation(word)
138 else
139 expanded = ''
140 end if
141 end function try_expand_abbreviation
142
143 end module abbreviations
144