mirror of
https://github.com/compiler-explorer/compiler-explorer.git
synced 2025-12-27 07:04:04 -05:00
Compiler Picker UI Improvements (#4849)
Alrighty, round 2! This PR makes the compiler picker dropdown taller (max height is to the bottom of the screen)  I've added a toolbar button for opening the popout as well as a button when the dropdown is open:   Then the modal interface allows text searching, filtering by compiler category, and filtering by compiler instruction set. In the future I'd like to replace the instructionSet property with an architecture property so the filtering here can be a little better.  Demo of the category filtering:  The text filtering highlights results the same as tomselect does:  I moved the favorites permanently to their own column so compilers aren't jarringly shifted around the screen when favoriting / unfavoriting. Also added media queries so the modal looks ok on smaller screens:   I think the only other two changes from the first PR are now the active compiler is highlighted like it is in the tomselect dropdown and I figured out how to reliably focus the search bar on modal open. (Oh, and now clicking a compiler actually does something!) --------- Co-authored-by: Matt Godbolt <matt@godbolt.org>
This commit is contained in:
@@ -20,6 +20,8 @@ group.gnat.licenseLink=https://gcc.gnu.org/onlinedocs/gcc/Copying.html
|
||||
group.gnat.licenseName=GNU General Public License
|
||||
group.gnat.licensePreamble=Copyright (c) 2007 Free Software Foundation, Inc. <a href="https://fsf.org/" target="_blank">https://fsf.org/</a>
|
||||
group.gnat.supportsBinaryObject=true
|
||||
group.gnat.instructionSet=amd64
|
||||
group.gnat.compilerCategories=gcc
|
||||
|
||||
compiler.gnat82.exe=/opt/compiler-explorer/gcc-8.2.0/bin/gnatmake
|
||||
compiler.gnat82.semver=8.2
|
||||
@@ -54,6 +56,7 @@ group.gnatcross.isSemVer=true
|
||||
group.gnatcross.licenseLink=https://gcc.gnu.org/onlinedocs/gcc/Copying.html
|
||||
group.gnatcross.licenseName=GNU General Public License
|
||||
group.gnatcross.licensePreamble=Copyright (c) 2007 Free Software Foundation, Inc. <a href="https://fsf.org/" target="_blank">https://fsf.org/</a>
|
||||
group.gnatcross.compilerCategories=gcc
|
||||
|
||||
################################
|
||||
# GNAT for sparc
|
||||
|
||||
@@ -12,6 +12,7 @@ group.nasm.options=
|
||||
group.nasm.isSemVer=true
|
||||
group.nasm.baseName=NASM
|
||||
group.nasm.compilerType=nasm
|
||||
group.nasm.instructionSet=amd64
|
||||
compiler.nasm21202.semver=2.12.02
|
||||
compiler.nasm21202.exe=/opt/compiler-explorer/nasm-2.12.02/nasm
|
||||
compiler.nasm21302.semver=2.13.02
|
||||
@@ -27,6 +28,7 @@ group.gnuas.versionFlag=--version
|
||||
group.gnuas.options=-g
|
||||
group.gnuas.isSemVer=true
|
||||
group.gnuas.baseName=x86-64 binutils
|
||||
group.gnuas.instructionSet=amd64
|
||||
compiler.gnuas72.exe=/opt/compiler-explorer/gcc-7.2.0/bin/as
|
||||
compiler.gnuas72.semver=2.27
|
||||
compiler.gnuas73.exe=/opt/compiler-explorer/gcc-7.3.0/bin/as
|
||||
@@ -51,6 +53,7 @@ group.gnuasarm.isSemVer=true
|
||||
group.gnuasarm.baseName=ARM binutils
|
||||
group.gnuasarm.supportsExecute=false
|
||||
group.gnuasarm.objdumper=/opt/compiler-explorer/arm/gcc-10.2.0/arm-unknown-linux-gnueabihf/bin/arm-unknown-linux-gnueabihf-objdump
|
||||
group.gnuasarm.instructionSet=arm32
|
||||
|
||||
compiler.gnuasarmhfg54.exe=/opt/compiler-explorer/arm/gcc-5.4.0/arm-unknown-linux-gnueabihf/bin/arm-unknown-linux-gnueabihf-as
|
||||
compiler.gnuasarmhfg54.name=ARMhf binutils 2.28
|
||||
@@ -79,6 +82,7 @@ group.gnuasarm64.isSemVer=true
|
||||
group.gnuasarm64.baseName=AArch64 binutils
|
||||
group.gnuasarm64.supportsExecute=false
|
||||
group.gnuasarm64.objdumper=/opt/compiler-explorer/arm64/gcc-10.2.0/aarch64-unknown-linux-gnu/aarch64-unknown-linux-gnu/bin/objdump
|
||||
group.gnuasarm64.instructionSet=aarch64
|
||||
|
||||
compiler.gnuasarm64g630.exe=/opt/compiler-explorer/arm64/gcc-6.3.0/aarch64-unknown-linux-gnueabi/bin/aarch64-unknown-linux-gnueabi-as
|
||||
compiler.gnuasarm64g630.name=AArch64 binutils 2.28
|
||||
@@ -100,6 +104,7 @@ group.llvmas.options=-filetype=obj -o example.o
|
||||
group.llvmas.versionRe=LLVM version .*
|
||||
group.llvmas.isSemVer=true
|
||||
group.llvmas.baseName=x86-64 clang
|
||||
group.llvmas.instructionSet=amd64
|
||||
compiler.llvmas30.exe=/opt/compiler-explorer/clang+llvm-3.0-x86_64-linux-Ubuntu-11_10/bin/llvm-mc
|
||||
compiler.llvmas30.semver=3.0.0
|
||||
compiler.llvmas31.exe=/opt/compiler-explorer/clang+llvm-3.1-x86_64-linux-ubuntu_12.04/bin/llvm-mc
|
||||
@@ -175,6 +180,7 @@ group.ptxas.compilerType=ptxas
|
||||
group.ptxas.demangler=
|
||||
group.ptxas.isSemVer=true
|
||||
group.ptxas.supportsExecute=false
|
||||
group.ptxas.instructionSet=ptx
|
||||
|
||||
compiler.ptxasnvcc91.objdumper=/opt/compiler-explorer/cuda/9.1.85/bin/nvdisasm
|
||||
compiler.ptxasnvcc91.semver=9.1.85
|
||||
|
||||
@@ -29,6 +29,7 @@ group.gcc86.licenseLink=https://gcc.gnu.org/onlinedocs/gcc/Copying.html
|
||||
group.gcc86.licenseName=GNU General Public License
|
||||
group.gcc86.licensePreamble=Copyright (c) 2007 Free Software Foundation, Inc. <a href="https://fsf.org/" target="_blank">https://fsf.org/</a>
|
||||
group.gcc86.supportsBinaryObject=true
|
||||
group.gcc86.compilerCategories=gcc
|
||||
|
||||
compiler.g412.exe=/opt/compiler-explorer/gcc-4.1.2/bin/g++
|
||||
compiler.g412.semver=4.1.2
|
||||
@@ -208,6 +209,7 @@ group.clang.licenseName=LLVM Apache 2
|
||||
group.clang.licenseLink=https://github.com/llvm/llvm-project/blob/main/LICENSE.TXT
|
||||
group.clang.licensePreamble=The LLVM Project is under the Apache License v2.0 with LLVM Exceptions
|
||||
group.clang.supportsBinaryObject=true
|
||||
group.clang.compilerCategories=clang
|
||||
|
||||
# Ancient clangs don't support GCC toolchain option
|
||||
compiler.clang30.exe=/opt/compiler-explorer/clang+llvm-3.0-x86_64-linux-Ubuntu-11_10/bin/clang++
|
||||
@@ -352,6 +354,7 @@ group.clangx86trunk.unwiseOptions=-march=native
|
||||
group.clangx86trunk.supportsPVS-Studio=true
|
||||
group.clangx86trunk.supportsSonar=true
|
||||
group.clangx86trunk.ldPath=${exePath}/../lib|${exePath}/../lib/x86_64-unknown-linux-gnu
|
||||
group.clangx86trunk.compilerCategories=clang
|
||||
|
||||
compiler.clang_trunk.exe=/opt/compiler-explorer/clang-trunk/bin/clang++
|
||||
compiler.clang_trunk.semver=(trunk)
|
||||
@@ -421,6 +424,7 @@ group.clang-rocm.supportsSonar=true
|
||||
group.clang-rocm.licenseName=LLVM Apache 2 and NCSA
|
||||
group.clang-rocm.licenseLink=https://github.com/RadeonOpenCompute/llvm-project/blob/amd-stg-open/LICENSE.TXT
|
||||
# and https://github.com/RadeonOpenCompute/ROCm-Device-Libs/blob/amd-stg-open/LICENSE.TXT
|
||||
group.clang-rocm.compilerCategories=clang
|
||||
|
||||
compiler.clang-rocm-trunk.exe=/opt/compiler-explorer/clang-rocm-trunk/bin/clang++
|
||||
compiler.clang-rocm-trunk.semver=(amd-stg-open)
|
||||
@@ -463,6 +467,7 @@ group.armclang32.objdumper=/opt/compiler-explorer/arm/gcc-10.2.0/arm-unknown-lin
|
||||
group.armclang32.licenseName=LLVM Apache 2
|
||||
group.armclang32.licenseLink=https://github.com/llvm/llvm-project/blob/main/LICENSE.TXT
|
||||
group.armclang32.licensePreamble=The LLVM Project is under the Apache License v2.0 with LLVM Exceptions
|
||||
group.armclang32.compilerCategories=clang
|
||||
|
||||
compiler.armv7-clang1101.exe=/opt/compiler-explorer/clang-11.0.1/bin/clang++
|
||||
compiler.armv7-clang1101.semver=11.0.1
|
||||
@@ -508,6 +513,7 @@ group.armclang64.instructionSet=aarch64
|
||||
group.armclang64.licenseName=LLVM Apache 2
|
||||
group.armclang64.licenseLink=https://github.com/llvm/llvm-project/blob/main/LICENSE.TXT
|
||||
group.armclang64.licensePreamble=The LLVM Project is under the Apache License v2.0 with LLVM Exceptions
|
||||
group.armclang64.compilerCategories=clang
|
||||
|
||||
compiler.armv8-clang1500.exe=/opt/compiler-explorer/clang-15.0.0/bin/clang++
|
||||
compiler.armv8-clang1500.semver=15.0.0
|
||||
@@ -572,6 +578,7 @@ group.mosclang-trunk.compilerType=llvmmos
|
||||
group.mosclang-trunk.isSemVer=true
|
||||
group.mosclang-trunk.objdumper=/opt/compiler-explorer/llvm-mos-trunk/bin/llvm-objdump
|
||||
group.mosclang-trunk.objdumperType=llvm
|
||||
group.mosclang-trunk.compilerCategories=clang
|
||||
|
||||
compiler.mos-nes-cnrom-trunk.exe=/opt/compiler-explorer/llvm-mos-trunk/bin/mos-nes-cnrom-clang++
|
||||
compiler.mos-nes-cnrom-trunk.semver=nes-cnrom
|
||||
@@ -616,6 +623,7 @@ group.rv32clang.options=-target riscv32-unknown-elf -march=rv32gc -mabi=ilp32d -
|
||||
group.rv32clang.objdumper=/opt/compiler-explorer/riscv32/gcc-10.2.0/riscv32-unknown-elf/bin/riscv32-unknown-elf-objdump
|
||||
group.rv32clang.baseName=RISC-V rv32gc clang
|
||||
group.rv32clang.groupName=RISC-V 32 Clang
|
||||
group.rv32clang.compilerCategories=clang
|
||||
|
||||
compiler.rv32-clang900.exe=/opt/compiler-explorer/clang-9.0.0/bin/clang++
|
||||
compiler.rv32-clang900.semver=9.0.0
|
||||
@@ -658,6 +666,7 @@ group.rv64clang.options=-target riscv64-unknown-linux-gnu -march=rv64gc -mabi=lp
|
||||
group.rv64clang.objdumper=/opt/compiler-explorer/riscv64/gcc-10.2.0/riscv64-unknown-linux-gnu/bin/riscv64-unknown-linux-gnu-objdump
|
||||
group.rv64clang.baseName=RISC-V rv64gc clang
|
||||
group.rv64clang.groupName=RISC-V 64 Clang
|
||||
group.rv64clang.compilerCategories=clang
|
||||
|
||||
compiler.rv64-clang900.exe=/opt/compiler-explorer/clang-9.0.0/bin/clang++
|
||||
compiler.rv64-clang900.semver=9.0.0
|
||||
@@ -703,6 +712,7 @@ group.wasmclang.supportsBinary=false
|
||||
group.wasmclang.licenseName=LLVM Apache 2
|
||||
group.wasmclang.licenseLink=https://github.com/llvm/llvm-project/blob/main/LICENSE.TXT
|
||||
group.wasmclang.licensePreamble=The LLVM Project is under the Apache License v2.0 with LLVM Exceptions
|
||||
group.wasmclang.compilerCategories=clang
|
||||
|
||||
compiler.wasm32clang.exe=/opt/compiler-explorer/clang-trunk/bin/clang++
|
||||
compiler.wasm32clang.demangler=/opt/compiler-explorer/gcc-snapshot/bin/c++filt
|
||||
@@ -719,6 +729,8 @@ group.icc.groupName=ICC x86-64
|
||||
group.icc.baseName=x86-64 icc
|
||||
group.icc.isSemVer=true
|
||||
group.icc.licensePreamble=Proprietary, with thanks to Intel for the license
|
||||
group.icc.compilerCategories=icc
|
||||
group.icc.instructionSet=amd64
|
||||
|
||||
compiler.icc1301.exe=/opt/compiler-explorer/intel/bin/icc
|
||||
compiler.icc1301.alias=/opt/intel/bin/icc
|
||||
@@ -806,6 +818,8 @@ group.icx.compilerType=clang-intel
|
||||
group.icx.licenseName=LLVM Apache 2
|
||||
group.icx.licenseLink=https://github.com/intel/llvm/blob/sycl/LICENSE.TXT
|
||||
group.icx.licensePreamble=The LLVM Project is under the Apache License v2.0 with LLVM Exceptions
|
||||
group.icx.compilerCategories=icc
|
||||
group.icx.instructionSet=amd64
|
||||
|
||||
compiler.icx202112.exe=/opt/compiler-explorer/intel-cpp-2021.1.2.63/compiler/latest/linux/bin/icpx
|
||||
compiler.icx202112.ldPath=/opt/compiler-explorer/intel-cpp-2021.1.2.63/compiler/latest/linux/compiler/lib/intel64_lin:/opt/compiler-explorer/intel-cpp-2021.1.2.63/compiler/latest/linux/lib
|
||||
@@ -877,6 +891,7 @@ group.cross.supportsExecute=false
|
||||
group.cross.licenseLink=https://gcc.gnu.org/onlinedocs/gcc/Copying.html
|
||||
group.cross.licenseName=GNU General Public License
|
||||
group.cross.licensePreamble=Copyright (c) 2007 Free Software Foundation, Inc. <a href="https://fsf.org/" target="_blank">https://fsf.org/</a>
|
||||
group.cross.compilerCategories=gcc
|
||||
|
||||
###############################
|
||||
# Cross for BPF
|
||||
@@ -893,6 +908,7 @@ group.clangbpf.isSemVer=true
|
||||
group.clangbpf.options=-target bpf
|
||||
group.clangbpf.objdumper=/opt/compiler-explorer/clang-trunk/bin/llvm-objdump
|
||||
group.clangbpf.objdumperType=llvm
|
||||
group.clangbpf.compilerCategories=clang
|
||||
|
||||
compiler.bpfclangtrunk.exe=/opt/compiler-explorer/clang-trunk/bin/clang++
|
||||
compiler.bpfclangtrunk.semver=(trunk)
|
||||
@@ -1536,6 +1552,7 @@ group.mips-clang.supportsBinary=false
|
||||
group.mips-clang.supportsBinaryObject=false
|
||||
group.mips-clang.supportsExecute=false
|
||||
group.mips-clang.options=-target mips-elf
|
||||
group.mips-clang.compilerCategories=clang
|
||||
|
||||
compiler.mips-clang1500.exe=/opt/compiler-explorer/clang-15.0.0/bin/clang++
|
||||
compiler.mips-clang1500.semver=15.0.0
|
||||
@@ -1554,6 +1571,7 @@ group.mipsel-clang.supportsBinary=false
|
||||
group.mipsel-clang.supportsBinaryObject=false
|
||||
group.mipsel-clang.supportsExecute=false
|
||||
group.mipsel-clang.options=-target mipsel-elf
|
||||
group.mipsel-clang.compilerCategories=clang
|
||||
|
||||
compiler.mipsel-clang1500.exe=/opt/compiler-explorer/clang-15.0.0/bin/clang++
|
||||
compiler.mipsel-clang1500.semver=15.0.0
|
||||
@@ -1572,6 +1590,7 @@ group.mips64-clang.supportsBinary=false
|
||||
group.mips64-clang.supportsBinaryObject=false
|
||||
group.mips64-clang.supportsExecute=false
|
||||
group.mips64-clang.options=-target mips64-elf
|
||||
group.mips64-clang.compilerCategories=clang
|
||||
|
||||
compiler.mips64-clang1500.exe=/opt/compiler-explorer/clang-15.0.0/bin/clang++
|
||||
compiler.mips64-clang1500.semver=15.0.0
|
||||
@@ -1590,6 +1609,7 @@ group.mips64el-clang.supportsBinary=false
|
||||
group.mips64el-clang.supportsBinaryObject=false
|
||||
group.mips64el-clang.supportsExecute=false
|
||||
group.mips64el-clang.options=-target mips64el-elf
|
||||
group.mips64el-clang.compilerCategories=clang
|
||||
|
||||
compiler.mips64el-clang1500.exe=/opt/compiler-explorer/clang-15.0.0/bin/clang++
|
||||
compiler.mips64el-clang1500.semver=15.0.0
|
||||
@@ -1672,6 +1692,7 @@ compiler.mipselg1220.demangler=/opt/compiler-explorer/mipsel/gcc-12.2.0/mipsel-m
|
||||
group.mips64el.groupName=MIPS64EL GCC
|
||||
group.mips64el.compilers=mips564el:mips64elg1210:mips64elg1220
|
||||
group.mips64el.baseName=mips64 (el) gcc
|
||||
group.mips64el.compilerCategories=gcc
|
||||
|
||||
compiler.mips564el.exe=/opt/compiler-explorer/mips64el/gcc-5.4.0/mips64el-unknown-linux-gnu/bin/mips64el-unknown-linux-gnu-g++
|
||||
compiler.mips564el.semver=5.4
|
||||
@@ -1882,6 +1903,8 @@ group.cl.demanglerType=win32
|
||||
group.cl.supportsBinary=false
|
||||
group.cl.objdumper=
|
||||
group.cl.isSemVer=true
|
||||
group.cl.compilerCategories=msvc
|
||||
group.cl.instructionSet=amd64
|
||||
group.cl19.groupName=WINE MSVC 2017
|
||||
group.cl19.compilers=cl19_64:cl19_32:cl19_arm
|
||||
group.cl19.options=/I/opt/compiler-explorer/windows/10.0.10240.0/ucrt/ /I/opt/compiler-explorer/windows/19.10.25017/lib/native/include/
|
||||
@@ -1895,7 +1918,7 @@ compiler.cl19_32.semver=19.10.25017
|
||||
compiler.cl19_arm.exe=/opt/compiler-explorer/windows/19.10.25017/lib/native/bin/amd64_arm/cl.exe
|
||||
compiler.cl19_arm.name=ARM msvc v19.10 (WINE)
|
||||
compiler.cl19_arm.semver=19.10.25017
|
||||
compiler.cl19_arm.instructionSet=arm
|
||||
compiler.cl19_arm.instructionSet=arm32
|
||||
|
||||
group.cl19_2015_u3.groupName=WINE MSVC 2015
|
||||
group.cl19_2015_u3.compilers=cl19_2015_u3_64:cl19_2015_u3_32:cl19_2015_u3_arm
|
||||
@@ -1910,7 +1933,7 @@ compiler.cl19_2015_u3_32.semver=19.00.24210
|
||||
compiler.cl19_2015_u3_arm.exe=/opt/compiler-explorer/windows/19.00.24210/bin/amd64_arm/cl.exe
|
||||
compiler.cl19_2015_u3_arm.name=ARM msvc v19.0 (WINE)
|
||||
compiler.cl19_2015_u3_arm.semver=19.00.24210
|
||||
compiler.cl19_2015_u3_arm.instructionSet=arm
|
||||
compiler.cl19_2015_u3_arm.instructionSet=arm32
|
||||
|
||||
group.cl_new.groupName=WINE MSVC 2017
|
||||
group.cl_new.compilers=cl_new_64:cl_new_32:cl_new_arm32:cl_new_arm64
|
||||
@@ -2018,6 +2041,8 @@ group.cxx6502.supportsExecute=false
|
||||
group.cxx6502.licenseLink=https://github.com/lefticus/6502-cpp/blob/master/LICENSE
|
||||
group.cxx6502.licenseName=The Unlicense
|
||||
group.cxx6502.licensePreamble=This is free and unencumbered software released into the public domain.
|
||||
group.cxx6502.compilerCategories=gcc
|
||||
group.cxx6502.instructionSet=6502
|
||||
|
||||
compiler.gcc6502_1110.exe=/opt/compiler-explorer/6502-c++-trunk/bin/6502-c++
|
||||
compiler.gcc6502_1110.semver=11.1.0
|
||||
@@ -2042,6 +2067,7 @@ group.nvcxx_x86_cxx.demanglerType=nvhpc
|
||||
group.nvcxx_x86_cxx.groupName=nvc++ x86
|
||||
group.nvcxx_x86_cxx.baseName=x86 nvc++
|
||||
group.nvcxx_x86_cxx.isSemVer=true
|
||||
group.nvcxx_x86_cxx.compilerCategories=nvc++
|
||||
|
||||
compiler.nvcxx_x86_cxx22_7.demangler=/opt/compiler-explorer/hpc_sdk/Linux_x86_64/22.7/compilers/bin/nvdecode
|
||||
compiler.nvcxx_x86_cxx22_7.exe=/opt/compiler-explorer/hpc_sdk/Linux_x86_64/22.7/compilers/bin/nvc++
|
||||
@@ -2069,6 +2095,7 @@ group.nvcxx_arm_cxx.groupName=nvc++ arm
|
||||
group.nvcxx_arm_cxx.baseName=ARM64 nvc++
|
||||
group.nvcxx_arm_cxx.isSemVer=true
|
||||
group.nvcxx_arm_cxx.instructionSet=aarch64
|
||||
group.nvcxx_arm_cxx.compilerCategories=nvc++
|
||||
|
||||
compiler.nvcxx_arm_cxx22_7.demangler=/opt/compiler-explorer/hpc_sdk/Linux_aarch64/22.7/compilers/bin/nvdecode
|
||||
compiler.nvcxx_arm_cxx22_7.exe=/opt/compiler-explorer/hpc_sdk/Linux_aarch64/22.7/compilers/bin/nvc++
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
compilers=&gcc:&clang
|
||||
|
||||
group.gcc.compilers=g44:g45:g46:g47:g48:g5:g6x:g7:g8:g9:g10:g11:gdefault
|
||||
group.gcc.compilerCategories=gcc
|
||||
compiler.g44.exe=/usr/bin/g++-4.4
|
||||
compiler.g44.name=g++ 4.4
|
||||
compiler.g45.exe=/usr/bin/g++-4.5
|
||||
@@ -33,6 +34,7 @@ compiler.gdefault.name=g++ default
|
||||
group.clang.compilers=clang7:clang8:clang9:clang10:clang11:clang12:clangdefault
|
||||
group.clang.intelAsm=-mllvm --x86-asm-syntax=intel
|
||||
group.clang.compilerType=clang
|
||||
group.clang.compilerCategories=clang
|
||||
compiler.clang7.exe=/usr/bin/clang++-7
|
||||
compiler.clang7.name=clang 7
|
||||
compiler.clang8.exe=/usr/bin/clang++-8
|
||||
|
||||
@@ -23,6 +23,7 @@ group.cgcc86.supportsPVS-Studio=true
|
||||
group.cgcc86.licenseLink=https://gcc.gnu.org/onlinedocs/gcc/Copying.html
|
||||
group.cgcc86.licenseName=GNU General Public License
|
||||
group.cgcc86.licensePreamble=Copyright (c) 2007 Free Software Foundation, Inc. <a href="https://fsf.org/" target="_blank">https://fsf.org/</a>
|
||||
group.cgcc86.compilerCategories=gcc
|
||||
|
||||
compiler.cg412.exe=/opt/compiler-explorer/gcc-4.1.2/bin/gcc
|
||||
compiler.cg412.semver=4.1.2
|
||||
@@ -149,6 +150,8 @@ group.cgcc-classic.supportsExecute=false
|
||||
group.cgcc-classic.supportsBinary=false
|
||||
group.cgcc-classic.licenseName=GNU CC GENERAL PUBLIC LICENSE (Clarified 11 Feb 1988)
|
||||
group.cgcc-classic.supportsBinaryObject=true
|
||||
group.cgcc-classic.compilerCategories=gcc
|
||||
group.cgcc-classic.instructionSet=amd64
|
||||
compiler.cg127.exe=/opt/compiler-explorer/gcc-1.27/bin/gcc
|
||||
compiler.cg127.semver=1.27
|
||||
|
||||
@@ -165,6 +168,7 @@ group.cclang.supportsPVS-Studio=true
|
||||
group.cclang.licenseName=LLVM Apache 2
|
||||
group.cclang.licenseLink=https://github.com/llvm/llvm-project/blob/main/LICENSE.TXT
|
||||
group.cclang.licensePreamble=The LLVM Project is under the Apache License v2.0 with LLVM Exceptions
|
||||
group.cclang.compilerCategories=clang
|
||||
|
||||
compiler.cclang30.exe=/opt/compiler-explorer/clang+llvm-3.0-x86_64-linux-Ubuntu-11_10/bin/clang
|
||||
compiler.cclang30.semver=3.0.0
|
||||
@@ -297,6 +301,7 @@ group.armcclang32.instructionSet=arm32
|
||||
group.armcclang32.licenseName=LLVM Apache 2
|
||||
group.armcclang32.licenseLink=https://github.com/llvm/llvm-project/blob/main/LICENSE.TXT
|
||||
group.armcclang32.licensePreamble=The LLVM Project is under the Apache License v2.0 with LLVM Exceptions
|
||||
group.armcclang32.compilerCategories=clang
|
||||
|
||||
group.armcclang64.groupName=Arm 64-bit clang
|
||||
group.armcclang64.compilers=armv8-cclang900:armv8-cclang901:armv8-cclang1000:armv8-cclang1001:armv8-cclang1100:armv8-cclang1101:armv8-cclang1200:armv8-cclang1201:armv8-cclang1300:armv8-cclang1301:armv8-cclang1400:armv8-cclang1500:armv8-cclang-trunk:armv8-full-cclang-trunk
|
||||
@@ -307,7 +312,7 @@ group.armcclang64.instructionSet=aarch64
|
||||
group.armcclang64.licenseName=LLVM Apache 2
|
||||
group.armcclang64.licenseLink=https://github.com/llvm/llvm-project/blob/main/LICENSE.TXT
|
||||
group.armcclang64.licensePreamble=The LLVM Project is under the Apache License v2.0 with LLVM Exceptions
|
||||
|
||||
group.armcclang64.compilerCategories=clang
|
||||
|
||||
compiler.armv7-cclang1500.name=armv7-a clang 15.0.0
|
||||
compiler.armv7-cclang1500.exe=/opt/compiler-explorer/clang-15.0.0/bin/clang
|
||||
@@ -512,6 +517,7 @@ group.cmosclang-trunk.compilerType=llvmmos
|
||||
group.cmosclang-trunk.isSemVer=true
|
||||
group.cmosclang-trunk.objdumper=/opt/compiler-explorer/llvm-mos-trunk/bin/llvm-objdump
|
||||
group.cmosclang-trunk.objdumperType=llvm
|
||||
group.cmosclang-trunk.compilerCategories=clang
|
||||
|
||||
compiler.cmos-nes-cnrom-trunk.exe=/opt/compiler-explorer/llvm-mos-trunk/bin/mos-nes-cnrom-clang
|
||||
compiler.cmos-nes-cnrom-trunk.semver=nes-cnrom
|
||||
@@ -551,6 +557,7 @@ group.rvcclang.isSemVer=true
|
||||
group.rvcclang.licenseName=LLVM Apache 2
|
||||
group.rvcclang.licenseLink=https://github.com/llvm/llvm-project/blob/main/LICENSE.TXT
|
||||
group.rvcclang.licensePreamble=The LLVM Project is under the Apache License v2.0 with LLVM Exceptions
|
||||
group.rvcclang.compilerCategories=clang
|
||||
|
||||
group.rv32cclang.compilers=rv32-cclang:rv32-cclang1500:rv32-cclang1400:rv32-cclang1301:rv32-cclang1300:rv32-cclang1200:rv32-cclang1201:rv32-cclang1101:rv32-cclang1100:rv32-cclang1001:rv32-cclang1000:rv32-cclang901:rv32-cclang900
|
||||
group.rv32cclang.options=-target riscv32-unknown-elf -march=rv32gc -mabi=ilp32d --gcc-toolchain=/opt/compiler-explorer/riscv32/gcc-10.2.0/riscv32-unknown-elf
|
||||
@@ -560,6 +567,7 @@ group.rv32cclang.groupName=RISC-V 32 Clang
|
||||
group.rv32cclang.licenseName=LLVM Apache 2
|
||||
group.rv32cclang.licenseLink=https://github.com/llvm/llvm-project/blob/main/LICENSE.TXT
|
||||
group.rv32cclang.licensePreamble=The LLVM Project is under the Apache License v2.0 with LLVM Exceptions
|
||||
group.rv32cclang.compilerCategories=clang
|
||||
|
||||
compiler.rv32-cclang900.exe=/opt/compiler-explorer/clang-9.0.0/bin/clang
|
||||
compiler.rv32-cclang900.semver=9.0.0
|
||||
@@ -602,6 +610,7 @@ group.rv64cclang.options=-target riscv64-unknown-linux-gnu -march=rv64gc -mabi=l
|
||||
group.rv64cclang.objdumper=/opt/compiler-explorer/riscv64/gcc-8.2.0/riscv64-unknown-linux-gnu/bin/riscv64-unknown-linux-gnu-objdump
|
||||
group.rv64cclang.baseName=RISC-V rv64gc clang
|
||||
group.rv64cclang.groupName=RISC-V 64 Clang
|
||||
group.rv64cclang.compilerCategories=clang
|
||||
|
||||
compiler.rv64-cclang900.semver=9.0.0
|
||||
compiler.rv64-cclang900.exe=/opt/compiler-explorer/clang-9.0.0/bin/clang
|
||||
@@ -648,6 +657,7 @@ group.wasmcclang.supportsBinaryObject=false
|
||||
group.wasmcclang.licenseName=LLVM Apache 2
|
||||
group.wasmcclang.licenseLink=https://github.com/llvm/llvm-project/blob/main/LICENSE.TXT
|
||||
group.wasmcclang.licensePreamble=The LLVM Project is under the Apache License v2.0 with LLVM Exceptions
|
||||
group.wasmcclang.compilerCategories=clang
|
||||
|
||||
compiler.wasm32cclang.exe=/opt/compiler-explorer/clang-trunk/bin/clang
|
||||
compiler.wasm32cclang.demangler=/opt/compiler-explorer/gcc-snapshot/bin/c++filt
|
||||
@@ -677,6 +687,8 @@ group.cicc.options=-x c -gcc-name=/opt/compiler-explorer/gcc-4.7.1/bin/gcc
|
||||
group.cicc.groupName=ICC x86-64
|
||||
group.cicc.isSemVer=true
|
||||
group.cicc.baseName=x86-64 icc
|
||||
group.cicc.compilerCategories=icc
|
||||
group.cicc.instructionSet=amd64
|
||||
compiler.cicc1301.exe=/opt/compiler-explorer/intel/bin/icc
|
||||
compiler.cicc1301.semver=13.0.1
|
||||
# intel 13.01 binary disabled: it just segfaults (no idea why)
|
||||
@@ -754,6 +766,8 @@ group.cicx.groupName=ICX x86-64
|
||||
group.cicx.baseName=x86-64 icx
|
||||
group.cicx.isSemVer=true
|
||||
group.cicx.compilerType=clang-intel
|
||||
group.cicx.compilerCategories=icc
|
||||
group.cicx.instructionSet=amd64
|
||||
|
||||
compiler.cicx202112.exe=/opt/compiler-explorer/intel-cpp-2021.1.2.63/compiler/latest/linux/bin/icx
|
||||
compiler.cicx202112.ldPath=/opt/compiler-explorer/intel-cpp-2021.1.2.63/compiler/latest/linux/compiler/lib/intel64_lin:/opt/compiler-explorer/intel-cpp-2021.1.2.63/compiler/latest/linux/lib
|
||||
@@ -812,6 +826,7 @@ group.ccross.groupName=Cross GCC
|
||||
group.ccross.licenseLink=https://gcc.gnu.org/onlinedocs/gcc/Copying.html
|
||||
group.ccross.licenseName=GNU General Public License
|
||||
group.ccross.licensePreamble=Copyright (c) 2007 Free Software Foundation, Inc. <a href="https://fsf.org/" target="_blank">https://fsf.org/</a>
|
||||
group.ccross.compilerCategories=gcc
|
||||
|
||||
###############################
|
||||
# Cross for BPF
|
||||
@@ -1166,7 +1181,7 @@ compiler.carm1031_07.supportsBinary=false
|
||||
compiler.carm1031_10.exe=/opt/compiler-explorer/arm/gcc-arm-none-eabi-10.3-2021.10/bin/arm-none-eabi-gcc
|
||||
compiler.carm1031_10.name=ARM gcc 10.3.1 (2021.10 none)
|
||||
compiler.carm1031_10.semver=10.3.1
|
||||
compiler.carm1031_10.supportsBinary=false
|
||||
compiler.carm1031_10.supportsBinary=false
|
||||
compiler.carm1121.exe=/opt/compiler-explorer/arm/gcc-arm-none-eabi-11.2-2022.02/bin/arm-none-eabi-gcc
|
||||
compiler.carm1121.name=ARM gcc 11.2.1 (none)
|
||||
compiler.carm1121.semver=11.2.1
|
||||
@@ -1867,6 +1882,8 @@ group.ccl.versionRe=^Microsoft \(R\) C/C\+\+.*$
|
||||
group.ccl.isSemVer=true
|
||||
group.ccl.supportsBinary=false
|
||||
group.ccl.objdumper=
|
||||
group.ccl.compilerCategories=msvc
|
||||
group.ccl.instructionSet=amd64
|
||||
group.ccl19.groupName=WINE MSVC 2017
|
||||
group.ccl19.compilers=ccl19_64:ccl19_32:ccl19_arm
|
||||
group.ccl19.options=/I/opt/compiler-explorer/windows/10.0.10240.0/ucrt/ /I/opt/compiler-explorer/windows/19.10.25017/lib/native/include/ /TC
|
||||
@@ -1879,7 +1896,7 @@ compiler.ccl19_32.semver=19.10.25017
|
||||
compiler.ccl19_arm.exe=/opt/compiler-explorer/windows/19.10.25017/lib/native/bin/amd64_arm/cl.exe
|
||||
compiler.ccl19_arm.name=ARM msvc v19.10 (WINE)
|
||||
compiler.ccl19_arm.semver=19.10.25017
|
||||
compiler.ccl19_arm.instructionSet=arm
|
||||
compiler.ccl19_arm.instructionSet=arm32
|
||||
|
||||
group.ccl19_2015_u3.groupName=WINE MSVC 2015
|
||||
group.ccl19_2015_u3.compilers=ccl19_2015_u3_64:ccl19_2015_u3_32:ccl19_2015_u3_arm
|
||||
@@ -1893,7 +1910,7 @@ compiler.ccl19_2015_u3_32.semver=19.00.24210
|
||||
compiler.ccl19_2015_u3_arm.exe=/opt/compiler-explorer/windows/19.00.24210/bin/amd64_arm/cl.exe
|
||||
compiler.ccl19_2015_u3_arm.name=ARM msvc v19.0 (WINE)
|
||||
compiler.ccl19_2015_u3_arm.semver=19.00.24210
|
||||
compiler.ccl19_2015_u3_arm.instructionSet=arm
|
||||
compiler.ccl19_2015_u3_arm.instructionSet=arm32
|
||||
|
||||
group.ccl_new.groupName=WINE MSVC 2017
|
||||
group.ccl_new.compilers=ccl_new_64:ccl_new_32:ccl_new_arm32:ccl_new_arm64
|
||||
|
||||
@@ -37,6 +37,11 @@ export function unique<V>(arr: V[]): V[] {
|
||||
return [...new Set(arr)];
|
||||
}
|
||||
|
||||
export function intersection<V>(a: V[], b: V[]): V[] {
|
||||
const B = new Set(b);
|
||||
return [...a].filter(item => B.has(item));
|
||||
}
|
||||
|
||||
// arr.filter(x => x !== null) returns a (T | null)[] even though it is a T[]
|
||||
// Apparently the idiomatic solution is arr.filter((x): x is T => x !== null), but this is shorter (and the type
|
||||
// predicate also isn't type checked so it doesn't seem safe to me)
|
||||
|
||||
@@ -261,6 +261,7 @@ export class CompilerFinder {
|
||||
versionRe: props<string>('versionRe'),
|
||||
explicitVersion: props<string>('explicitVersion'),
|
||||
compilerType: props('compilerType', ''),
|
||||
compilerCategories: props<string | undefined>('compilerCategories', undefined)?.split(':'),
|
||||
debugPatched: props('debugPatched', false),
|
||||
demangler: demangler,
|
||||
demanglerType: props('demanglerType', ''),
|
||||
@@ -269,7 +270,7 @@ export class CompilerFinder {
|
||||
objdumperType: props('objdumperType', ''),
|
||||
intelAsm: props('intelAsm', ''),
|
||||
supportsAsmDocs: props('supportsAsmDocs', true),
|
||||
instructionSet: props('instructionSet', ''),
|
||||
instructionSet: props<string | number>('instructionSet', '').toString(),
|
||||
needsMulti: !!props('needsMulti', true),
|
||||
adarts: props('adarts', ''),
|
||||
supportsDemangle: !!demangler,
|
||||
|
||||
20
package-lock.json
generated
20
package-lock.json
generated
@@ -15,6 +15,7 @@
|
||||
"@aws-sdk/client-ssm": "^3.282.0",
|
||||
"@flatten-js/interval-tree": "^1.0.20",
|
||||
"@fortawesome/fontawesome-free": "^6.2.1",
|
||||
"@orchidjs/sifter": "^1.0.3",
|
||||
"@sentry/browser": "^7.28.1",
|
||||
"@sentry/node": "^7.28.1",
|
||||
"@types/morgan": "^1.9.4",
|
||||
@@ -2991,9 +2992,17 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@orchidjs/sifter": {
|
||||
"version": "0.9.3",
|
||||
"resolved": "https://registry.npmjs.org/@orchidjs/sifter/-/sifter-0.9.3.tgz",
|
||||
"integrity": "sha512-9XGiAJcWvEektxjR9X+dYeG+kg8GdojM6ZCmrnuDaWoVew+GAKxiesvYxyY+RLUgWTv8B1qpLIVYlswxKcW5XQ=="
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/@orchidjs/sifter/-/sifter-1.0.3.tgz",
|
||||
"integrity": "sha512-zCZbwKegHytfsPm8Amcfh7v/4vHqTAaOu6xFswBYcn8nznBOuseu6COB2ON7ez0tFV0mKL0nRNnCiZZA+lU9/g==",
|
||||
"dependencies": {
|
||||
"@orchidjs/unicode-variants": "^1.0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/@orchidjs/unicode-variants": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/@orchidjs/unicode-variants/-/unicode-variants-1.0.4.tgz",
|
||||
"integrity": "sha512-NvVBRnZNE+dugiXERFsET1JlKZfM5lJDEpSMilKW4bToYJ7pxf0Zne78xyXB2ny2c2aHfJ6WLnz1AaTNHAmQeQ=="
|
||||
},
|
||||
"node_modules/@pkgr/utils": {
|
||||
"version": "2.3.1",
|
||||
@@ -15356,6 +15365,11 @@
|
||||
"url": "https://opencollective.com/tom-select"
|
||||
}
|
||||
},
|
||||
"node_modules/tom-select/node_modules/@orchidjs/sifter": {
|
||||
"version": "0.9.3",
|
||||
"resolved": "https://registry.npmjs.org/@orchidjs/sifter/-/sifter-0.9.3.tgz",
|
||||
"integrity": "sha512-9XGiAJcWvEektxjR9X+dYeG+kg8GdojM6ZCmrnuDaWoVew+GAKxiesvYxyY+RLUgWTv8B1qpLIVYlswxKcW5XQ=="
|
||||
},
|
||||
"node_modules/tough-cookie": {
|
||||
"version": "2.5.0",
|
||||
"resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz",
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
"@aws-sdk/client-ssm": "^3.282.0",
|
||||
"@flatten-js/interval-tree": "^1.0.20",
|
||||
"@fortawesome/fontawesome-free": "^6.2.1",
|
||||
"@orchidjs/sifter": "^1.0.3",
|
||||
"@sentry/browser": "^7.28.1",
|
||||
"@sentry/node": "^7.28.1",
|
||||
"@types/morgan": "^1.9.4",
|
||||
|
||||
@@ -27,9 +27,9 @@ rules:
|
||||
- error
|
||||
- smart
|
||||
indent:
|
||||
- error
|
||||
- 4
|
||||
- SwitchCase: 1
|
||||
- off
|
||||
#- 4
|
||||
#- SwitchCase: 1
|
||||
max-len:
|
||||
- error
|
||||
- 120
|
||||
|
||||
81
static/highlight.ts
Normal file
81
static/highlight.ts
Normal file
@@ -0,0 +1,81 @@
|
||||
// Copyright (c) 2023, Compiler Explorer Authors
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
type Interval = {start: number; length: number};
|
||||
|
||||
function regexExecAll(base_re: RegExp, s: string) {
|
||||
const re = new RegExp(base_re.source, base_re.flags + 'gd');
|
||||
let m: any;
|
||||
const matches: Interval[] = [];
|
||||
while ((m = re.exec(s)) != null) {
|
||||
// TODO(jeremy-rifkin): Find a way to get TS to understand that m.indices is real
|
||||
matches.push({
|
||||
start: m.indices[0][0],
|
||||
length: m.indices[0][1] - m.indices[0][0],
|
||||
});
|
||||
}
|
||||
return matches;
|
||||
}
|
||||
|
||||
export function highlight(str: string, regexes: RegExp[]) {
|
||||
// At the moment, because compiler names are short, I think this solution is best. It's easiest to just
|
||||
// track intervals with an array. The ideal solution in the general case is probably something along the
|
||||
// lines of an interval tree.
|
||||
const intervals: Interval[] = [];
|
||||
for (const regex of regexes) {
|
||||
intervals.push(...regexExecAll(regex, str));
|
||||
}
|
||||
// sort by interval start
|
||||
intervals.sort((a, b) => a.start - b.start);
|
||||
// combine intervals
|
||||
let i = 0;
|
||||
while (i < intervals.length - 1) {
|
||||
const {start: AStart, length: ALength} = intervals[i];
|
||||
const {start: BStart, length: BLength} = intervals[i + 1];
|
||||
if (AStart + ALength >= BStart) {
|
||||
intervals.splice(i, 2, {
|
||||
start: AStart,
|
||||
length: BStart + BLength - AStart,
|
||||
});
|
||||
} else {
|
||||
i++;
|
||||
}
|
||||
}
|
||||
// for each interval, highlight
|
||||
let offset = 0;
|
||||
for (const {start, length} of intervals) {
|
||||
const tagStart = '<span class="highlight">';
|
||||
const tagEnd = '</span>';
|
||||
const intervalStart = offset + start;
|
||||
const intervalEnd = offset + start + length;
|
||||
str =
|
||||
str.slice(0, intervalStart) +
|
||||
tagStart +
|
||||
str.slice(intervalStart, intervalEnd) +
|
||||
tagEnd +
|
||||
str.slice(intervalEnd);
|
||||
offset += tagStart.length + tagEnd.length;
|
||||
}
|
||||
return str;
|
||||
}
|
||||
@@ -234,7 +234,8 @@ export class Compiler extends MonacoPane<monaco.editor.IStandaloneCodeEditor, Co
|
||||
private linkedFadeTimeoutId: NodeJS.Timeout | null;
|
||||
private toolsMenu: JQuery<HTMLElement> | null;
|
||||
private revealJumpStack: (monaco.editor.ICodeEditorViewState | null)[];
|
||||
private compilerPicker: CompilerPicker | JQuery<HTMLElement>;
|
||||
private compilerPickerElement: JQuery<HTMLElement>;
|
||||
private compilerPicker: CompilerPicker;
|
||||
private compiler: CompilerInfo | null;
|
||||
private currentLangId: string | null;
|
||||
private filters: Toggles;
|
||||
@@ -470,6 +471,7 @@ export class Compiler extends MonacoPane<monaco.editor.IStandaloneCodeEditor, Co
|
||||
this.eventHub.unsubscribe();
|
||||
this.eventHub.emit('compilerClose', this.id, this.sourceTreeId ?? 0);
|
||||
this.editor.dispose();
|
||||
this.compilerPicker.destroy();
|
||||
}
|
||||
|
||||
onCompiler(compilerId: number, compiler: unknown, options: string, editorId: number, treeId: number): void {}
|
||||
@@ -2353,7 +2355,7 @@ export class Compiler extends MonacoPane<monaco.editor.IStandaloneCodeEditor, Co
|
||||
this.optionsField.val(this.options);
|
||||
|
||||
this.shortCompilerName = this.domRoot.find('.short-compiler-name');
|
||||
this.compilerPicker = this.domRoot.find('.compiler-picker');
|
||||
this.compilerPickerElement = this.domRoot.find('.compiler-picker');
|
||||
this.setCompilerVersionPopover({version: '', fullVersion: ''}, '');
|
||||
|
||||
this.topBar = this.domRoot.find('.top-bar');
|
||||
|
||||
@@ -339,7 +339,7 @@ export class Conformance extends Pane<ConformanceViewState> {
|
||||
this.compilerPickers = _.reject(this.compilerPickers, function (entry) {
|
||||
return compilerEntry.picker?.id === entry.picker?.id;
|
||||
});
|
||||
compilerEntry.picker?.tomSelect?.close();
|
||||
compilerEntry.picker?.destroy();
|
||||
compilerEntry.parent.remove();
|
||||
|
||||
this.updateLibraries();
|
||||
@@ -596,7 +596,7 @@ export class Conformance extends Pane<ConformanceViewState> {
|
||||
override close(): void {
|
||||
this.eventHub.unsubscribe();
|
||||
this.compilerPickers.forEach(compilerEntry => {
|
||||
compilerEntry.picker?.tomSelect?.close();
|
||||
compilerEntry.picker?.destroy();
|
||||
compilerEntry.parent.remove();
|
||||
});
|
||||
if (this.compilerInfo.editorId) this.eventHub.emit('conformanceViewClose', this.compilerInfo.editorId);
|
||||
|
||||
@@ -284,7 +284,7 @@ export class Executor extends Pane<ExecutorState> {
|
||||
close(): void {
|
||||
this.eventHub.unsubscribe();
|
||||
if (this.compilerPicker instanceof CompilerPicker) {
|
||||
this.compilerPicker.close();
|
||||
this.compilerPicker.destroy();
|
||||
}
|
||||
|
||||
this.eventHub.emit('executorClose', this.id);
|
||||
|
||||
@@ -547,12 +547,12 @@ input.vim-check {
|
||||
height: 20px;
|
||||
}
|
||||
|
||||
/* While we find a better solution, lets up this a bit */
|
||||
.compiler-picker .ts-dropdown-content {
|
||||
max-height: 300px !important;
|
||||
.compiler-picker-dropdown .ts-dropdown-content {
|
||||
// Default max-height, the compiler picker will override this to prevent overflowing the window
|
||||
max-height: 600px;
|
||||
}
|
||||
|
||||
.compiler-picker .ts-dropdown-content .option {
|
||||
.compiler-picker-dropdown .ts-dropdown-content .option {
|
||||
padding: 0 10px;
|
||||
}
|
||||
|
||||
@@ -834,6 +834,105 @@ div.populararguments div.dropdown-menu {
|
||||
display: none;
|
||||
}
|
||||
|
||||
@media (max-width: 830px) {
|
||||
#compiler-picker-modal {
|
||||
.compilers-row {
|
||||
flex-direction: column-reverse;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 1200px) {
|
||||
#compiler-picker-modal {
|
||||
.compilers-col {
|
||||
.compilers {
|
||||
width: 300px !important;
|
||||
columns: 1 300px !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#compiler-picker-modal {
|
||||
.modal-body {
|
||||
overflow-y: scroll;
|
||||
}
|
||||
|
||||
input.compiler-search {
|
||||
margin-left: 10px;
|
||||
//outline: 0 !important;
|
||||
padding: 5px 10px;
|
||||
}
|
||||
|
||||
.filters {
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.architecture,
|
||||
.compiler-type {
|
||||
padding: 2px 5px;
|
||||
border-radius: 3px;
|
||||
margin: 0 0 0 3px;
|
||||
cursor: pointer;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.compilers-col {
|
||||
margin-top: 5px;
|
||||
h6 {
|
||||
margin-top: 15px;
|
||||
font-size: 16px;
|
||||
}
|
||||
.compilers {
|
||||
width: 650px;
|
||||
columns: 2 300px;
|
||||
column-gap: 40px;
|
||||
&.one-col {
|
||||
width: 300px;
|
||||
columns: 1 300px;
|
||||
}
|
||||
}
|
||||
.favorites {
|
||||
margin-left: 10px;
|
||||
}
|
||||
.compilers,
|
||||
.favorites {
|
||||
.group-wrapper {
|
||||
display: inline-block;
|
||||
.group {
|
||||
width: 300px;
|
||||
margin-bottom: 25px;
|
||||
.label {
|
||||
cursor: pointer;
|
||||
}
|
||||
.compiler {
|
||||
cursor: pointer;
|
||||
.highlight {
|
||||
background: rgba(255, 237, 40, 0.4);
|
||||
border-radius: 1px;
|
||||
}
|
||||
.toggle-fav {
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
.folded {
|
||||
display: none;
|
||||
text-align: center;
|
||||
}
|
||||
&.collapsed {
|
||||
.compiler {
|
||||
display: none !important;
|
||||
}
|
||||
.folded {
|
||||
display: block !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#timing-info .modal-content {
|
||||
min-width: 500px;
|
||||
min-height: 400px;
|
||||
@@ -939,11 +1038,35 @@ html[data-theme='dark'] {
|
||||
overflow-y: scroll;
|
||||
}
|
||||
|
||||
.prepend-options {
|
||||
.prepend-options,
|
||||
.picker-popout-button {
|
||||
border-top-right-radius: 0;
|
||||
border-bottom-right-radius: 0;
|
||||
}
|
||||
|
||||
.picker-popout-button {
|
||||
font-size: 14px;
|
||||
line-height: 14px;
|
||||
position: relative;
|
||||
i {
|
||||
vertical-align: middle;
|
||||
}
|
||||
}
|
||||
|
||||
.compiler-picker-dropdown-popout-wrapper {
|
||||
text-align: center;
|
||||
cursor: pointer;
|
||||
font-size: 15px;
|
||||
position: absolute;
|
||||
top: 100%;
|
||||
background: inherit;
|
||||
box-shadow: rgba(0, 0, 0, 0.176) 0px 6px 12px 0px; // same as the tomselect dropdown
|
||||
left: 0;
|
||||
.compiler-picker-dropdown-popout {
|
||||
padding: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
.popular-arguments-btn {
|
||||
border-top-right-radius: 0;
|
||||
}
|
||||
|
||||
@@ -507,6 +507,14 @@ textarea.form-control {
|
||||
background-color: #353535 !important;
|
||||
}
|
||||
|
||||
.picker-popout-button {
|
||||
border: none !important;
|
||||
background: #444444 !important;
|
||||
&:hover {
|
||||
background: darken(#444444, 5%) !important;
|
||||
}
|
||||
}
|
||||
|
||||
.qb-logo-pri {
|
||||
fill: #e2e2e2 !important;
|
||||
}
|
||||
@@ -622,6 +630,30 @@ textarea.form-control {
|
||||
}
|
||||
}
|
||||
|
||||
#compiler-picker-modal {
|
||||
.architecture,
|
||||
.compiler-type {
|
||||
background: #444;
|
||||
&.active {
|
||||
background: #007bff;
|
||||
}
|
||||
}
|
||||
|
||||
.compilers-col .group-wrapper .group {
|
||||
.label {
|
||||
background: #555555;
|
||||
}
|
||||
.compiler {
|
||||
&:hover {
|
||||
background: #8d8d8e;
|
||||
}
|
||||
&.selected {
|
||||
background: #21525f;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#alert {
|
||||
&.error-alert {
|
||||
.modal-content {
|
||||
|
||||
@@ -278,6 +278,11 @@ kbd {
|
||||
background-color: #e9ecef;
|
||||
}
|
||||
|
||||
.picker-popout-button {
|
||||
background-color: #fff;
|
||||
border-left: none;
|
||||
}
|
||||
|
||||
#simplecook {
|
||||
background-color: #f4f4f4;
|
||||
}
|
||||
@@ -410,6 +415,31 @@ div.argmenuitem span.argdescription {
|
||||
}
|
||||
}
|
||||
|
||||
#compiler-picker-modal {
|
||||
.architecture,
|
||||
.compiler-type {
|
||||
background: #eeeeee;
|
||||
&.active {
|
||||
background: #3c9aff;
|
||||
}
|
||||
}
|
||||
|
||||
.compilers-col .group-wrapper .group {
|
||||
.label {
|
||||
// taking the color tom-select uses, but I find that a little low-contrast
|
||||
background: darken(#f6f6f6, 3%);
|
||||
}
|
||||
.compiler {
|
||||
&:hover {
|
||||
background: #e9ecef;
|
||||
}
|
||||
&.selected {
|
||||
background: #e9ecef;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#alert {
|
||||
&.error-alert {
|
||||
.modal-content {
|
||||
|
||||
269
static/widgets/compiler-picker-popup.ts
Normal file
269
static/widgets/compiler-picker-popup.ts
Normal file
@@ -0,0 +1,269 @@
|
||||
// Copyright (c) 2023, Compiler Explorer Authors
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
import $ from 'jquery';
|
||||
import _ from 'underscore';
|
||||
|
||||
import * as sifter from '@orchidjs/sifter';
|
||||
|
||||
import {CompilerInfo} from '../../types/compiler.interfaces';
|
||||
import {intersection, remove, unique} from '../../lib/common-utils';
|
||||
import {unwrap, unwrapString} from '../assert';
|
||||
import {CompilerPicker} from './compiler-picker';
|
||||
import {CompilerService} from '../compiler-service';
|
||||
import {highlight} from '../highlight';
|
||||
|
||||
export class CompilerPickerPopup {
|
||||
modal: JQuery<HTMLElement>;
|
||||
searchBar: JQuery<HTMLElement>;
|
||||
architectures: JQuery<HTMLElement>;
|
||||
compilerTypes: JQuery<HTMLElement>;
|
||||
compilersContainer: JQuery<HTMLElement>;
|
||||
resultsContainer: JQuery<HTMLElement>;
|
||||
favoritesContainer: JQuery<HTMLElement>;
|
||||
|
||||
groups: {value: string; label: string}[];
|
||||
options: (CompilerInfo & {$groups: string[]})[];
|
||||
langId: string;
|
||||
|
||||
isaFilters: string[];
|
||||
categoryFilters: string[];
|
||||
|
||||
sifter: sifter.Sifter;
|
||||
searchResults: ReturnType<sifter.Sifter['search']> | undefined;
|
||||
|
||||
constructor(private readonly compilerPicker: CompilerPicker) {
|
||||
this.modal = $('#compiler-picker-modal').clone(true);
|
||||
this.searchBar = this.modal.find('.compiler-search');
|
||||
this.architectures = this.modal.find('.architectures');
|
||||
this.compilerTypes = this.modal.find('.compiler-types');
|
||||
this.compilersContainer = this.modal.find('.compilers-row');
|
||||
this.resultsContainer = this.modal.find('.compilers');
|
||||
this.favoritesContainer = this.modal.find('.favorites');
|
||||
|
||||
this.modal.on('shown.bs.modal', () => {
|
||||
this.searchBar[0].focus();
|
||||
});
|
||||
}
|
||||
|
||||
setLang(groups: {value: string; label: string}[], options: (CompilerInfo & {$groups: string[]})[], langId: string) {
|
||||
this.groups = groups;
|
||||
this.options = options;
|
||||
this.langId = langId;
|
||||
this.setupFilters();
|
||||
this.sifter = new sifter.Sifter(options, {
|
||||
diacritics: false,
|
||||
});
|
||||
}
|
||||
|
||||
setupFilters() {
|
||||
// get available instruction sets
|
||||
const compilers = Object.values(this.compilerPicker.compilerService.getCompilersForLang(this.langId) ?? {});
|
||||
// If instructionSet is '', just label it unknown
|
||||
const instruction_sets = compilers.map(compiler => compiler.instructionSet || 'other');
|
||||
this.architectures.empty();
|
||||
this.architectures.append(
|
||||
...unique(instruction_sets)
|
||||
.sort()
|
||||
.map(isa => `<span class="architecture" data-value=${_.escape(isa)}>${_.escape(isa)}</span>`),
|
||||
);
|
||||
// get available compiler types
|
||||
const compilerTypes = compilers.map(compiler => compiler.compilerCategories ?? ['other']).flat();
|
||||
this.compilerTypes.empty();
|
||||
this.compilerTypes.append(
|
||||
...unique(compilerTypes)
|
||||
.sort()
|
||||
.map(type => `<span class="compiler-type" data-value=${_.escape(type)}>${_.escape(type)}</span>`),
|
||||
);
|
||||
|
||||
// search box
|
||||
this.searchBar.on('input', () => {
|
||||
const query = unwrapString(this.searchBar.val()).trim();
|
||||
if (query === '') {
|
||||
this.searchResults = undefined;
|
||||
} else {
|
||||
this.searchResults = this.sifter.search(query, {
|
||||
fields: ['name'],
|
||||
conjunction: 'and',
|
||||
sort: CompilerService.getSelectizerOrder(),
|
||||
});
|
||||
}
|
||||
this.fillCompilers();
|
||||
});
|
||||
|
||||
// isa filters
|
||||
$(this.architectures)
|
||||
.find('.architecture')
|
||||
.on('click', e => this.onFilterClick(e, this.isaFilters));
|
||||
|
||||
// category filters
|
||||
$(this.compilerTypes)
|
||||
.find('.compiler-type')
|
||||
.on('click', e => this.onFilterClick(e, this.categoryFilters));
|
||||
}
|
||||
|
||||
onFilterClick(e: JQuery.ClickEvent, filtersArray: string[]) {
|
||||
e.preventDefault();
|
||||
const elem = $(e.currentTarget);
|
||||
elem.toggleClass('active');
|
||||
const filterValue = unwrap(elem.attr('data-value'));
|
||||
if (filtersArray.includes(filterValue)) {
|
||||
// This is pretty much the best way to filter an array in-place
|
||||
filtersArray.splice(0, filtersArray.length, ...filtersArray.filter(v => v !== filterValue));
|
||||
} else {
|
||||
filtersArray.push(filterValue);
|
||||
}
|
||||
this.fillCompilers();
|
||||
}
|
||||
|
||||
fillCompilers() {
|
||||
const filteredIndices = this.searchResults
|
||||
? new Set(this.searchResults.items.map(item => item.id as number))
|
||||
: undefined;
|
||||
const filteredCompilers = this.options.filter((compiler, i) => {
|
||||
if (this.isaFilters.length > 0) {
|
||||
if (!this.isaFilters.includes(compiler.instructionSet || 'other')) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (this.categoryFilters.length > 0) {
|
||||
const categories = compiler.compilerCategories ?? ['other'];
|
||||
if (intersection(this.categoryFilters, categories).length === 0) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (filteredIndices) {
|
||||
if (!filteredIndices.has(i)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
});
|
||||
// figure out if there are any empty groups, these will be ignored
|
||||
const groupCounts: Partial<Record<string, number>> = {};
|
||||
for (const compiler of filteredCompilers) {
|
||||
for (const group of compiler.$groups) {
|
||||
groupCounts[group] = (groupCounts[group] ?? 0) + 1;
|
||||
}
|
||||
}
|
||||
// add the compiler entries / group headers themselves
|
||||
this.resultsContainer.empty();
|
||||
this.favoritesContainer.empty();
|
||||
const groupMap: Record<string, JQuery> = {};
|
||||
for (const group of this.groups) {
|
||||
if ((groupCounts[group.value] ?? 0) > 0 || group.value === CompilerPicker.favoriteGroupName) {
|
||||
const group_elem = $(
|
||||
`
|
||||
<div class="group-wrapper">
|
||||
<div class="group">
|
||||
<div class="label">${_.escape(group.label)}</div>
|
||||
</div>
|
||||
</div>
|
||||
`,
|
||||
);
|
||||
if (group.value === CompilerPicker.favoriteGroupName) {
|
||||
group_elem.appendTo(this.favoritesContainer);
|
||||
} else {
|
||||
group_elem.appendTo(this.resultsContainer);
|
||||
}
|
||||
groupMap[group.value] = group_elem.find('.group');
|
||||
}
|
||||
}
|
||||
// if there can only ever be one column, don't bother with room for 2
|
||||
this.resultsContainer.toggleClass(
|
||||
'one-col',
|
||||
this.groups.filter(group => group.value !== CompilerPicker.favoriteGroupName).length <= 1,
|
||||
);
|
||||
const searchRegexes = this.searchResults
|
||||
? remove(
|
||||
this.searchResults.tokens.map(token => token.regex),
|
||||
null,
|
||||
)
|
||||
: undefined;
|
||||
for (const compiler of filteredCompilers) {
|
||||
const isFavorited = compiler.$groups.includes(CompilerPicker.favoriteGroupName);
|
||||
const extraClasses = isFavorited ? 'fas fa-star fav' : 'far fa-star';
|
||||
for (const group of compiler.$groups) {
|
||||
// TODO(jeremy-rifkin): At the moment none of our compiler names should contain html special characters.
|
||||
// This is just a good measure to take. If a compiler is ever added that does have special characters in
|
||||
// its name it could interfere with the highlighting (e.g. if your text search is for "<" that won't
|
||||
// highlight). I'm going to defer handling that to a future PR though.
|
||||
const name = _.escape(compiler.name);
|
||||
const compiler_elem = $(
|
||||
`
|
||||
<div class="compiler d-flex" data-value="${compiler.id}">
|
||||
<div>${searchRegexes ? highlight(name, searchRegexes) : name}</div>
|
||||
<div title="Click to mark or unmark as a favorite" class="ml-auto toggle-fav">
|
||||
<i class="${extraClasses}"></i>
|
||||
</div>
|
||||
</div>
|
||||
`,
|
||||
);
|
||||
if (compiler.id === this.compilerPicker.lastCompilerId) {
|
||||
compiler_elem.addClass('selected');
|
||||
}
|
||||
compiler_elem.appendTo(groupMap[group]);
|
||||
}
|
||||
}
|
||||
// group header click events
|
||||
this.compilersContainer.find('.group').append('<div class="folded">⋯</div>');
|
||||
this.compilersContainer.find('.group > .label').on('click', e => {
|
||||
$(e.currentTarget).closest('.group').toggleClass('collapsed');
|
||||
});
|
||||
// compiler click events
|
||||
this.compilersContainer.find('.compiler').on('click', e => {
|
||||
this.compilerPicker.selectCompiler(unwrap(e.currentTarget.getAttribute('data-value')));
|
||||
this.hide();
|
||||
});
|
||||
// favorite stars
|
||||
this.compilersContainer.find('.compiler .toggle-fav').on('click', e => {
|
||||
const compilerId = unwrap($(e.currentTarget).closest('.compiler').attr('data-value'));
|
||||
const data = filteredCompilers.filter(c => c.id === compilerId)[0];
|
||||
const isAddingNewFavorite = !data.$groups.includes(CompilerPicker.favoriteGroupName);
|
||||
if (isAddingNewFavorite) {
|
||||
data.$groups.push(CompilerPicker.favoriteGroupName);
|
||||
this.compilerPicker.addToFavorites(data.id);
|
||||
} else {
|
||||
data.$groups.splice(data.$groups.indexOf(CompilerPicker.favoriteGroupName), 1);
|
||||
this.compilerPicker.removeFromFavorites(data.id);
|
||||
}
|
||||
this.fillCompilers();
|
||||
});
|
||||
}
|
||||
|
||||
show() {
|
||||
// reflow the compilers to get any new favorites from the compiler picker dropdown and reset filters and whatnot
|
||||
this.isaFilters = [];
|
||||
this.categoryFilters = [];
|
||||
this.searchBar.val('');
|
||||
this.searchBar.trigger('input');
|
||||
this.modal.find('.architectures .active, .compiler-types .active').toggleClass('active');
|
||||
this.fillCompilers();
|
||||
this.modal.modal({});
|
||||
}
|
||||
|
||||
hide() {
|
||||
this.modal.modal('hide');
|
||||
}
|
||||
}
|
||||
@@ -30,6 +30,10 @@ import * as local from '../local.js';
|
||||
import {EventHub} from '../event-hub.js';
|
||||
import {Hub} from '../hub.js';
|
||||
import {CompilerService} from '../compiler-service.js';
|
||||
import {CompilerInfo} from '../../types/compiler.interfaces.js';
|
||||
import {unique} from '../../lib/common-utils.js';
|
||||
import {unwrap} from '../assert.js';
|
||||
import {CompilerPickerPopup} from './compiler-picker-popup.js';
|
||||
|
||||
type Favourites = {
|
||||
[compilerId: string]: boolean;
|
||||
@@ -39,7 +43,6 @@ export class CompilerPicker {
|
||||
static readonly favoriteGroupName = '__favorites__';
|
||||
static readonly favoriteStoreKey = 'favCompilerIds';
|
||||
static nextSelectorId = 1;
|
||||
domRoot: JQuery;
|
||||
domNode: HTMLSelectElement;
|
||||
eventHub: EventHub;
|
||||
id: number;
|
||||
@@ -49,6 +52,9 @@ export class CompilerPicker {
|
||||
lastLangId: string;
|
||||
lastCompilerId: string;
|
||||
compilerIsVisible: (any) => any; // TODO => bool probably
|
||||
popup: CompilerPickerPopup;
|
||||
toolbarPopoutButton: JQuery<HTMLElement>;
|
||||
popupTooltip: JQuery<HTMLElement>;
|
||||
constructor(
|
||||
domRoot: JQuery,
|
||||
hub: Hub,
|
||||
@@ -63,6 +69,11 @@ export class CompilerPicker {
|
||||
if (!(compilerPicker instanceof HTMLSelectElement)) {
|
||||
throw new Error('.compiler-picker is not an HTMLSelectElement');
|
||||
}
|
||||
this.toolbarPopoutButton = domRoot.find('.picker-popout-button');
|
||||
domRoot.find('.picker-popout-button').on('click', () => {
|
||||
unwrap(this.tomSelect).close();
|
||||
this.popup.show();
|
||||
});
|
||||
this.domNode = compilerPicker;
|
||||
this.compilerService = hub.compilerService;
|
||||
this.onCompilerChange = onCompilerChange;
|
||||
@@ -74,22 +85,24 @@ export class CompilerPicker {
|
||||
this.compilerIsVisible = () => true;
|
||||
}
|
||||
|
||||
this.popup = new CompilerPickerPopup(this);
|
||||
|
||||
this.initialize(langId, compilerId);
|
||||
}
|
||||
|
||||
close() {
|
||||
// Quick note while I'm here: This function is never called. It probably should be. The conformance view
|
||||
// bypasses this function and does compilerEntry.picker.tomSelect.close(); manually. This function is the
|
||||
// only time this.tomSelect can be null, might be nice if we can get rid of that.
|
||||
destroy() {
|
||||
this.eventHub.unsubscribe();
|
||||
if (this.tomSelect) this.tomSelect.destroy();
|
||||
this.tomSelect = null;
|
||||
}
|
||||
|
||||
initialize(langId: string, compilerId: string) {
|
||||
private initialize(langId: string, compilerId: string) {
|
||||
this.lastLangId = langId;
|
||||
this.lastCompilerId = compilerId;
|
||||
|
||||
const groups = this.getGroups(langId);
|
||||
const options = this.getOptions(langId, compilerId);
|
||||
|
||||
this.tomSelect = new TomSelect(this.domNode, {
|
||||
sortField: CompilerService.getSelectizerOrder(),
|
||||
valueField: 'id',
|
||||
@@ -97,9 +110,9 @@ export class CompilerPicker {
|
||||
searchField: ['name'],
|
||||
placeholder: '🔍 Select a compiler...',
|
||||
optgroupField: '$groups',
|
||||
optgroups: this.getGroups(langId),
|
||||
optgroups: groups,
|
||||
lockOptgroupOrder: true,
|
||||
options: this.getOptions(langId, compilerId),
|
||||
options: options,
|
||||
items: compilerId ? [compilerId] : [],
|
||||
dropdownParent: 'body',
|
||||
closeAfterSelect: true,
|
||||
@@ -110,14 +123,14 @@ export class CompilerPicker {
|
||||
// Typing here needs improvement later anyway.
|
||||
/* eslint-disable-next-line @typescript-eslint/no-unnecessary-condition */
|
||||
if (val) {
|
||||
const compilerId = val as any as string;
|
||||
ga.proxy('send', {
|
||||
hitType: 'event',
|
||||
eventCategory: 'SelectCompiler',
|
||||
eventAction: val,
|
||||
eventAction: compilerId,
|
||||
});
|
||||
const str = val as any as string;
|
||||
this.onCompilerChange(str);
|
||||
this.lastCompilerId = str;
|
||||
this.onCompilerChange(compilerId);
|
||||
this.lastCompilerId = compilerId;
|
||||
}
|
||||
},
|
||||
duplicates: true,
|
||||
@@ -140,6 +153,32 @@ export class CompilerPicker {
|
||||
},
|
||||
});
|
||||
|
||||
this.tomSelect.on('dropdown_open', () => {
|
||||
// Prevent overflowing the window
|
||||
const dropdown = unwrap(this.tomSelect).dropdown_content;
|
||||
dropdown.style.maxHeight = `${window.innerHeight - dropdown.getBoundingClientRect().top - 10}px`;
|
||||
|
||||
this.popupTooltip = $(`
|
||||
<div class="compiler-picker-dropdown-popout-wrapper">
|
||||
<div class="compiler-picker-dropdown-popout">
|
||||
<i class="fa-solid fa-arrow-up-right-from-square"></i> Pop Out
|
||||
</div>
|
||||
</div>
|
||||
`);
|
||||
// I think tomselect is stealing the click event here. Somehow tomselect's global onclick prevents a click
|
||||
// here from firing, maybe related to the dropdown closing and this getting removed from the dom. But,
|
||||
// mousedown is a decent workaround.
|
||||
this.popupTooltip.on('mousedown', () => {
|
||||
unwrap(this.tomSelect).close();
|
||||
this.popup.show();
|
||||
});
|
||||
this.popupTooltip.appendTo(this.toolbarPopoutButton);
|
||||
});
|
||||
|
||||
this.tomSelect.on('dropdown_close', () => {
|
||||
this.popupTooltip.remove();
|
||||
});
|
||||
|
||||
$(this.tomSelect.dropdown_content).on('click', '.toggle-fav', evt => {
|
||||
evt.preventDefault();
|
||||
evt.stopPropagation();
|
||||
@@ -156,13 +195,10 @@ export class CompilerPicker {
|
||||
data.$groups.push(CompilerPicker.favoriteGroupName);
|
||||
this.addToFavorites(data.id);
|
||||
} else {
|
||||
data.$groups.splice(data.group.indexOf(CompilerPicker.favoriteGroupName), 1);
|
||||
data.$groups.splice(data.$groups.indexOf(CompilerPicker.favoriteGroupName), 1);
|
||||
this.removeFromFavorites(data.id);
|
||||
}
|
||||
|
||||
this.tomSelect.updateOption(value, data);
|
||||
this.tomSelect.refreshOptions(false);
|
||||
|
||||
if (clickedGroup !== CompilerPicker.favoriteGroupName) {
|
||||
// If the user clicked on an option that wasn't in the top "Favorite" group, then we just added
|
||||
// or removed a bunch of controls way up in the list. Find the new element top and adjust the scroll
|
||||
@@ -175,16 +211,21 @@ export class CompilerPicker {
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
this.popup.setLang(groups, options, langId);
|
||||
}
|
||||
|
||||
getOptions(langId: string, compilerId: string) {
|
||||
getOptions(langId: string, compilerId: string): (CompilerInfo & {$groups: string[]})[] {
|
||||
const favorites = this.getFavorites();
|
||||
return Object.values(this.compilerService.getCompilersForLang(langId) ?? {})
|
||||
.filter(e => (this.compilerIsVisible(e) && !e.hidden) || e.id === compilerId)
|
||||
.map(e => {
|
||||
e.$groups = [e.group];
|
||||
if (favorites[e.id]) e.$groups.unshift(CompilerPicker.favoriteGroupName);
|
||||
return e;
|
||||
const $groups = [e.group];
|
||||
if (favorites[e.id]) $groups.unshift(CompilerPicker.favoriteGroupName);
|
||||
return {
|
||||
...e,
|
||||
$groups,
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
@@ -225,6 +266,7 @@ export class CompilerPicker {
|
||||
const faves = this.getFavorites();
|
||||
faves[compilerId] = true;
|
||||
this.setFavorites(faves);
|
||||
this.updateTomselectOption(compilerId);
|
||||
this.eventHub.emit('compilerFavoriteChange', this.id);
|
||||
}
|
||||
|
||||
@@ -232,6 +274,20 @@ export class CompilerPicker {
|
||||
const faves = this.getFavorites();
|
||||
delete faves[compilerId];
|
||||
this.setFavorites(faves);
|
||||
this.updateTomselectOption(compilerId);
|
||||
this.eventHub.emit('compilerFavoriteChange', this.id);
|
||||
}
|
||||
|
||||
updateTomselectOption(compilerId: string) {
|
||||
if (this.tomSelect) {
|
||||
this.tomSelect.updateOption(compilerId, this.tomSelect.options[compilerId]);
|
||||
this.tomSelect.refreshOptions(false);
|
||||
}
|
||||
}
|
||||
|
||||
selectCompiler(compilerId: string) {
|
||||
if (this.tomSelect) {
|
||||
this.tomSelect.addItem(compilerId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,6 +40,9 @@ export type CompilerInfo = {
|
||||
versionRe?: string;
|
||||
explicitVersion?: string;
|
||||
compilerType: string;
|
||||
// groups are more fine-grained, e.g. gcc x86-64, gcc arm, clang x86-64, ...
|
||||
// category is more broad: gcc, clang, msvc, ...
|
||||
compilerCategories?: string[];
|
||||
debugPatched: boolean;
|
||||
demangler: string;
|
||||
demanglerType: string;
|
||||
@@ -79,7 +82,6 @@ export type CompilerInfo = {
|
||||
lang: LanguageKey;
|
||||
group: string;
|
||||
groupName: string;
|
||||
$groups: string[];
|
||||
includeFlag: string;
|
||||
includePath: string;
|
||||
linkFlag: string;
|
||||
@@ -123,10 +125,9 @@ export type CompilerInfo = {
|
||||
};
|
||||
|
||||
// Compiler information collected by the compiler-finder
|
||||
export type PreliminaryCompilerInfo = Omit<
|
||||
CompilerInfo,
|
||||
'version' | 'fullVersion' | 'baseName' | '$groups' | 'disabledFilters'
|
||||
> & {version?: string};
|
||||
export type PreliminaryCompilerInfo = Omit<CompilerInfo, 'version' | 'fullVersion' | 'baseName' | 'disabledFilters'> & {
|
||||
version?: string;
|
||||
};
|
||||
|
||||
export interface ICompiler {
|
||||
possibleArguments: ICompilerArguments;
|
||||
|
||||
@@ -2,6 +2,8 @@ include load-save
|
||||
|
||||
include alert
|
||||
|
||||
include compiler-picker-modal
|
||||
|
||||
include yes-no
|
||||
|
||||
include enter-something
|
||||
|
||||
32
views/popups/compiler-picker-modal.pug
Normal file
32
views/popups/compiler-picker-modal.pug
Normal file
@@ -0,0 +1,32 @@
|
||||
#compiler-picker-modal.modal.fade.gl_keep(tabindex="-1" role="dialog")
|
||||
.modal-dialog.modal-lg
|
||||
.modal-content
|
||||
.modal-header
|
||||
h5.modal-title Compilers
|
||||
button.close(type="button" data-dismiss="modal" aria-hidden="true" aria-label="Close")
|
||||
span(aria-hidden="true")
|
||||
| ×
|
||||
.modal-body
|
||||
.card
|
||||
.card-body
|
||||
.container
|
||||
.row
|
||||
.col-lg
|
||||
div.filters Filter:
|
||||
input.compiler-search(value="" placeholder="🔍 Search for a compiler...")
|
||||
.row
|
||||
.col-lg
|
||||
div.filters Instruction Sets:
|
||||
span.architectures
|
||||
.row
|
||||
.col-lg
|
||||
div.filters Categories:
|
||||
span.compiler-types
|
||||
.row
|
||||
.compilers-col.col-md
|
||||
h6 Results
|
||||
.row.compilers-row
|
||||
.col-md
|
||||
.compilers
|
||||
.col-md
|
||||
.favorites
|
||||
@@ -10,6 +10,10 @@ mixin newPaneButton(classId, text, title, icon)
|
||||
.input-group-prepend
|
||||
.input-group
|
||||
select.compiler-picker
|
||||
.input-group-append
|
||||
button.btn.btn-sm.btn-light.input-group-text.picker-popout-button(data-trigger="click" style="cursor: pointer;" role="button" title="Compiler picker popout")
|
||||
span
|
||||
i.fa-solid.fa-arrow-up-right-from-square
|
||||
.input-group-append
|
||||
button.btn.btn-sm.btn-light.input-group-text.prepend-options(data-trigger="click" style="cursor: pointer;" role="button" title="All compilation options")
|
||||
span.status-icon
|
||||
|
||||
@@ -29,6 +29,10 @@
|
||||
.input-group-prepend
|
||||
.input-group
|
||||
select.compiler-picker
|
||||
.input-group-append
|
||||
button.btn.btn-sm.btn-light.input-group-text.picker-popout-button(data-trigger="click" style="cursor: pointer;" role="button" title="Compiler picker popout")
|
||||
span
|
||||
i.fa-solid.fa-arrow-up-right-from-square
|
||||
.input-group-append
|
||||
button.btn.btn-sm.btn-light.input-group-text.prepend-options(data-trigger="click" style="cursor: pointer;" role="button" title="All compilation options")
|
||||
span.btn.btn-sm.btn-light.status-icon
|
||||
|
||||
@@ -4,6 +4,10 @@
|
||||
.input-group-prepend
|
||||
.input-group
|
||||
select.compiler-picker
|
||||
.input-group-append
|
||||
button.btn.btn-sm.btn-light.input-group-text.picker-popout-button(data-trigger="click" style="cursor: pointer;" role="button" title="Compiler picker popout")
|
||||
span
|
||||
i.fa-solid.fa-arrow-up-right-from-square
|
||||
.input-group-append
|
||||
button.btn.btn-sm.btn-light.input-group-text.prepend-options(tabindex="0" data-trigger="focus" style="cursor: pointer;" role="button" title="All compilation options")
|
||||
span.btn.btn-sm.btn-light.status-icon
|
||||
|
||||
Reference in New Issue
Block a user