├── .gitattributes ├── img ├── look_up.png ├── settings.png ├── insert_odt.png ├── readme_icon.png ├── tray_icon.png └── locator_info.png ├── ZoteroWindowsPicker.ico ├── ZoteroWindowsPicker.ini ├── ZoteroWindowsPicker_v.0.9.2.exe ├── LICENSE ├── README.md └── ZoteroWindowsPicker_v.0.9.2.ahk /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /img/look_up.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/boan-anbo/Zotero-Citation-Picker-for-Windows/HEAD/img/look_up.png -------------------------------------------------------------------------------- /img/settings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/boan-anbo/Zotero-Citation-Picker-for-Windows/HEAD/img/settings.png -------------------------------------------------------------------------------- /img/insert_odt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/boan-anbo/Zotero-Citation-Picker-for-Windows/HEAD/img/insert_odt.png -------------------------------------------------------------------------------- /img/readme_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/boan-anbo/Zotero-Citation-Picker-for-Windows/HEAD/img/readme_icon.png -------------------------------------------------------------------------------- /img/tray_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/boan-anbo/Zotero-Citation-Picker-for-Windows/HEAD/img/tray_icon.png -------------------------------------------------------------------------------- /img/locator_info.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/boan-anbo/Zotero-Citation-Picker-for-Windows/HEAD/img/locator_info.png -------------------------------------------------------------------------------- /ZoteroWindowsPicker.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/boan-anbo/Zotero-Citation-Picker-for-Windows/HEAD/ZoteroWindowsPicker.ico -------------------------------------------------------------------------------- /ZoteroWindowsPicker.ini: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/boan-anbo/Zotero-Citation-Picker-for-Windows/HEAD/ZoteroWindowsPicker.ini -------------------------------------------------------------------------------- /ZoteroWindowsPicker_v.0.9.2.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/boan-anbo/Zotero-Citation-Picker-for-Windows/HEAD/ZoteroWindowsPicker_v.0.9.2.exe -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 boan-anbo 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Zotero Citation Picker for Windows 2 | 3 | > An AHK-based windows application to easily search, pick, and insert Zotero citations using keyboard shortcuts. 4 | 5 |
6 | 7 | ## Update History 8 | 9 | * 0.9.2 10 | * Added '[' ']' around Pandoc format output entries, e.g. `[@latourInquiryModesExistence2013]` 11 | . 12 | * Allow blank on locator (e.g. page) on ODT format. You can just press enter and not put in any page number now. 13 | 14 | * 0.9.1 15 | * Fixed admin priviledge notice. Longer picker window timeout. 16 | 17 | * 0.9 18 | * First Version 19 | 20 | ## Installation 21 | 22 | Windows: 23 | 24 | 1. Install [Zotero](https://www.zotero.org/download/) for Windows. 25 | 2. Install [Better BibTeX for Zotero](https://retorque.re/zotero-better-bibtex/installation/) add-on. 26 | 3. Install [RTF/ODF-Scan for Zotero ](https://zotero-odf-scan.github.io/zotero-odf-scan/) add-on. Optional but recommended for live citations update. 27 | 4. Download [Zotero Windows Picker](https://github.com/boan-anbo/Zotero-Citation-Picker-for-Windows/releases) and run the .exe, 28 | * Or compile the .ahk file using [AutoHotkey](https://www.autohotkey.com/) compiler. 29 | 30 | ## Function 31 | 32 | 1. Connect to [Better BibTeX for Zotero](https://retorque.re/zotero-better-bibtex/installation/). E.g. Insert citations in multiple formats, including formatted Zotero quick citation styles that you choose. 33 | 2. Connect to [RTF/ODF-Scan for Zotero ](https://zotero-odf-scan.github.io/zotero-odf-scan/). E.g. Insert citations in ODT format that you can link to Zotero and update the citations live. 34 | 3. Support a [ZoteroWinPicker.ico](C:\Users\Bo\Dropbox\NEra\Script\ZoteroWindowsPickerSrc\ZoteroWinPicker.ico) dding locator information for ODT format. E.g. adding page or chapter numbers. 35 | 4. Should be able insert Zotero citations everywhere, including Scrivener, Word, Google Docs, etc. 36 | 5. Written and compiled with [AutoHotkey](https://www.autohotkey.com/). The .exe should be portable. 37 | 38 | ## Usage 39 | 40 | 1. Choose initial setting for the first run. (If you don't need to manually input the pages numbers etc, turn off the "locator information" option.) 41 | 42 | ![](img/settings.png) 43 | 44 | 3. Use keyboard shortcut to call out Zotero Quick Format Citation window. 45 | 46 | 4. Search and pick your citation. 47 | 48 | ![](img/look_up.png) 49 | 50 | 5. When using ODT format, insert locator information, such as pages, chapters, etc. 51 | 52 | ![](img/locator_info.png) 53 | 54 | 6. Insert the citation(s) into the current active window or save to clipboard instead. 55 | 56 | ![](img/insert_odt.png) 57 | 58 | 7. Hover over or right click the tray icon for more. 59 | 60 | ![](img/tray_icon.png) 61 | 62 | ## Possible Issue 63 | 64 | * For the settings to take effect, the app needs admin priviledge to write to an .ini file to store the settings. If you encounter this problem, run it as administrator. Or, download the default ZoteroWindowsPicker.ini (otherwise unnecessary) into the same folder and retry. 65 | 66 | ## Prior Work 67 | 68 | * On Windows: 69 | * **[Zotero_scrivener_picker_windows](https://github.com/AmomentOfMusic/Zotero_scrivener_picker_windows)** 70 | 71 | * Other intergrations (vim, VS Code, Linux...): 72 | * Refer to Better BibTex documentation: https://retorque.re/zotero-better-bibtex/citing/cayw/ 73 | 74 | ## License 75 | 76 | 2019-20 Bo An 77 | -------------------------------------------------------------------------------- /ZoteroWindowsPicker_v.0.9.2.ahk: -------------------------------------------------------------------------------- 1 | #SingleInstance, Force 2 | #NoEnv 3 | ; Menu, Tray, Icon, ZoteroWinPicker.ico 4 | #Persistent 5 | Menu, Tray, NoStandard 6 | Menu, Tray, Add, Zotero Picker Settings, openSettings 7 | Menu, Tray, Add 8 | Menu, Tray, Add, Restart, reload 9 | Menu, Tray, Add 10 | Menu, Tray, Add, About, about 11 | Menu, Tray, Add 12 | Menu, Tray, Add, Exit, exit 13 | 14 | v = v.0.9.2 15 | iniFileName = ZoteroWindowsPicker.ini 16 | pickerWindowTitle = Quick Format Citation 17 | formatOptions := {"Latex":"latex","Biblatex":"biblatex","MultiMarkdown":"mmd","Pandoc":"pandoc","Zotero ODF Scan":"scannable-cite","Formatted Zotero Quick Citation":"formatted-citation","Formatted Zotero Quick Bibliography":"formatted-bibliography","JSON":"json"} 18 | odtLocatorOptions := {"Article":"art.","Chapter":"ch.","Subchapter":"subch.","Column":"col.","Figure":"fig.","Line":"l.","Note":"n.","Issue":"no.","Opus":"op.","Page":"p.","Paragraph":"para.","Subparagraph":"subpara.","Part":"pt.","Rule":"r.","Section":"sec.","Subsection":"subsec.","Section":"Sec.","Sub verbo":"sv.","Schedule":"sch.","Title":"tit.","Verse":"vrs.","Volume":"vol."} 19 | 20 | Start := A_TickCount 21 | loop, 26 22 | { 23 | letterList .= chr(A_Index + 64) . "|" 24 | } 25 | loop, 10 26 | { 27 | letterList .= chr(A_Index + 47) . "|" 28 | } 29 | loop, 12 30 | { 31 | letterList .= "F" . A_Index . "|" 32 | } 33 | for key, value in formatOptions 34 | { 35 | formatOptionList .= key . "|" 36 | } 37 | letterListArray := StrSplit(letterList,"|") 38 | formatOptionListArray := StrSplit(formatOptionList,"|") 39 | 40 | IfNotExist, %iniFileName% 41 | { 42 | MsgBox, ,Zotero Windows Picker, 43 | ( 44 | Initialial Settings 45 | ) 46 | currentFormat := "Formatted Zotero Quick Bibliography" 47 | currentShortcut := "+!F" 48 | locatorCheck := 0 49 | insertCheck := 1 50 | notificationCheck := 1 51 | openSettings() 52 | } else { 53 | readIni() 54 | } 55 | 56 | 57 | if (currentFormat = "Zotero ODF Scan") 58 | { 59 | for key, value in odtLocatorOptions 60 | { 61 | odtLocatorOptionsList .= key . "|" 62 | } 63 | } 64 | formatedShortcut := formatShortcut(currentShortcut) 65 | Menu, Tray, Tip , Format:`n %currentFormat%`n`nShortcut:`n %formatedShortcut%`n 66 | 67 | currentFormatString := "format=" . formatOptions[currentFormat] 68 | requestString := "http://127.0.0.1:23119/better-bibtex/cayw?" . currentFormatString 69 | try{ 70 | Hotkey, %currentShortcut%, getRef 71 | } catch { 72 | MsgBox, , Error, 73 | ( 74 | 75 | Error with %iniFileName% settings file. 76 | 77 | Delete %iniFileName% and restart. 78 | 79 | ) 80 | } 81 | return 82 | 83 | getRef: 84 | IfWinExist, Quick Format Citation 85 | WinActivate, Quick Format Citation 86 | global tempClipboard := Clipboard 87 | Clipboard := "" 88 | IfWinNotExist, ahk_exe zotero.exe 89 | { 90 | MsgBox, , Zotero Not Found, Please Launch Zotero for Windows First. 91 | Return 92 | } 93 | WinGetActiveTitle, activeWindow 94 | req := ComObjCreate("WinHttp.WinHttpRequest.5.1") 95 | req.SetTimeouts(0, 60000, 30000, 120000) 96 | req.Open("GET", requestString, true) 97 | req.SetRequestHeader("Content-Type", "application/json") 98 | try 99 | { 100 | req.Send() 101 | req.WaitForResponse(120) 102 | } catch { 103 | WinClose, %pickerWindowTitle% 104 | return 105 | } 106 | if (!req.ResponseText){ 107 | return 108 | } 109 | if (InStr(req.ResponseText, "CAYW failed: Error: scannable-cite")) { 110 | errorMessage := req.ResponseText 111 | MsgBox,, Remainder, 112 | ( 113 | 114 | To use ODF format, you need to install "RTF/ODF Scan for Zotero" plugin. 115 | 116 | See: https://zotero-odf-scan.github.io/zotero-odf-scan/ 117 | 118 | To switch to other formats, go to Settings. 119 | 120 | 121 | Error Message: %errorMessage% 122 | 123 | ) 124 | return 125 | } else if (InStr(req.ResponseText, "CAYW failed: Error: formatted")) { 126 | errorMessage := req.ResponseText 127 | MsgBox,, Remainder, 128 | ( 129 | 130 | To use formatted citation, set Zotero default quick-copy format to a citation style first. 131 | 132 | If you want to switch to other formats, go to Settings. 133 | 134 | 135 | Error Message: %errorMessage% 136 | 137 | ) 138 | return 139 | } 140 | else if (InStr(req.ResponseText, "No endpoint")) { 141 | errorMessage := req.ResponseText 142 | MsgBox,, Remainder, 143 | ( 144 | 145 | Cannot connect to Better BibTeX for Zotero add-on. Install it and restart Zotero. 146 | 147 | See: https://retorque.re/zotero-better-bibtex/ 148 | 149 | 150 | Error Message: %errorMessage% 151 | 152 | ) 153 | return 154 | } 155 | else if (InStr(req.ResponseText, "CAYW failed: translation")) { 156 | errorMessage := req.ResponseText 157 | MsgBox,, Remainder, 158 | ( 159 | 160 | Cannot find ODT translator. Check or reinstall Zotero ODT Scan add-on. 161 | 162 | See: https://zotero-odf-scan.github.io/zotero-odf-scan/ 163 | 164 | 165 | Error Message: %errorMessage% 166 | 167 | ) 168 | return 169 | } 170 | citationStrings := req.ResponseText 171 | if (currentFormat = "Zotero ODF Scan" && locatorCheck = 1) 172 | { 173 | IfWinExist, Locator Information 174 | Gui,2:Destroy 175 | rList := formatResult(citationStrings) 176 | for index, value in rList 177 | { 178 | Gui, 2: Add, Text, , %index%. %value% 179 | Gui, 2: Add, DropDownList, vlocator%index% Choose9, %odtLocatorOptionsList% 180 | Gui, 2: Add, Edit, vlocatorNumber%index% 181 | } 182 | Gui,2: Add, Button, w120 default, OK 183 | Gui,2: Add, Button, w120 x+5 , Cancel 184 | Gui,2: Show,, Locator Information 185 | return 186 | 2GuiClose: 187 | 2ButtonCancel: 188 | Gui 2: Destroy 189 | return 190 | 2ButtonOK: 191 | Gui,2: Submit 192 | Gui 2: Destroy 193 | pList := [] 194 | for index, value in rList 195 | { 196 | locatorString := "" 197 | locator := "locator" index 198 | locator := %locator% 199 | ln := "locatorNumber" index 200 | ln := %ln% 201 | if (ln){ 202 | locatorString := "|" . " " . odtLocatorOptions[locator] . " " . ln 203 | value := RegExReplace(value, "\|", locatorString,, 1, InStr(value, "|",,, 2)) 204 | pList.Push(value) 205 | } 206 | ; Add an alternative if the user it not inputing any page numbers 207 | else { 208 | locatorString := "|" 209 | value := RegExReplace(value, "\|", locatorString,, 1, InStr(value, "|",,, 2)) 210 | pList.Push(value) 211 | } 212 | } 213 | citationStrings := "" 214 | for key, value in pList 215 | { 216 | citationStrings .= value 217 | } 218 | outputResult(citationStrings) 219 | return 220 | } else if (currentFormat = "Pandoc") { 221 | ; Added '[' ']' around Pandoc format output. 222 | citationStrings := "[" . citationStrings . "]" 223 | outputResult(citationStrings) 224 | return 225 | } 226 | else { 227 | outputResult(citationStrings) 228 | return 229 | } 230 | return 231 | 232 | outputResult(citationStrings) { 233 | global 234 | Clipboard := "" 235 | Clipboard := citationStrings 236 | ClipWait 237 | ; WinActivate, %activeWindow% 238 | ; WinWaitActive, %activeWindow% 239 | if (insertCheck = 1) 240 | { 241 | if (notificationCheck = 1) 242 | { 243 | TrayTip, Citation Inserted, %citationStrings%, 4, 244 | 245 | } 246 | Sleep, 500 247 | Send, ^v 248 | WinWait A 249 | Clipboard := tempClipboard 250 | }else { 251 | if (notificationCheck = 1) 252 | { 253 | TrayTip, Saved to Clipboard, %citationStrings%, 4, 254 | } 255 | } 256 | } 257 | return 258 | 259 | formatResult(r) { 260 | r := StrReplace(r,"}{","};{") 261 | rList := StrSplit(r,";") 262 | return rList 263 | } 264 | return 265 | 266 | About() { 267 | MsgBox, , Zotero Windows Picker %v%, 268 | ( 269 | Requirement: 270 | 271 | 1. Zotero For Window 272 | 2. Better BibTeX for Zotero 273 | 3. RTF/ODF Scan for Zotero (for ODF format, optional) 274 | 275 | 276 | Bo An 277 | 2019-20 278 | Scripted in AHK. 279 | ) 280 | } 281 | 282 | readIni() { 283 | global 284 | 285 | IniRead, currentFormat, %iniFileName%, Settings, currentFormat 286 | IniRead, currentShortcut, %iniFileName%, Settings, currentShortcut 287 | IniRead, locatorCheck, %iniFileName%, Settings, locatorCheck 288 | IniRead, insertCheck, %iniFileName%, Settings, insertCheck 289 | IniRead, notificationCheck, %iniFileName%, Settings, notificationCheck 290 | 291 | } 292 | 293 | formatShortcut(s){ 294 | s := StrReplace(s, "+", "Shift + ") 295 | s := StrReplace(s, "!", "Alt + ") 296 | s := StrReplace(s, "^", "Ctrl + ") 297 | return s 298 | } 299 | 300 | openSettings(){ 301 | global 302 | IfWinExist, Zotero Windows Picker Settings 303 | { 304 | ; WinActivate, Zotero Windows Picker Settings 305 | return 306 | } 307 | 308 | 309 | IfExist, %iniFileName% 310 | readIni() 311 | checkCtrl := InStr(currentShortcut, "^") ? "Checked" : "" 312 | checkAlt := InStr(currentShortcut, "!") ? "Checked" : "" 313 | checkShift := InStr(currentShortcut, "+") ? "Checked" : "" 314 | currentKeyChoice := RegExReplace(currentShortcut,"[!+^]") 315 | checkLocator := locatorCheck ? "Checked" : "" 316 | checkInsert := insertCheck ? "Checked" : "" 317 | checkNotification := notificationCheck ? "Checked": "" 318 | 319 | for index, value in letterListArray 320 | if (value = currentKeyChoice) 321 | checkKey := "Choose" . index 322 | for index, value in formatOptionListArray 323 | if (value = currentFormat) 324 | checkFormat := "Choose" . index 325 | 326 | ; GUI for Settings 327 | Gui, Add, Text, w75 y10 , Hotkey: 328 | Gui, Add, Checkbox, w65 x+15 vctrlCheck %checkCtrl% , Ctrl 329 | 330 | Gui, Add, Checkbox, w65 x+1 vshiftCheck %checkShift% , Shift 331 | 332 | Gui, Add, Checkbox, w65 x+1 valtCheck %checkAlt% , Alt 333 | 334 | Gui, Add, Text, w45 x+1 , + 335 | 336 | Gui, Add, DropDownList, w90 x+1 vchosenLetter %checkKey% , %letterList% 337 | 338 | Gui, Add, Text, x10, 339 | 340 | Gui, Add, Text, w75 x10, Citation Format: 341 | 342 | Gui, Add, DropDownList, w200 x+25 vchosenFormat %checkFormat% , %formatOptionList% 343 | 344 | Gui, Add, Link, x110, * Use the ODT format if you want link and update your citations with Zotero. 345 | Gui, Add, Link, x110, * For details of different formats, see Better BibTex documentation. 346 | 347 | Gui, Add, Text, x10, 348 | 349 | Gui, Add, Text, w75 x10, Zotero ODT Scan: 350 | Gui, Add, Checkbox, x+15 vlocatorCheck %checkLocator%, Input Locator Information (add informations like pages etc during insertion) 351 | Gui, Add, Link, x110, * For detailed Zotero ODT Scan instructions, see the Add-on website 352 | 353 | Gui, Add, Text, x10, 354 | 355 | Gui, Add, Text, w75 x10, Export: 356 | Gui, Add, Checkbox, x+15 vinsertCheck %checkInsert%, Automatically Insert Citations (uncheck to save to clipboard only) 357 | 358 | Gui, Add, Text, x10, 359 | 360 | Gui, Add, Text, w75 x10, Notification: 361 | Gui, Add, Checkbox, x+15 vnotificationCheck %checkNotification%, Show Notification 362 | 363 | Gui, Add, Text, x10, 364 | 365 | Gui, Add, Button, w160 default, Save 366 | Gui, Add, Button, w140 x+10, Cancel 367 | Gui, Add, Link, x+10 w130 Right, %v% by Bo An via AHK. 368 | 369 | Gui, Show,, Zotero Windows Picker Settings 370 | return 371 | 372 | ButtonCancel: 373 | GuiClose: 374 | Gui, Destroy 375 | return 376 | ButtonSave: 377 | Gui, Submit 378 | Gui, Destroy 379 | if(ctrlCheck){ 380 | chosenShortcut .= "^" 381 | } 382 | if(shiftCheck){ 383 | chosenShortcut .= "+" 384 | } 385 | if(altCheck){ 386 | chosenShortcut .= "!" 387 | } 388 | chosenShortcut .= chosenLetter 389 | IniWrite, %chosenFormat%, %iniFileName%, Settings, currentFormat 390 | IniWrite, %chosenShortcut%, %iniFileName%, Settings, currentShortcut 391 | IniWrite, %locatorCheck%, %iniFileName%, Settings, locatorCheck 392 | IniWrite, %insertCheck%, %iniFileName%, Settings, insertCheck 393 | IniWrite, %notificationCheck%, %iniFileName%, Settings, notificationCheck 394 | IfNotExist, %iniFileName% 395 | { 396 | MsgBox, , Error, 397 | ( 398 | 399 | Cannot create %iniFileName% to save settings. 400 | 401 | Please run again as Administrator. 402 | 403 | ) 404 | ExitApp 405 | 406 | } else { 407 | MsgBox, Settings Saved 408 | } 409 | Reload 410 | } 411 | 412 | OnWin(Event, Hwnd) 413 | { 414 | Static This_Func_Name := "OnWin" 415 | Static RunAtScriptExecution1 := DllCall( "RegisterShellHookWindow", UInt, A_ScriptHwnd) 416 | Static SH_MsgNum := DllCall( "RegisterWindowMessage", Str,"SHELLHOOK" ) 417 | Static RunAtScriptExecution2 := OnMessage(SH_MsgNum, Func(This_Func_Name), 1000) 418 | ; ((event = 32772) || (event = 4)) 419 | if (event = 1) 420 | { 421 | WinGetTitle, Title_Found, % "ahk_id" Hwnd 422 | 423 | if (Title_Found = "Quick Format Citation") 424 | { 425 | IfWinNotActive, Quick Format Citation 426 | { 427 | WinActivate, Quick Format Citation 428 | } 429 | } 430 | } 431 | } 432 | 433 | reload(){ 434 | reload 435 | } 436 | 437 | exit() { 438 | ExitApp 439 | } --------------------------------------------------------------------------------